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
36 public class MapEditor extends AbstractPropertyEditor {
37 static final Pattern ELEMENT = Pattern.compile(
38 "([,\\s]+)|" +
39 "(\\s*=\\s*)|" +
40 "(?<=\")((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^\"])*)(?=\")|" +
41 "(?<=')((?:\\\\\"|\\\\'|\\\\\\\\|\\\\ |[^'])*)(?=')|" +
42 "((?:[^\\\\\\s'\",]|\\\\ |\\\\\"|\\\\')+)");
43
44 private final Class<?> keyType;
45 private final Class<?> valueType;
46
47 public MapEditor(Class<?> keyType, Class<?> valueType) {
48 if (keyType == null) {
49 throw new NullPointerException("keyType");
50 }
51 if (valueType == null) {
52 throw new NullPointerException("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(
65 "No key " + PropertyEditor.class.getSimpleName() +
66 " found for " + keyType.getSimpleName() + '.');
67 }
68 return e;
69 }
70
71 private PropertyEditor getValueEditor() {
72 PropertyEditor e = PropertyEditorFactory.getInstance(valueType);
73 if (e == null) {
74 throw new IllegalArgumentException(
75 "No value " + PropertyEditor.class.getSimpleName() +
76 " found for " + valueType.getSimpleName() + '.');
77 }
78 return e;
79 }
80
81 @Override
82 @SuppressWarnings("unchecked")
83 protected final String toText(Object value) {
84 StringBuilder buf = new StringBuilder();
85 for (Object o: ((Map) value).entrySet()) {
86 Map.Entry entry = (Map.Entry) o;
87 Object ekey = entry.getKey();
88 Object evalue = entry.getValue();
89
90 PropertyEditor ekeyEditor = PropertyEditorFactory.getInstance(ekey);
91 if (ekeyEditor == null) {
92 throw new IllegalArgumentException(
93 "No key " + PropertyEditor.class.getSimpleName() +
94 " found for " + ekey.getClass().getSimpleName() + '.');
95 }
96 ekeyEditor.setValue(ekey);
97
98 PropertyEditor evalueEditor = PropertyEditorFactory.getInstance(evalue);
99 if (evalueEditor == null) {
100 throw new IllegalArgumentException(
101 "No value " + PropertyEditor.class.getSimpleName() +
102 " found for " + evalue.getClass().getSimpleName() + '.');
103 }
104 ekeyEditor.setValue(ekey);
105 evalueEditor.setValue(evalue);
106
107
108 String keyString = ekeyEditor.getAsText();
109 String valueString = evalueEditor.getAsText();
110 buf.append(keyString);
111 buf.append(" = ");
112 buf.append(valueString);
113 buf.append(", ");
114 }
115
116
117 if (buf.length() >= 2) {
118 buf.setLength(buf.length() - 2);
119 }
120 return buf.toString();
121 }
122
123 @Override
124 protected final Object toValue(String text) throws IllegalArgumentException {
125 PropertyEditor keyEditor = getKeyEditor();
126 PropertyEditor valueEditor = getValueEditor();
127 Map<Object, Object> answer = newMap();
128 Matcher m = ELEMENT.matcher(text);
129 TokenType lastTokenType = TokenType.ENTRY_DELIM;
130 Object key = null;
131 Object value = null;
132
133 while (m.find()) {
134 if (m.group(1) != null) {
135 switch (lastTokenType) {
136 case VALUE: case ENTRY_DELIM:
137 break;
138 default:
139 throw new IllegalArgumentException(
140 "Unexpected entry delimiter: " + text);
141 }
142
143 lastTokenType = TokenType.ENTRY_DELIM;
144 continue;
145 }
146
147 if (m.group(2) != null) {
148 if (lastTokenType != TokenType.KEY) {
149 throw new IllegalArgumentException(
150 "Unexpected key-value delimiter: " + text);
151 }
152
153 lastTokenType = TokenType.KEY_VALUE_DELIM;
154 continue;
155 }
156
157
158
159 String region = m.group();
160
161 if (m.group(3) != null || m.group(4) != null) {
162
163 m.region(m.end() + 1, m.regionEnd());
164 }
165
166 switch (lastTokenType) {
167 case ENTRY_DELIM:
168 keyEditor.setAsText(region);
169 key = keyEditor.getValue();
170 lastTokenType = TokenType.KEY;
171 break;
172 case KEY_VALUE_DELIM:
173 valueEditor.setAsText(region);
174 value = valueEditor.getValue();
175 lastTokenType = TokenType.VALUE;
176 answer.put(key, value);
177 break;
178 case KEY: case VALUE:
179 throw new IllegalArgumentException(
180 "Unexpected key or value: " + text);
181 }
182 }
183
184 return answer;
185 }
186
187 protected Map<Object, Object> newMap() {
188 return new LinkedHashMap<Object, Object>();
189 }
190
191 private static enum TokenType {
192 ENTRY_DELIM,
193 KEY_VALUE_DELIM,
194 KEY,
195 VALUE,
196 }
197 }