View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.integration.beans;
21  
22  import java.beans.PropertyEditor;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.regex.Matcher;
26  import java.util.regex.Pattern;
27  
28  /**
29   * A {@link PropertyEditor} which converts a {@link String} into
30   * a {@link Collection} and vice versa.
31   *
32   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
33   */
34  public class CollectionEditor extends AbstractPropertyEditor {
35      static final Pattern ELEMENT = Pattern.compile("([,\\s]+)|"
36              + // Delimiter
37              "(?<=\")((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^\"])*)(?=\")|"
38              + "(?<=')((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^'])*)(?=')|" + "((?:[^\\\\\\s'\",]|\\\\ |\\\\\"|\\\\')+)");
39  
40      private final Class<?> elementType;
41  
42      /**
43       * Creates a new CollectionEditor instance
44       * 
45       * @param elementType The Element type
46       */
47      public CollectionEditor(Class<?> elementType) {
48          if (elementType == null) {
49              throw new IllegalArgumentException("elementType");
50          }
51  
52          this.elementType = elementType;
53          getElementEditor();
54          setTrimText(false);
55      }
56  
57      private PropertyEditor getElementEditor() {
58          PropertyEditor e = PropertyEditorFactory.getInstance(elementType);
59          if (e == null) {
60              throw new IllegalArgumentException("No " + PropertyEditor.class.getSimpleName() + " found for "
61                      + elementType.getSimpleName() + '.');
62          }
63          return e;
64      }
65  
66      /**
67       * {@inheritDoc}
68       */
69      @Override
70      protected final String toText(Object value) {
71          StringBuilder buf = new StringBuilder();
72          
73          for (Object v : (Collection<?>) value) {
74              if (v == null) {
75                  v = defaultElement();
76              }
77  
78              PropertyEditor e = PropertyEditorFactory.getInstance(v);
79              
80              if (e == null) {
81                  throw new IllegalArgumentException("No " + PropertyEditor.class.getSimpleName() + " found for "
82                          + v.getClass().getSimpleName() + '.');
83              }
84              
85              e.setValue(v);
86              // TODO normalize.
87              String s = e.getAsText();
88              buf.append(s);
89              buf.append(", ");
90          }
91  
92          // Remove the last delimiter.
93          if (buf.length() >= 2) {
94              buf.setLength(buf.length() - 2);
95          }
96          
97          return buf.toString();
98      }
99  
100     /**
101      * {@inheritDoc}
102      */
103     @Override
104     protected final Object toValue(String text) throws IllegalArgumentException {
105         PropertyEditor e = getElementEditor();
106         Collection<Object> answer = newCollection();
107         Matcher m = ELEMENT.matcher(text);
108         boolean matchedDelimiter = true;
109 
110         while (m.find()) {
111             if (m.group(1) != null) {
112                 matchedDelimiter = true;
113                 continue;
114             }
115 
116             if (!matchedDelimiter) {
117                 throw new IllegalArgumentException("No delimiter between elements: " + text);
118             }
119 
120             // TODO escape here.
121             e.setAsText(m.group());
122             answer.add(e.getValue());
123 
124             matchedDelimiter = false;
125             
126             if (m.group(2) != null || m.group(3) != null) {
127                 // Skip the last '"'.
128                 m.region(m.end() + 1, m.regionEnd());
129             }
130         }
131 
132         return answer;
133     }
134 
135     protected Collection<Object> newCollection() {
136         return new ArrayList<>();
137     }
138 
139     protected Object defaultElement() {
140         PropertyEditor e = PropertyEditorFactory.getInstance(elementType);
141         
142         if (e == null) {
143             return null;
144         }
145 
146         if (e instanceof AbstractPropertyEditor) {
147             return ((AbstractPropertyEditor) e).defaultValue();
148         }
149 
150         return null;
151     }
152 }