1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.properties;
18
19 import java.util.AbstractMap.SimpleEntry;
20 import java.util.Collections;
21 import java.util.Enumeration;
22 import java.util.Iterator;
23 import java.util.LinkedHashSet;
24 import java.util.Map;
25 import java.util.Objects;
26 import java.util.Properties;
27 import java.util.Set;
28 import java.util.function.BiConsumer;
29 import java.util.function.BiFunction;
30 import java.util.function.Function;
31 import java.util.stream.Collectors;
32
33
34
35
36
37
38
39
40
41
42 public class OrderedProperties extends Properties {
43
44 private static final long serialVersionUID = 1L;
45
46
47
48
49 private final LinkedHashSet<Object> orderedKeys = new LinkedHashSet<>();
50
51
52
53
54 public OrderedProperties() {
55
56 }
57
58 @Override
59 public synchronized void clear() {
60 orderedKeys.clear();
61 super.clear();
62 }
63
64 @Override
65 public synchronized Object compute(final Object key, final BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
66 final Object compute = super.compute(key, remappingFunction);
67 if (compute != null) {
68 orderedKeys.add(key);
69 }
70 return compute;
71 }
72
73 @Override
74 public synchronized Object computeIfAbsent(final Object key, final Function<? super Object, ? extends Object> mappingFunction) {
75 final Object computeIfAbsent = super.computeIfAbsent(key, mappingFunction);
76 if (computeIfAbsent != null) {
77 orderedKeys.add(key);
78 }
79 return computeIfAbsent;
80 }
81
82 @Override
83 public Set<Map.Entry<Object, Object>> entrySet() {
84 return orderedKeys.stream().map(k -> new SimpleEntry<>(k, get(k))).collect(Collectors.toCollection(LinkedHashSet::new));
85 }
86
87 @Override
88 public synchronized void forEach(final BiConsumer<? super Object, ? super Object> action) {
89 Objects.requireNonNull(action);
90 orderedKeys.forEach(k -> action.accept(k, get(k)));
91 }
92
93 @Override
94 public synchronized Enumeration<Object> keys() {
95 return Collections.enumeration(orderedKeys);
96 }
97
98 @Override
99 public Set<Object> keySet() {
100 return orderedKeys;
101 }
102
103 @Override
104 public synchronized Object merge(final Object key, final Object value,
105 final BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
106 orderedKeys.add(key);
107 return super.merge(key, value, remappingFunction);
108 }
109
110 @Override
111 public Enumeration<?> propertyNames() {
112 return Collections.enumeration(orderedKeys);
113 }
114
115 @Override
116 public synchronized Object put(final Object key, final Object value) {
117 final Object put = super.put(key, value);
118 if (put == null) {
119 orderedKeys.add(key);
120 }
121 return put;
122 }
123
124 @Override
125 public synchronized void putAll(final Map<? extends Object, ? extends Object> t) {
126 orderedKeys.addAll(t.keySet());
127 super.putAll(t);
128 }
129
130 @Override
131 public synchronized Object putIfAbsent(final Object key, final Object value) {
132 final Object putIfAbsent = super.putIfAbsent(key, value);
133 if (putIfAbsent == null) {
134 orderedKeys.add(key);
135 }
136 return putIfAbsent;
137 }
138
139 @Override
140 public synchronized Object remove(final Object key) {
141 final Object remove = super.remove(key);
142 if (remove != null) {
143 orderedKeys.remove(key);
144 }
145 return remove;
146 }
147
148 @Override
149 public synchronized boolean remove(final Object key, final Object value) {
150 final boolean remove = super.remove(key, value);
151 if (remove) {
152 orderedKeys.remove(key);
153 }
154 return remove;
155 }
156
157 @Override
158 public synchronized String toString() {
159
160 final int max = size() - 1;
161 if (max == -1) {
162 return "{}";
163 }
164 final StringBuilder sb = new StringBuilder();
165 final Iterator<Map.Entry<Object, Object>> it = entrySet().iterator();
166 sb.append('{');
167 for (int i = 0;; i++) {
168 final Map.Entry<Object, Object> e = it.next();
169 final Object key = e.getKey();
170 final Object value = e.getValue();
171 sb.append(key == this ? "(this Map)" : key.toString());
172 sb.append('=');
173 sb.append(value == this ? "(this Map)" : value.toString());
174 if (i == max) {
175 return sb.append('}').toString();
176 }
177 sb.append(", ");
178 }
179 }
180 }