source: java/main/src/main/java/com/framsticks/params/UniqueListAccess.java @ 193

Last change on this file since 193 was 193, checked in by Maciej Komosinski, 10 years ago

Set svn:eol-style native for all textual files

  • Property svn:eol-style set to native
File size: 7.6 KB
Line 
1package com.framsticks.params;
2
3import com.framsticks.params.types.UniqueListParam;
4import com.framsticks.util.FramsticksException;
5import com.framsticks.util.UnimplementedException;
6import com.framsticks.util.FramsticksUnsupportedOperationException;
7import com.framsticks.util.lang.Casting;
8import com.framsticks.util.lang.Numbers;
9import org.apache.logging.log4j.Logger;
10import org.apache.logging.log4j.LogManager;
11
12import java.util.*;
13
14/**
15 * @author Piotr Sniegowski
16 */
17public class UniqueListAccess extends ListAccess {
18
19        private static final Logger log = LogManager.getLogger(UniqueListAccess.class);
20
21        Map<String, Object> map;
22
23        protected final String uidName;
24        protected final Access uidAccess;
25
26        public UniqueListAccess(Access elementAccess, String uidName) {
27                super(elementAccess);
28                this.uidName = uidName;
29                uidAccess = elementAccess.cloneAccess();
30        }
31
32        public static Integer getUidNumber(String uid) {
33                try {
34                        return Integer.valueOf(uid.substring(1));
35                } catch (NumberFormatException e) {
36                        return null;
37                }
38        }
39
40        /**
41         * @return the uidName
42         */
43        public String getUidName() {
44                return uidName;
45        }
46
47        public static class UidComparator implements Comparator<String> {
48
49                protected Object description;
50
51
52                /**
53                 * @param description
54                 */
55                public UidComparator(Object description) {
56                        this.description = description;
57                }
58
59                @Override
60                public int compare(String a, String b) {
61                        if (a.equals(b)) {
62                                return 0;
63                        }
64                        int diff = a.length() - b.length();
65                        if (diff != 0) {
66                                return diff;
67                        }
68                        Integer au = getUidNumber(a);
69                        Integer bu = getUidNumber(b);
70                        if (au == null || bu == null) {
71                                throw new FramsticksException().msg("comparator failure").arg("left", a).arg("right", b).arg("in", this);
72                        }
73                        return au - bu;
74                }
75
76                @Override
77                public String toString() {
78                        return "comparator " + description;
79                }
80
81
82        }
83
84        public static <T> Map<String, T> createMap(Class<T> type, Object description) {
85                return new TreeMap<String, T>(new UidComparator(description));
86        }
87
88        public static <M, T extends M> int getNumberInMap(Map<String, M> map, T object) {
89                Iterator<Map.Entry<String, M>> iterator = map.entrySet().iterator();
90                int number = 0;
91                while (iterator.hasNext()) {
92                        if (iterator.next().getValue() == object) {
93                                return number;
94                        }
95                        ++number;
96                }
97                return -1;
98        }
99
100        @Override
101        public Map<String, Object> createAccessee() {
102                return createMap(Object.class, elementAccess);
103        }
104
105        @Override
106        public CompositeParam getParam(int i) {
107                if ((i < 0) ||  (i >= map.size())) {
108                        return null;
109                }
110                Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
111                while (i > 0 && iterator.hasNext()) {
112                        iterator.next();
113                        --i;
114                }
115                if (i > 0) {
116                        return null;
117                }
118                if (!iterator.hasNext()) {
119                        return null;
120                }
121                return paramBuilder.id(iterator.next().getKey()).finish(CompositeParam.class);
122        }
123
124        @Override
125        public CompositeParam getParam(String id) {
126                Integer i = Numbers.parse(id, Integer.class);
127                if (i != null) {
128                        return getParam(i);
129                }
130                Integer uidNumber = getUidNumber(id);
131                if (uidNumber == null) {
132                        return null;
133                }
134                if (!map.containsKey(id)) {
135                        return null;
136                }
137                return paramBuilder.id(id).finish(CompositeParam.class);
138        }
139
140
141        @Override
142        public String getTypeId() {
143                return "l " + elementAccess.getTypeId() + " " + uidName;
144        }
145
146        @Override
147        public int getParamCount() {
148                return map.size();
149        }
150
151        @Override
152        public <T> T get(int i, Class<T> type) {
153                Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
154                while (i > 0 && iterator.hasNext()) {
155                        iterator.next();
156                        --i;
157                }
158                if (i > 0) {
159                        return null;
160                }
161                if (!iterator.hasNext()) {
162                        return null;
163                }
164                return Casting.tryCast(type, iterator.next().getValue());
165        }
166
167        @Override
168        public <T> T get(String id, Class<T> type) {
169                Integer i = Numbers.parse(id, Integer.class);
170                if (i != null) {
171                        return get(i, type);
172                }
173                Integer uidNumber = getUidNumber(id);
174                if (uidNumber == null) {
175                        return null;
176                }
177                return Casting.tryCast(type, map.get(id));
178        }
179
180        @Override
181        public <T> T get(ValueParam param, Class<T> type) {
182                return get(param.getId(), type);
183        }
184
185        public String getUidOf(Object value) {
186                return uidAccess.select(value).get(uidName, String.class);
187        }
188
189        public int setUidOf(Object value, String uid) {
190                return uidAccess.select(value).set(uidName, uid);
191        }
192
193        protected int uidCounter = 1;
194
195        public String generateNextUid() {
196                return containedTypeName.substring(0, 1).toUpperCase() + Integer.toString(uidCounter++);
197        }
198
199        public String findNextFreeUid() {
200                String uid;
201                do {
202                        uid = generateNextUid();
203                } while (get(uid, Object.class) != null);
204                return uid;
205        }
206
207        protected int setByUid(Object object, String uid) {
208                if (uid == null) {
209                        uid = getUidOf(object);
210                        if (uid == null) {
211                                uid = findNextFreeUid();
212                                setUidOf(object, uid);
213                        }
214                }
215                if (object == null) {
216                        map.remove(uid);
217                } else {
218                        map.put(uid, object);
219                }
220                return 0;
221        }
222
223        @Override
224        public <T> int set(int i, T value) {
225                if (value != null) {
226                        if (i != map.size()) {
227                                throw new FramsticksUnsupportedOperationException().msg("setting element in unique list through index is available only for addition");
228                        }
229                        set(getUidOf(value), value);
230                        return 0;
231                }
232                if (i >= map.size()) {
233                        throw new FramsticksUnsupportedOperationException().msg("invalid index for removal");
234                }
235                Object current = get(i, Object.class);
236                return setByUid(null, getUidOf(current));
237        }
238
239        @Override
240        public <T> int set(String id, T value) {
241                if (id == null) {
242                        return setByUid(value, null);
243                }
244                Integer i = Numbers.parse(id, Integer.class);
245                if (i != null) {
246                        return set(i, value);
247                }
248                if (value == null) {
249                        return setByUid(null, id);
250                }
251                String uid = getUidOf(value);
252                if (uid != null && id != null) {
253                        if (!id.equals(uid)) {
254                                log.error("uid mismatch with set key");
255                                return 0;
256                        }
257                        setByUid(value, uid);
258                        return 0;
259                }
260                if (uid != null) {
261                        setByUid(value, uid);
262                        return 0;
263                }
264                if (id != null) {
265                        setByUid(value, id);
266                        return 0;
267                }
268                log.error("missing both uid and id - failed to set");
269                return 0;
270        }
271
272        @Override
273        public <T> int set(ValueParam param, T value) {
274                return set(param.getId(), value);
275        }
276
277        @Override
278        public void clearValues() {
279                map.clear();
280        }
281
282        @SuppressWarnings("unchecked")
283        @Override
284        public UniqueListAccess select(Object object) {
285                map = ParamsUtil.selectObjectForAccess(this, object, Map.class);
286                return this;
287        }
288
289        @Override
290        public Object getSelected() {
291                return map;
292        }
293
294        @Override
295        public UniqueListAccess cloneAccess() {
296                return new UniqueListAccess(elementAccess.cloneAccess(), uidName);
297        }
298
299        // public String computeIdentifierFor(Object selected) {
300        //      String uid = getUidOf(selected);
301        //      if (uid == null) {
302        //              log.error("missing uid field");
303        //              return null;
304        //      }
305        //      return uid;
306        // }
307
308        @Override
309        public Iterable<Param> getParams() {
310                return new Iterable<Param>() {
311
312                        @Override
313                        public Iterator<Param> iterator() {
314                                return new Iterator<Param>() {
315
316                                        protected Iterator<Map.Entry<String, Object>> internal = map.entrySet().iterator();
317
318                                        @Override
319                                        public boolean hasNext() {
320                                                return internal.hasNext();
321                                        }
322
323                                        @Override
324                                        public Param next() {
325                                                return paramBuilder.id(internal.next().getKey()).finish();
326                                        }
327
328                                        @Override
329                                        public void remove() {
330                                                throw new UnimplementedException().msg("remove element from list").arg("list", UniqueListAccess.this);
331
332                                        }
333                                };
334                        }
335                };
336        }
337
338        @Override
339        public int getCompositeParamCount() {
340                return map.size();
341        }
342
343        @Override
344        public CompositeParam getCompositeParam(int number) {
345                return getParam(number);
346        }
347
348        @Override
349        public ParamBuilder buildParam(ParamBuilder builder) {
350                return builder.name(containedTypeName + " list").type(UniqueListParam.class).containedTypeName(containedTypeName).uid(uidName);
351        }
352
353}
Note: See TracBrowser for help on using the repository browser.