1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.integration.beans;
21
22 import java.beans.PropertyEditor;
23 import java.util.Collection;
24 import java.util.LinkedHashMap;
25 import java.util.Map;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29
30
31
32
33
34
35 public class MapEditor extends AbstractPropertyEditor {
36 static final Pattern ELEMENT = Pattern.compile("([,\\s]+)|"
37 +
38 "(\\s*=\\s*)|"
39 +
40 "(?<=\")((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^\"])*)(?=\")|"
41 + "(?<=')((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^'])*)(?=')|" + "((?:[^\\\\\\s'\",]|\\\\ |\\\\\"|\\\\')+)");
42
43 private final Class<?> keyType;
44
45 private final Class<?> valueType;
46
47 public MapEditor(Class<?> keyType, Class<?> valueType) {
48 if (keyType == null) {
49 throw new IllegalArgumentException("keyType");
50 }
51 if (valueType == null) {
52 throw new IllegalArgumentException("valueType");
53 }
54 this.keyType = keyType;
55 this.valueType = valueType;
56 getKeyEditor();
57 getValueEditor();
58 setTrimText(false);
59 }
60
61 private PropertyEditor getKeyEditor() {
62 PropertyEditor e = PropertyEditorFactory.getInstance(keyType);
63 if (e == null) {
64 throw new IllegalArgumentException("No key " + PropertyEditor.class.getSimpleName() + " found for "
65 + keyType.getSimpleName() + '.');
66 }
67 return e;
68 }
69
70 private PropertyEditor getValueEditor() {
71 PropertyEditor e = PropertyEditorFactory.getInstance(valueType);
72 if (e == null) {
73 throw new IllegalArgumentException("No value " + PropertyEditor.class.getSimpleName() + " found for "
74 + valueType.getSimpleName() + '.');
75 }
76 return e;
77 }
78
79 @Override
80 @SuppressWarnings("unchecked")
81 protected final String toText(Object value) {
82 StringBuilder buf = new StringBuilder();
83 for (Object o : ((Map) value).entrySet()) {
84 Map.Entry entry = (Map.Entry) o;
85 Object ekey = entry.getKey();
86 Object evalue = entry.getValue();
87
88 PropertyEditor ekeyEditor = PropertyEditorFactory.getInstance(ekey);
89 if (ekeyEditor == null) {
90 throw new IllegalArgumentException("No key " + PropertyEditor.class.getSimpleName() + " found for "
91 + ekey.getClass().getSimpleName() + '.');
92 }
93 ekeyEditor.setValue(ekey);
94
95 PropertyEditor evalueEditor = PropertyEditorFactory.getInstance(evalue);
96 if (evalueEditor == null) {
97 throw new IllegalArgumentException("No value " + PropertyEditor.class.getSimpleName() + " found for "
98 + evalue.getClass().getSimpleName() + '.');
99 }
100 ekeyEditor.setValue(ekey);
101 evalueEditor.setValue(evalue);
102
103
104 String keyString = ekeyEditor.getAsText();
105 String valueString = evalueEditor.getAsText();
106 buf.append(keyString);
107 buf.append(" = ");
108 buf.append(valueString);
109 buf.append(", ");
110 }
111
112
113 if (buf.length() >= 2) {
114 buf.setLength(buf.length() - 2);
115 }
116 return buf.toString();
117 }
118
119 @Override
120 protected final Object toValue(String text) throws IllegalArgumentException {
121 PropertyEditor keyEditor = getKeyEditor();
122 PropertyEditor valueEditor = getValueEditor();
123 Map<Object, Object> answer = newMap();
124 Matcher m = ELEMENT.matcher(text);
125 TokenType lastTokenType = TokenType.ENTRY_DELIM;
126 Object key = null;
127 Object value = null;
128
129 while (m.find()) {
130 if (m.group(1) != null) {
131 switch (lastTokenType) {
132 case VALUE:
133 case ENTRY_DELIM:
134 break;
135 default:
136 throw new IllegalArgumentException("Unexpected entry delimiter: " + text);
137 }
138
139 lastTokenType = TokenType.ENTRY_DELIM;
140 continue;
141 }
142
143 if (m.group(2) != null) {
144 if (lastTokenType != TokenType.KEY) {
145 throw new IllegalArgumentException("Unexpected key-value delimiter: " + text);
146 }
147
148 lastTokenType = TokenType.KEY_VALUE_DELIM;
149 continue;
150 }
151
152
153 String region = m.group();
154
155 if (m.group(3) != null || m.group(4) != null) {
156
157 m.region(m.end() + 1, m.regionEnd());
158 }
159
160 switch (lastTokenType) {
161 case ENTRY_DELIM:
162 keyEditor.setAsText(region);
163 key = keyEditor.getValue();
164 lastTokenType = TokenType.KEY;
165 break;
166 case KEY_VALUE_DELIM:
167 valueEditor.setAsText(region);
168 value = valueEditor.getValue();
169 lastTokenType = TokenType.VALUE;
170 answer.put(key, value);
171 break;
172 case KEY:
173 case VALUE:
174 throw new IllegalArgumentException("Unexpected key or value: " + text);
175 }
176 }
177
178 return answer;
179 }
180
181 protected Map<Object, Object> newMap() {
182 return new LinkedHashMap<Object, Object>();
183 }
184
185 private static enum TokenType {
186 ENTRY_DELIM, KEY_VALUE_DELIM, KEY, VALUE,
187 }
188 }