source: java/main/src/main/java/com/framsticks/structure/AbstractTree.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: 8.8 KB
Line 
1package com.framsticks.structure;
2
3import java.util.Comparator;
4import java.util.Iterator;
5import java.util.Map;
6import java.util.PriorityQueue;
7
8import javax.annotation.Nonnull;
9
10import org.apache.commons.collections.map.ReferenceIdentityMap;
11import org.apache.logging.log4j.Logger;
12import org.apache.logging.log4j.LogManager;
13
14import com.framsticks.communication.queries.NeedFile;
15import com.framsticks.communication.queries.NeedFileAcceptor;
16import com.framsticks.params.Access;
17import com.framsticks.params.CompositeParam;
18import com.framsticks.params.FramsClass;
19import com.framsticks.params.ParamFlags;
20import com.framsticks.params.ParamsPackage;
21import com.framsticks.params.Registry;
22import com.framsticks.params.annotations.AutoAppendAnnotation;
23import com.framsticks.params.annotations.FramsClassAnnotation;
24import com.framsticks.params.annotations.ParamAnnotation;
25import com.framsticks.structure.messages.ListChange;
26import com.framsticks.structure.messages.Message;
27import com.framsticks.structure.messages.Result;
28import com.framsticks.structure.messages.ValueChange;
29import com.framsticks.util.ExceptionHandler;
30import com.framsticks.util.FramsticksException;
31import com.framsticks.util.Misc;
32import com.framsticks.util.dispatching.AbstractJoinable;
33import com.framsticks.util.dispatching.BufferedDispatcher;
34import com.framsticks.util.dispatching.Dispatcher;
35import com.framsticks.util.dispatching.Dispatching;
36import com.framsticks.util.dispatching.Joinable;
37import com.framsticks.util.dispatching.JoinableParent;
38import com.framsticks.util.dispatching.JoinableState;
39import com.framsticks.util.dispatching.RunAt;
40import com.framsticks.util.dispatching.ThrowExceptionHandler;
41import com.framsticks.util.lang.Pair;
42
43/**
44 * @author Piotr Sniegowski
45 */
46@FramsClassAnnotation
47public abstract class AbstractTree extends AbstractJoinable implements Tree, JoinableParent, NeedFileAcceptor {
48
49        private static final Logger log = LogManager.getLogger(AbstractTree.class);
50
51        private Node root = null;
52        private ExceptionHandler handler = ThrowExceptionHandler.getInstance();
53
54        protected final BufferedDispatcher<Tree> bufferedDispatcher = new BufferedDispatcher<>(this);
55
56        protected final Registry registry = new Registry();
57
58        protected final PriorityQueue<Pair<Integer, NeedFileAcceptor>> needFileAcceptors = new PriorityQueue<>(32, new Comparator<Pair<Integer, NeedFileAcceptor>>() {
59
60                @Override
61                public int compare(Pair<Integer, NeedFileAcceptor> arg0, Pair<Integer, NeedFileAcceptor> arg1) {
62                        if (arg0.first < arg1.first) {
63                                return -1;
64                        }
65                        if (arg0.first > arg1.first) {
66                                return 1;
67                        }
68                        return 0;
69                }
70        });
71
72        @Override
73        public void assignRootParam(CompositeParam param) {
74                if (root != null) {
75                        throw new FramsticksException().msg("root has already specified type");
76                }
77                root = new Node(this, param, null);
78                log.debug("assigned root type: {}", root);
79        }
80
81        @Override
82        public void assignRootObject(Object object) {
83                if (root == null) {
84                        throw new FramsticksException().msg("root has no type specified");
85                }
86                if (root.getObject() != null) {
87                        throw new FramsticksException().msg("root has already object assigned").arg("current", root.getObject()).arg("candidate", object);
88                }
89                root = new Node(this, root.getParam(), object);
90                log.debug("assigned root object: {}", root);
91        }
92
93        @Override
94        public @Nonnull Node getAssignedRoot() {
95                if (root == null) {
96                        throw new FramsticksException().msg("root has no type specified yet").arg("in", this);
97                }
98                return root;
99        }
100
101        public boolean isRootAssigned() {
102                // assert isActive();
103                return root != null;
104        }
105
106        protected String name;
107
108        public AbstractTree() {
109                setName("tree");
110
111                registry.registerAndBuild(Result.class);
112                registry.registerAndBuild(ValueChange.class);
113                registry.registerAndBuild(ListChange.class);
114                registry.registerAndBuild(Message.class);
115        }
116
117        protected void tryRegisterOnChangeEvents(Path path) {
118
119        }
120
121        @Override
122        public final FramsClass getInfoFromCache(String id) {
123                assert isActive();
124                return registry.getFramsClass(id);
125        }
126
127
128        @Override
129        public @Nonnull Access prepareAccess(CompositeParam param) {
130                return registry.prepareAccess(param, false);
131        }
132
133        @Override
134        public void takeAllFrom(Registry source) {
135                registry.takeAllFrom(source);
136        }
137
138        @AutoAppendAnnotation
139        public void usePackage(ParamsPackage paramsPackage) {
140                log.debug("using package {} in tree {}", paramsPackage, this);
141                paramsPackage.register(registry);
142        }
143
144        @AutoAppendAnnotation
145        public void takeFromRegistry(Registry registry) {
146                log.debug("taking from registry {} in tree {}", registry, this);
147                this.registry.takeAllFrom(registry);
148        }
149
150
151        @Override
152        public void putInfoIntoCache(FramsClass framclass) {
153                registry.putFramsClass(framclass);
154        }
155
156
157        /**
158         * @return the handler
159         */
160        @Override
161        public ExceptionHandler getExceptionHandler() {
162                return handler;
163        }
164
165        /**
166         * @param handler the handler to set
167         */
168        @Override
169        public void setExceptionHandler(ExceptionHandler handler) {
170                this.handler = handler;
171        }
172
173        @Override
174        public void handle(FramsticksException exception) {
175                handler.handle(exception);
176        }
177
178        /**
179         * @return the dispatcher
180         */
181        @Override
182        public Dispatcher<Tree> getDispatcher() {
183                return bufferedDispatcher;
184        }
185
186        /**
187         * @param dispatcher the dispatcher to set
188         */
189        @Override
190        public void setDispatcher(Dispatcher<Tree> dispatcher) {
191                bufferedDispatcher.setTargetDispatcher(dispatcher);
192        }
193
194        /**
195         * @return the name
196         */
197        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
198        public String getName() {
199                return name;
200        }
201
202        /**
203         * @param name the name to set
204         */
205        @ParamAnnotation
206        public void setName(String name) {
207                this.name = name;
208        }
209
210        /**
211         * @return the registry
212         */
213        @Override
214        public Registry getRegistry() {
215                return registry;
216        }
217
218        @Override
219        protected void joinableStart() {
220                bufferedDispatcher.createThreadIfNeeded();
221                Dispatching.use(bufferedDispatcher, this);
222        }
223
224        @Override
225        protected void joinableInterrupt() {
226                Dispatching.drop(bufferedDispatcher, this);
227        }
228
229        @Override
230        protected void joinableFinish() {
231
232        }
233
234        @Override
235        protected void joinableJoin() throws InterruptedException {
236                Dispatching.join(bufferedDispatcher);
237        }
238
239        @Override
240        public void childChangedState(Joinable joinable, JoinableState state) {
241                if (joinable == bufferedDispatcher) {
242                        proceedToState(state);
243                }
244        }
245
246        @Override
247        public boolean isActive() {
248                return bufferedDispatcher.isActive();
249        }
250
251        @Override
252        public void dispatch(RunAt<? extends Tree> runnable) {
253                bufferedDispatcher.dispatch(runnable);
254        }
255
256
257        @SuppressWarnings("unchecked")
258        protected final Map<Object, Object> sideNotes = (Map<Object, Object>) new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD);
259
260        @Override
261        public <T> void putSideNote(Object object, SideNoteKey<T> key, T value) {
262                assert isActive();
263                Misc.throwIfNull(object);
264                Misc.throwIfNull(key);
265                Misc.throwIfNull(value);
266                Object sideNote = sideNotes.get(object);
267                if (sideNote == null) {
268                        sideNote = new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD);
269                        sideNotes.put(object, sideNote);
270                }
271                @SuppressWarnings("unchecked")
272                Map<SideNoteKey<?>, Object> sideNotesMap = (Map<SideNoteKey<?>, Object>) sideNote;
273                sideNotesMap.put(key, value);
274        }
275
276        @SuppressWarnings("unchecked")
277        @Override
278        public <T> T getSideNote(Object object, SideNoteKey<T> key) {
279                assert isActive();
280                Misc.throwIfNull(object);
281                Misc.throwIfNull(key);
282                Object sideNote = sideNotes.get(object);
283                if (sideNote == null) {
284                        return null;
285                }
286                Object value = ((Map<SideNoteKey<?>, Object>) sideNote).get(key);
287                if (value == null) {
288                        return null;
289                }
290                return (T) value;
291        }
292
293        @Override
294        public boolean removeSideNote(Object object, SideNoteKey<?> key) {
295                assert isActive();
296                Object sideNote = sideNotes.get(object);
297                if (sideNote == null) {
298                        return false;
299                }
300                @SuppressWarnings("unchecked")
301                Map<SideNoteKey<?>, Object> sideNotesMap = (Map<SideNoteKey<?>, Object>) sideNote;
302                boolean result = (sideNotesMap.remove(key) != null);
303                if (sideNotesMap.isEmpty()) {
304                        sideNotes.remove(object);
305                }
306                return result;
307        }
308
309        @Override
310        public void addNeedFileAcceptor(int priority, NeedFileAcceptor acceptor) {
311                assert isActive();
312                needFileAcceptors.add(Pair.make(priority, acceptor));
313        }
314
315        @Override
316        public void removeNeedFileAcceptor(NeedFileAcceptor acceptor) {
317                assert isActive();
318                Iterator<Pair<Integer, NeedFileAcceptor>> i = needFileAcceptors.iterator();
319                while (i.hasNext()) {
320                        if (i.next().second == acceptor) {
321                                i.remove();
322                                break;
323                        }
324                }
325        }
326
327        @Override
328        public boolean acceptNeed(final NeedFile needFile) {
329                Dispatching.dispatchIfNotActive(this, new RunAt<AbstractTree>(needFile.getFuture()) {
330
331                        @Override
332                        protected void runAt() {
333                                for (Pair<Integer, NeedFileAcceptor> acceptor : needFileAcceptors) {
334                                        if (acceptor.second.acceptNeed(needFile)) {
335                                                return;
336                                        }
337                                }
338                                throw new FramsticksException().msg("failed to find need file acceptor in tree").arg("tree", AbstractTree.this).arg("needfile", needFile);
339                        }
340                });
341                return true;
342        }
343
344}
345
Note: See TracBrowser for help on using the repository browser.