blob: d11b6d1eb19a649f0c36150dfffe0d26548171ba [file] [log] [blame]
Stuart McCullochbb014372012-06-07 21:57:32 +00001package aQute.libg.header;
2
3import java.util.*;
4import java.util.regex.*;
5
6import aQute.lib.collections.*;
7import aQute.libg.version.*;
8
9public class Attrs implements Map<String, String> {
10 public enum Type {
11 STRING(null), LONG(null), VERSION(null), DOUBLE(null), STRINGS(STRING), LONGS(LONG), VERSIONS(VERSION), DOUBLES(DOUBLE);
12
13 Type sub;
14
15 Type(Type sub) {
16 this.sub = sub;
17 }
18
19 }
20
21 /**
22 * <pre>
23 * Provide-Capability ::= capability ::=
24 * name-space ::= typed-attr ::= type ::= scalar ::=
25 * capability ( ',' capability )*
26 * name-space
27 * ( ’;’ directive | typed-attr )*
28 * symbolic-name
29 * extended ( ’:’ type ) ’=’ argument
30 * scalar | list
31 * ’String’ | ’Version’ | ’Long’
32 * list ::=
33 * ’List<’ scalar ’>’
34 * </pre>
35 */
36 static String EXTENDED = "[\\-0-9a-zA-Z\\._]+";
37 static String SCALAR = "String|Version|Long|Double";
38 static String LIST = "List\\s*<\\s*(" + SCALAR + ")\\s*>";
39 public static final Pattern TYPED = Pattern.compile("\\s*(" + EXTENDED + ")\\s*:\\s*("+ SCALAR + "|" + LIST + ")\\s*");
40
41 private LinkedHashMap<String, String> map;
42 private Map<String, Type> types;
43 static Map<String, String> EMPTY = Collections.emptyMap();
44
45 public Attrs(Attrs... attrs) {
46 for (Attrs a : attrs) {
47 if (a != null) {
48 putAll(a);
49 }
50 }
51 }
52
53 public void clear() {
54 map.clear();
55 }
56
57 public boolean containsKey(String name) {
58 if (map == null)
59 return false;
60
61 return map.containsKey(name);
62 }
63
64 @SuppressWarnings("cast")
65 @Deprecated public boolean containsKey(Object name) {
66 assert name instanceof String;
67 if (map == null)
68 return false;
69
70 return map.containsKey((String) name);
71 }
72
73 public boolean containsValue(String value) {
74 if (map == null)
75 return false;
76
77 return map.containsValue(value);
78 }
79
80 @SuppressWarnings("cast")
81 @Deprecated public boolean containsValue(Object value) {
82 assert value instanceof String;
83 if (map == null)
84 return false;
85
86 return map.containsValue((String) value);
87 }
88
89 public Set<java.util.Map.Entry<String, String>> entrySet() {
90 if (map == null)
91 return EMPTY.entrySet();
92
93 return map.entrySet();
94 }
95
96 @SuppressWarnings("cast")
97 @Deprecated public String get(Object key) {
98 assert key instanceof String;
99 if (map == null)
100 return null;
101
102 return map.get((String) key);
103 }
104
105 public String get(String key) {
106 if (map == null)
107 return null;
108
109 return map.get(key);
110 }
111
112 public String get(String key, String deflt) {
113 String s = get(key);
114 if (s == null)
115 return deflt;
116 return s;
117 }
118
119 public boolean isEmpty() {
120 return map == null || map.isEmpty();
121 }
122
123 public Set<String> keySet() {
124 if (map == null)
125 return EMPTY.keySet();
126
127 return map.keySet();
128 }
129
130 public String put(String key, String value) {
131 if (map == null)
132 map = new LinkedHashMap<String, String>();
133
134 Matcher m = TYPED.matcher(key);
135 if (m.matches()) {
136 key = m.group(1);
137 String type = m.group(2);
138 Type t = Type.STRING;
139
140 if ( type.startsWith("List")) {
141 type = m.group(3);
142 if ( "String".equals(type))
143 t = Type.STRINGS;
144 else if ( "Long".equals(type))
145 t = Type.LONGS;
146 else if ( "Double".equals(type))
147 t = Type.DOUBLES;
148 else if ( "Version".equals(type))
149 t = Type.VERSIONS;
150 } else {
151 if ( "String".equals(type))
152 t = Type.STRING;
153 else if ( "Long".equals(type))
154 t = Type.LONG;
155 else if ( "Double".equals(type))
156 t = Type.DOUBLE;
157 else if ( "Version".equals(type))
158 t = Type.VERSION;
159 }
160 if (types == null)
161 types = new LinkedHashMap<String, Type>();
162 types.put(key, t);
163
164 // TODO verify value?
165 }
166
167 return map.put(key, value);
168 }
169
170 public Type getType(String key) {
171 if (types == null)
172 return Type.STRING;
173 Type t = types.get(key);
174 if (t == null)
175 return Type.STRING;
176 return t;
177 }
178
179 public void putAll(Map<? extends String, ? extends String> map) {
180 for (Map.Entry<? extends String, ? extends String> e : map.entrySet())
181 put(e.getKey(), e.getValue());
182 }
183
184 @SuppressWarnings("cast")
185 @Deprecated public String remove(Object var0) {
186 assert var0 instanceof String;
187 if (map == null)
188 return null;
189
190 return map.remove((String) var0);
191 }
192
193 public String remove(String var0) {
194 if (map == null)
195 return null;
196 return map.remove(var0);
197 }
198
199 public int size() {
200 if (map == null)
201 return 0;
202 return map.size();
203 }
204
205 public Collection<String> values() {
206 if (map == null)
207 return EMPTY.values();
208
209 return map.values();
210 }
211
212 public String getVersion() {
213 return get("version");
214 }
215
216 public String toString() {
217 StringBuilder sb = new StringBuilder();
218 append(sb);
219 return sb.toString();
220 }
221
222 public void append(StringBuilder sb) {
223 String del = "";
224 for (Map.Entry<String, String> e : entrySet()) {
225 sb.append(del);
226 sb.append(e.getKey());
227 sb.append("=");
228 sb.append(e.getValue());
229 del = ";";
230 }
231 }
232
233 @Deprecated public boolean equals(Object other) {
234 return super.equals(other);
235 }
236
237 @Deprecated public int hashCode() {
238 return super.hashCode();
239 }
240
241 public boolean isEqual(Attrs o) {
242 if (this == o)
243 return true;
244
245 Attrs other = o;
246
247 if (size() != other.size())
248 return false;
249
250 if (isEmpty())
251 return true;
252
253 SortedList<String> l = new SortedList<String>(keySet());
254 SortedList<String> lo = new SortedList<String>(other.keySet());
255 if (!l.isEqual(lo))
256 return false;
257
258 for (String key : keySet()) {
259 if (!get(key).equals(other.get(key)))
260 return false;
261 }
262 return true;
263
264 }
265
266 public Object getTyped(String adname) {
267 String s = get(adname);
268 if (s == null)
269 return null;
270
271 Type t = getType(adname);
272 return convert(t, s);
273 }
274
275 private Object convert(Type t, String s) {
276 if (t.sub == null) {
277 switch (t) {
278 case STRING:
279 return s;
280 case LONG:
281 return Long.parseLong(s.trim());
282 case VERSION:
283 return Version.parseVersion(s);
284 }
285 return null;
286 }
287 List<Object> list = new ArrayList<Object>();
288 String split[] = s.split("\\s*\\(\\?!\\),\\s*");
289 for (String p : split) {
290 p = p.replaceAll("\\\\", "");
291 list.add(convert(t.sub, p));
292 }
293 return list;
294 }
295}