source: java/main/src/main/java/com/framsticks/core/AbstractTree.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: 7.1 KB
Line 
1package com.framsticks.core;
2
3import java.util.Map;
4
5import javax.annotation.Nonnull;
6
7import org.apache.commons.collections.map.ReferenceIdentityMap;
8import org.apache.logging.log4j.Logger;
9import org.apache.logging.log4j.LogManager;
10
11import com.framsticks.params.Access;
12import com.framsticks.params.CompositeParam;
13import com.framsticks.params.FramsClass;
14import com.framsticks.params.ParamsPackage;
15import com.framsticks.params.Registry;
16import com.framsticks.params.annotations.AutoAppendAnnotation;
17import com.framsticks.params.annotations.FramsClassAnnotation;
18import com.framsticks.params.annotations.ParamAnnotation;
19import com.framsticks.util.FramsticksException;
20import com.framsticks.util.Misc;
21import com.framsticks.util.dispatching.AbstractJoinable;
22import com.framsticks.util.dispatching.Dispatcher;
23import com.framsticks.util.dispatching.Dispatching;
24import com.framsticks.util.dispatching.ExceptionResultHandler;
25import com.framsticks.util.dispatching.Joinable;
26import com.framsticks.util.dispatching.JoinableDispatcher;
27import com.framsticks.util.dispatching.JoinableParent;
28import com.framsticks.util.dispatching.JoinableState;
29import com.framsticks.util.dispatching.RunAt;
30import com.framsticks.util.dispatching.Thread;
31import com.framsticks.util.dispatching.ThrowExceptionHandler;
32import com.framsticks.util.lang.Casting;
33
34/**
35 * @author Piotr Sniegowski
36 */
37@FramsClassAnnotation
38public abstract class AbstractTree extends AbstractJoinable implements Dispatcher<Tree>, Tree, JoinableParent {
39
40        private static final Logger log = LogManager.getLogger(AbstractTree.class);
41
42        private Node root = null;
43        private ExceptionResultHandler handler = ThrowExceptionHandler.getInstance();
44
45        private JoinableDispatcher<Tree> dispatcher;
46
47        @Override
48        public void assignRootParam(CompositeParam param) {
49                if (root != null) {
50                        throw new FramsticksException().msg("root has already specified type");
51                }
52                root = new Node(this, param, null);
53                log.debug("assigned root type: {}", root);
54        }
55
56        @Override
57        public void assignRootObject(Object object) {
58                if (root == null) {
59                        throw new FramsticksException().msg("root is has no type specified");
60                }
61                if (root.getObject() != null) {
62                        throw new FramsticksException().msg("root has already object assigned").arg("current", root.getObject()).arg("candidate", object);
63                }
64                root = new Node(this, root.getParam(), object);
65                log.debug("assigned root object: {}", root);
66        }
67
68        @Override
69        public @Nonnull Node getAssignedRoot() {
70                if (root == null) {
71                        throw new FramsticksException().msg("root has no type specified yet");
72                }
73                return root;
74        }
75
76        public boolean isRootAssigned() {
77                // assert isActive();
78                return root != null;
79        }
80
81        protected String name;
82
83        public AbstractTree() {
84                setName("tree");
85        }
86
87        protected void tryRegisterOnChangeEvents(Path path) {
88
89        }
90
91        @Override
92        public final FramsClass getInfoFromCache(String id) {
93                assert isActive();
94                return registry.getFramsClass(id);
95        }
96
97        protected Registry registry = new Registry();
98
99
100        @Override
101        public @Nonnull Access prepareAccess(CompositeParam param) {
102                return registry.prepareAccess(param);
103        }
104
105        @Override
106        public void takeAllFrom(Registry source) {
107                registry.takeAllFrom(source);
108        }
109
110        @AutoAppendAnnotation
111        public void usePackage(ParamsPackage paramsPackage) {
112                log.debug("using package {} in tree {}", paramsPackage, this);
113                paramsPackage.register(registry);
114        }
115
116        @AutoAppendAnnotation
117        public void takeFromRegistry(Registry registry) {
118                log.debug("taking from registry {} in tree {}", registry, this);
119                this.registry.takeAllFrom(registry);
120        }
121
122
123        @Override
124        public void putInfoIntoCache(FramsClass framclass) {
125                registry.putFramsClass(framclass);
126        }
127
128
129        /**
130         * @return the handler
131         */
132        @Override
133        public ExceptionResultHandler getExceptionHandler() {
134                return handler;
135        }
136
137        /**
138         * @param handler the handler to set
139         */
140        @Override
141        public void setExceptionHandler(ExceptionResultHandler handler) {
142                this.handler = handler;
143        }
144
145        @Override
146        public void handle(FramsticksException exception) {
147                handler.handle(exception);
148        }
149
150        /**
151         * @return the dispatcher
152         */
153        @Override
154        public JoinableDispatcher<Tree> getDispatcher() {
155                return dispatcher;
156        }
157
158        /**
159         * @param dispatcher the dispatcher to set
160         */
161        @Override
162        public void setDispatcher(JoinableDispatcher<Tree> dispatcher) {
163                if (this.dispatcher != null) {
164                        throw new FramsticksException().msg("dispatcher is already set").arg("tree", this).arg("dispatcher", dispatcher);
165                }
166                this.dispatcher = dispatcher;
167        }
168
169        /**
170         * @return the name
171         */
172        @ParamAnnotation
173        public String getName() {
174                return name;
175        }
176
177        /**
178         * @param name the name to set
179         */
180        @ParamAnnotation
181        public void setName(String name) {
182                this.name = name;
183        }
184
185        /**
186         * @return the registry
187         */
188        @Override
189        public Registry getRegistry() {
190                return registry;
191        }
192
193        @Override
194        protected void joinableStart() {
195                if (dispatcher == null) {
196                        dispatcher = new Thread<Tree>();
197                }
198                Dispatching.use(dispatcher, this);
199        }
200
201        @Override
202        protected void joinableInterrupt() {
203                Dispatching.drop(dispatcher, this);
204        }
205
206        @Override
207        protected void joinableFinish() {
208
209        }
210
211        @Override
212        protected void joinableJoin() throws InterruptedException {
213                Dispatching.join(dispatcher);
214        }
215
216        @Override
217        public void childChangedState(Joinable joinable, JoinableState state) {
218                if (joinable == dispatcher) {
219                        proceedToState(state);
220                }
221        }
222
223        @Override
224        public boolean isActive() {
225                if (dispatcher == null) {
226                        throw new FramsticksException().msg("no dispatcher is set for tree yet").arg("tree", this);
227                }
228                return dispatcher.isActive();
229        }
230
231        @Override
232        public void dispatch(RunAt<? extends Tree> runnable) {
233                if (dispatcher == null) {
234                        throw new FramsticksException().msg("no dispatcher is set for tree yet").arg("tree", this);
235                }
236                dispatcher.dispatch(runnable);
237        }
238
239
240        @SuppressWarnings("unchecked")
241        protected final Map<Object, Object> sideNotes = (Map<Object, Object>) new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD);
242
243        @Override
244        public void putSideNote(Object object, Object key, Object value) {
245                assert isActive();
246                Misc.throwIfNull(object);
247                Misc.throwIfNull(key);
248                Misc.throwIfNull(value);
249                Object sideNote = sideNotes.get(object);
250                if (sideNote == null) {
251                        sideNote = new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD);
252                        sideNotes.put(object, sideNote);
253                }
254                @SuppressWarnings("unchecked")
255                Map<Object, Object> sideNotesMap = (Map<Object, Object>) sideNote;
256                sideNotesMap.put(key, value);
257        }
258
259        @Override
260        public <T> T getSideNote(Object object, Object key, Class<T> valueType) {
261                assert isActive();
262                Misc.throwIfNull(object);
263                Misc.throwIfNull(key);
264                Object sideNote = sideNotes.get(object);
265                if (sideNote == null) {
266                        return null;
267                }
268                return Casting.nullOrThrowCast(valueType, ((Map<?, ?>) sideNote).get(key));
269        }
270
271        @Override
272        public boolean removeSideNote(Object object, Object key) {
273                Object sideNote = sideNotes.get(object);
274                if (sideNote == null) {
275                        return false;
276                }
277                @SuppressWarnings("unchecked")
278                Map<Object, Object> sideNotesMap = (Map<Object, Object>) sideNote;
279                boolean result = (sideNotesMap.remove(key) != null);
280                if (sideNotesMap.isEmpty()) {
281                        sideNotes.remove(object);
282                }
283                return result;
284        }
285
286}
287
Note: See TracBrowser for help on using the repository browser.