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

Last change on this file since 100 was 100, checked in by psniegowski, 11 years ago

HIGHLIGHTS:

  • add <include/> to configuration
  • add side notes to tree
    • used to store arbitrary information alongside the tree structure
  • migrate to log4j2
    • supports lazy string evaluation of passed arguments
  • improve GUI tree
    • it stays in synchronization with actual state (even in high load test scenario)
  • improve panel management in GUI
  • make loading objects in GUI more lazy
  • offload parsing to connection receiver thread
    • info parsing
    • first step of objects parsing
  • fix connection parsing bug (eof in long values)
  • support zero-arguments procedure in table view

CHANGELOG:
Implement procedure calls from table view.

Refactorization around procedures in tables.

Add table editor for buttons.

Render buttons in the the list view.

Further improve Columns.

Add Column class for TableModel?.

Accept also non-arguments ProcedureParams? in tableView.

Increase maximal TextAreaControl? size.

Add tooltip to ProcedureControl?.

Fix bug of interpreting eofs in long values by connection reader.

Further rework connection parsing.

Simplify client connection processing.

Test ListChange? modification.

Test ListChange? events with java server.

Add TestChild?.

Fix bug with fast deregistering when connecting to running server.

Another minor refactorization in TreeOperations?.

Fix bug in SimpleAbstractAccess? loading routine.

Another minor improvement.

Minor change.

Make reading of List objects two-phase.

Another minor change.

Dispatch parsing into receiver thread.

Another step.

Enclose passing value in ObjectParam? case in closure.

Minor step.

Minor change on way to offload parsing.

Temporarily comment out single ValueParam? get.

It will be generalized to multi ValueParam?.

Process info in receiver thread.

Add DispatchingExceptionHandler?.

Make waits in browser test longer.

Use FETCHED_MARK.

It is honored in GUI, where it used to decide whether to get values

after user action.

It is set in standard algorithm for processing fetched values.

Add remove operation to side notes.

Make loading more lazy.

Improve loading policy.

On node choose load itself, on node expansion, load children.

Minor improvement.

Fix bug with panel interleaving.

Minor improvements.

Improve panel management.

More cleaning around panels.

Reorganize panels.

Further improve tree.

Fix bug in TreeModel?.

Remove children from TreeNode?.

Implement TreeNode? hashCode and equals.

Make TreeNode? delegate equals and hashcode to internal reference.

Move listeners from TreeNode? to side notes.

Store path.textual as a side note.

Side note params instead of accesses for objects.

More refactorizations.

In TreeNode? bindAccess based on side notes.

Minor step.

Hide createAccess.

Rename AccessInterface? to Access.

Minor changes.

Several improvements in high load scenarios.

Change semantics of ArrayListAccess?.set(index, null);

It now removes the element, making list shorter
(it was set to null before).

Add path remove handler.

Handle exceptions in Connection.

Update .gitignore

Configure logging to file.

Move registration to TreeModel?.

Further refactorization.

Minor refactorization.

Minor improvements.

Use specialized event also for Modify action of ListChange?.

Use remove events.

Use the insertion events for tree.

Further improve tree refreshing.

Further improve reacting on events in GUI.

Fix problem with not adding objects on addition list change.

Migrate to log4j lazy String construction interface.

Migrate imports to log4j2.

Drop dependency on adapter to version 1.2.

Switch log4j implementation to log4j2.

Add dirty mark to the NodeAtFrame?.

Make selecting in AccessInterfaces? type safe.

Ignore containers size settings in Model and Genotype.

Use tree side notes to remember local changes and panels.

Add sideNotes to tree.

They will be used to store various accompanying information
right in the tree.

Use ReferenceIdentityMap? from apache in TreeNode?.

It suits the need perfectly (weak semantics on both key and value).

Make ArrayListParam? do not react size changes.

Guard in TableModel? before not yet loaded objects.

Add <include/> clause and AutoInjector?.

Extract common columns configuration to separate xml,
that can be included by other configurations.

File size: 6.8 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.UnsupportedOperationException;
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 getId() {
143                return "l " + elementAccess.getId() + " " + 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        protected int setByUid(Object object, String uid) {
190                if (uid == null) {
191                        uid = getUidOf(object);
192                        if (uid == null) {
193                                log.error("failed to set - missing uid");
194                                return 0;
195                        }
196                }
197                if (object == null) {
198                        map.remove(uid);
199                } else {
200                        map.put(uid, object);
201                }
202                return 0;
203        }
204
205        @Override
206        public <T> int set(int i, T value) {
207                throw new UnsupportedOperationException().msg("accesing unique list through index");
208        }
209
210        @Override
211        public <T> int set(String id, T value) {
212                Integer i = Numbers.parse(id, Integer.class);
213                if (i != null) {
214                        return set(i, value);
215                }
216                if (value == null) {
217                        return setByUid(null, id);
218                }
219                String uid = getUidOf(value);
220                if (uid != null && id != null) {
221                        if (!id.equals(uid)) {
222                                log.error("uid mismatch with set key");
223                                return 0;
224                        }
225                        setByUid(value, uid);
226                        return 0;
227                }
228                if (uid != null) {
229                        setByUid(value, uid);
230                        return 0;
231                }
232                if (id != null) {
233                        setByUid(value, id);
234                        return 0;
235                }
236                log.error("missing both uid and id - failed to set");
237                return 0;
238        }
239
240        @Override
241        public <T> int set(ValueParam param, T value) {
242                return set(param.getId(), value);
243        }
244
245        @Override
246        public void clearValues() {
247                map.clear();
248        }
249
250        @SuppressWarnings("unchecked")
251        @Override
252        public UniqueListAccess select(Object object) {
253                map = Util.selectObjectForAccess(this, object, Map.class);
254                return this;
255        }
256
257        @Override
258        public Object getSelected() {
259                return map;
260        }
261
262        @Override
263        public UniqueListAccess cloneAccess() {
264                return new UniqueListAccess(elementAccess.cloneAccess(), uidName);
265        }
266
267        // public String computeIdentifierFor(Object selected) {
268        //      String uid = getUidOf(selected);
269        //      if (uid == null) {
270        //              log.error("missing uid field");
271        //              return null;
272        //      }
273        //      return uid;
274        // }
275
276        @Override
277        public Iterable<Param> getParams() {
278                return new Iterable<Param>() {
279
280                        @Override
281                        public Iterator<Param> iterator() {
282                                return new Iterator<Param>() {
283
284                                        protected Iterator<Map.Entry<String, Object>> internal = map.entrySet().iterator();
285
286                                        @Override
287                                        public boolean hasNext() {
288                                                return internal.hasNext();
289                                        }
290
291                                        @Override
292                                        public Param next() {
293                                                return paramBuilder.id(internal.next().getKey()).finish();
294                                        }
295
296                                        @Override
297                                        public void remove() {
298                                                throw new UnimplementedException().msg("remove element from list").arg("list", UniqueListAccess.this);
299
300                                        }
301                                };
302                        }
303                };
304        }
305
306        @Override
307        public int getCompositeParamCount() {
308                return map.size();
309        }
310
311        @Override
312        public CompositeParam getCompositeParam(int number) {
313                return getParam(number);
314        }
315
316        @Override
317        public ParamBuilder buildParam(ParamBuilder builder) {
318                return builder.name(containedTypeName + " list").type(UniqueListParam.class).containedTypeName(containedTypeName).uid(uidName);
319        }
320
321}
Note: See TracBrowser for help on using the repository browser.