Properties.java revision 1472:c18cbe5936b8
1/*
2 * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24package com.sun.hotspot.igv.data;
25
26import java.io.Serializable;
27import java.util.ArrayList;
28import java.util.Collection;
29import java.util.Iterator;
30import java.util.List;
31import java.util.regex.Matcher;
32import java.util.regex.Pattern;
33
34
35/**
36 *
37 * @author Thomas Wuerthinger
38 */
39public class Properties implements Serializable, Iterable<Property> {
40
41    public static final long serialVersionUID = 1L;
42    private String[] map = new String[4];
43
44    public Properties() {
45    }
46
47    @Override
48    public boolean equals(java.lang.Object o) {
49        if (!(o instanceof Properties)) {
50            return false;
51        }
52
53        Properties p = (Properties) o;
54
55        for (Property prop : this) {
56            String value = p.get(prop.getName());
57            if (value == null || !value.equals(prop.getValue())) {
58                return false;
59            }
60        }
61        return true;
62    }
63
64    @Override
65    public int hashCode() {
66        int hash = 5;
67        hash = 83 * hash + (this.map != null ? this.map.hashCode() : 0);
68        return hash;
69    }
70
71    public Properties(String name, String value) {
72        this();
73        this.setProperty(name, value);
74    }
75
76    public Properties(String name, String value, String name1, String value1) {
77        this(name, value);
78        this.setProperty(name1, value1);
79    }
80
81    public Properties(String name, String value, String name1, String value1, String name2, String value2) {
82        this(name, value, name1, value1);
83        this.setProperty(name2, value2);
84    }
85
86    public Properties(Properties p) {
87        map = new String[p.map.length];
88        System.arraycopy(map, 0, p.map, 0, p.map.length);
89    }
90
91    public static class Entity implements Provider {
92
93        private Properties properties;
94
95        public Entity() {
96            properties = new Properties();
97        }
98
99        public Entity(Properties.Entity object) {
100            properties = new Properties(object.getProperties());
101        }
102
103        public Properties getProperties() {
104            return properties;
105        }
106    }
107
108    private String getProperty(String key) {
109        for (int i = 0; i < map.length; i += 2)
110            if (map[i] != null && map[i].equals(key)) {
111                return map[i + 1];
112            }
113        return null;
114    }
115
116    public interface PropertyMatcher {
117
118        String getName();
119
120        boolean match(String value);
121    }
122
123    public static class InvertPropertyMatcher implements PropertyMatcher {
124
125        private PropertyMatcher matcher;
126
127        public InvertPropertyMatcher(PropertyMatcher matcher) {
128            this.matcher = matcher;
129        }
130
131        public String getName() {
132            return matcher.getName();
133        }
134
135        public boolean match(String p) {
136            return !matcher.match(p);
137        }
138    }
139
140    public static class StringPropertyMatcher implements PropertyMatcher {
141
142        private String name;
143        private String value;
144
145        public StringPropertyMatcher(String name, String value) {
146            this.name = name;
147            this.value = value;
148        }
149
150        public String getName() {
151            return name;
152        }
153
154        public boolean match(String p) {
155            return p.equals(value);
156        }
157    }
158
159    public static class RegexpPropertyMatcher implements PropertyMatcher {
160
161        private String name;
162        private Pattern valuePattern;
163
164        public RegexpPropertyMatcher(String name, String value) {
165            this.name = name;
166            valuePattern = Pattern.compile(value);
167        }
168
169        public String getName() {
170            return name;
171        }
172
173        public boolean match(String p) {
174            Matcher m = valuePattern.matcher(p);
175            return m.matches();
176        }
177    }
178
179    public Property selectSingle(PropertyMatcher matcher) {
180        String value = null;
181        for (int i = 0; i < map.length; i += 2) {
182            if (map[i] != null && matcher.getName().equals(map[i]))  {
183                value = map[i + 1];
184                break;
185            }
186        }
187        if (value != null && matcher.match(value)) {
188            return new Property(matcher.getName(), value);
189        } else {
190            return null;
191        }
192    }
193
194    public interface Provider {
195
196        public Properties getProperties();
197    }
198
199    @Override
200    public String toString() {
201        StringBuilder sb = new StringBuilder();
202        sb.append("[");
203        for (int i = 0; i < map.length; i += 2) {
204            if (map[i + 1] != null) {
205                String p = map[i + 1];
206                sb.append(map[i] + " = " + map[i + 1] + "; ");
207            }
208        }
209        return sb.append("]").toString();
210    }
211
212    public static class PropertySelector<T extends Properties.Provider> {
213
214        private Collection<T> objects;
215
216        public PropertySelector(Collection<T> objects) {
217            this.objects = objects;
218        }
219
220        public T selectSingle(final String name, final String value) {
221            return selectSingle(new StringPropertyMatcher(name, value));
222        }
223
224        public T selectSingle(PropertyMatcher matcher) {
225
226            for (T t : objects) {
227                Property p = t.getProperties().selectSingle(matcher);
228                if (p != null) {
229                    return t;
230                }
231            }
232
233            return null;
234        }
235
236        public List<T> selectMultiple(final String name, final String value) {
237            return selectMultiple(new StringPropertyMatcher(name, value));
238        }
239
240        public List<T> selectMultiple(PropertyMatcher matcher) {
241            List<T> result = new ArrayList<T>();
242            for (T t : objects) {
243                Property p = t.getProperties().selectSingle(matcher);
244                if (p != null) {
245                    result.add(t);
246                }
247            }
248            return result;
249        }
250    }
251
252    public String get(String key) {
253        for (int i = 0; i < map.length; i += 2) {
254            if (map[i] != null && map[i].equals(key)) {
255                return map[i + 1];
256            }
257        }
258        return null;
259    }
260
261    public void setProperty(String name, String value) {
262        for (int i = 0; i < map.length; i += 2) {
263            if (map[i] != null && map[i].equals(name)) {
264                String p = map[i + 1];
265                if (value == null) {
266                    // remove this property
267                    map[i] = null;
268                    map[i + 1] = null;
269                } else {
270                    map[i + 1] = value;
271                }
272                return;
273            }
274        }
275        if (value == null) {
276            return;
277        }
278        for (int i = 0; i < map.length; i += 2) {
279            if (map[i] == null) {
280                map[i] = name;
281                map[i + 1] = value;
282                return;
283            }
284        }
285        String[] newMap = new String[map.length + 4];
286        System.arraycopy(map, 0, newMap, 0, map.length);
287        newMap[map.length] = name;
288        newMap[map.length + 1] = value;
289        map = newMap;
290    }
291
292    public  Iterator<Property> getProperties() {
293        return iterator();
294    }
295
296    public void add(Properties properties) {
297        for (Property p : properties) {
298            add(p);
299        }
300    }
301
302    public void add(Property property) {
303        assert property.getName() != null;
304        assert property.getValue() != null;
305        setProperty(property.getName(), property.getValue());
306    }
307    class PropertiesIterator implements Iterator<Property>, Iterable<Property> {
308        public Iterator<Property> iterator() {
309                return this;
310        }
311
312        int index;
313
314        public boolean hasNext() {
315            while (index < map.length && map[index + 1] == null)
316                index += 2;
317            return index < map.length;
318        }
319
320        public Property next() {
321            if (index < map.length) {
322                index += 2;
323                return new Property(map[index - 2], map[index - 1]);
324            }
325            return null;
326        }
327
328        public void remove() {
329            throw new UnsupportedOperationException("Not supported yet.");
330        }
331
332    }
333    public Iterator<Property> iterator() {
334        return new PropertiesIterator();
335    }
336}
337