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 The Apache MINA Project (dev@mina.apache.org)
33   * @version $Revision: 601229 $, $Date: 2007-12-05 08:13:18 +0100 (mer, 05 déc 2007) $
34   */
35  public class CollectionEditor extends AbstractPropertyEditor {
36      static final Pattern ELEMENT = Pattern.compile(
37              "([,\\s]+)|" + // Delimiter
38              "(?<=\")((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^\"])*)(?=\")|" +
39              "(?<=')((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^'])*)(?=')|" +
40              "((?:[^\\\\\\s'\",]|\\\\ |\\\\\"|\\\\')+)");
41      
42      private final Class<?> elementType;
43      
44      public CollectionEditor(Class<?> elementType) {
45          if (elementType == null) {
46              throw new NullPointerException("elementType");
47          }
48          
49          this.elementType = elementType;
50          getElementEditor();
51          setTrimText(false);
52      }
53  
54      private PropertyEditor getElementEditor() {
55          PropertyEditor e = PropertyEditorFactory.getInstance(elementType);
56          if (e == null) {
57              throw new IllegalArgumentException(
58                      "No " + PropertyEditor.class.getSimpleName() + 
59                      " found for " + elementType.getSimpleName() + '.');
60          }
61          return e;
62      }
63  
64      @Override
65      @SuppressWarnings("unchecked")
66      protected final String toText(Object value) {
67          StringBuilder buf = new StringBuilder();
68          for (Object v: (Collection) value) {
69              if (v == null) {
70                  v = defaultElement();
71              }
72              
73              PropertyEditor e = PropertyEditorFactory.getInstance(v);
74              if (e == null) {
75                  throw new IllegalArgumentException(
76                          "No " + PropertyEditor.class.getSimpleName() + 
77                          " found for " + v.getClass().getSimpleName() + '.');
78              }            
79              e.setValue(v);
80              // TODO normalize.
81              String s = e.getAsText();
82              buf.append(s);
83              buf.append(", ");
84          }
85          
86          // Remove the last delimiter.
87          if (buf.length() >= 2) {
88              buf.setLength(buf.length() - 2);
89          }
90          return buf.toString();
91      }
92  
93      @Override
94      protected final Object toValue(String text) throws IllegalArgumentException {
95          PropertyEditor e = getElementEditor();
96          Collection<Object> answer = newCollection();
97          Matcher m = ELEMENT.matcher(text);
98          boolean matchedDelimiter = true;
99  
100         while (m.find()) {
101             if (m.group(1) != null) {
102                 matchedDelimiter = true;
103                 continue;
104             }
105             
106             if (!matchedDelimiter) {
107                 throw new IllegalArgumentException("No delimiter between elements: " + text);
108             }
109 
110             // TODO escape here.
111             e.setAsText(m.group());
112             answer.add(e.getValue());
113             
114             matchedDelimiter = false;
115             if (m.group(2) != null || m.group(3) != null) {
116                 // Skip the last '"'.
117                 m.region(m.end() + 1, m.regionEnd());
118             }
119         }
120         
121         return answer;
122     }
123     
124     protected Collection<Object> newCollection() {
125         return new ArrayList<Object>();
126     }
127     
128     protected Object defaultElement() {
129         PropertyEditor e = PropertyEditorFactory.getInstance(elementType);
130         if (e == null) {
131             return null;
132         }
133         
134         if (e instanceof AbstractPropertyEditor) {
135             return ((AbstractPropertyEditor) e).defaultValue();
136         }
137 
138         return null;
139     }
140 }