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