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