001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.mina.integration.beans;
021
022import java.beans.PropertyEditor;
023import java.lang.reflect.Array;
024import java.util.ArrayList;
025import java.util.List;
026import java.util.regex.Matcher;
027
028/**
029 * A {@link PropertyEditor} which converts a {@link String} into
030 * a one-dimensional array and vice versa.
031 *
032 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
033 */
034public class ArrayEditor extends AbstractPropertyEditor {
035    private final Class<?> componentType;
036
037    public ArrayEditor(Class<?> componentType) {
038        if (componentType == null) {
039            throw new IllegalArgumentException("componentType");
040        }
041
042        this.componentType = componentType;
043        getComponentEditor();
044        setTrimText(false);
045    }
046
047    private PropertyEditor getComponentEditor() {
048        PropertyEditor e = PropertyEditorFactory.getInstance(componentType);
049        if (e == null) {
050            throw new IllegalArgumentException("No " + PropertyEditor.class.getSimpleName() + " found for "
051                    + componentType.getSimpleName() + '.');
052        }
053        return e;
054    }
055
056    @Override
057    protected String toText(Object value) {
058        Class<?> componentType = value.getClass().getComponentType();
059        if (componentType == null) {
060            throw new IllegalArgumentException("not an array: " + value);
061        }
062
063        PropertyEditor e = PropertyEditorFactory.getInstance(componentType);
064        if (e == null) {
065            throw new IllegalArgumentException("No " + PropertyEditor.class.getSimpleName() + " found for "
066                    + componentType.getSimpleName() + '.');
067        }
068
069        StringBuilder buf = new StringBuilder();
070        for (int i = 0; i < Array.getLength(value); i++) {
071            e.setValue(Array.get(value, i));
072            // TODO normalize.
073            String s = e.getAsText();
074            buf.append(s);
075            buf.append(", ");
076        }
077
078        // Remove the last delimiter.
079        if (buf.length() >= 2) {
080            buf.setLength(buf.length() - 2);
081        }
082        return buf.toString();
083    }
084
085    @Override
086    protected Object toValue(String text) throws IllegalArgumentException {
087        PropertyEditor e = getComponentEditor();
088        List<Object> values = new ArrayList<Object>();
089        Matcher m = CollectionEditor.ELEMENT.matcher(text);
090        boolean matchedDelimiter = true;
091
092        while (m.find()) {
093            if (m.group(1) != null) {
094                matchedDelimiter = true;
095                continue;
096            }
097
098            if (!matchedDelimiter) {
099                throw new IllegalArgumentException("No delimiter between elements: " + text);
100            }
101
102            // TODO escape here.
103            e.setAsText(m.group());
104            values.add(e.getValue());
105
106            matchedDelimiter = false;
107            if (m.group(2) != null || m.group(3) != null) {
108                // Skip the last '"'.
109                m.region(m.end() + 1, m.regionEnd());
110            }
111        }
112
113        Object answer = Array.newInstance(componentType, values.size());
114        for (int i = 0; i < Array.getLength(answer); i++) {
115            Array.set(answer, i, values.get(i));
116        }
117        return answer;
118    }
119}