source: java/main/src/main/java/com/framsticks/core/Instance.java @ 88

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

HIGHLIGHTS:

  • loading f0 schema with XmlLoader?
  • use XmlLoader? to load configuration
  • introduce unified fork-join model of various entities

(Instances, Connections, GUI Frames, etc.),
all those entities clean up gracefully on
shutdown, which may be initialized by user
or by some entity

  • basing on above, simplify several organizing classes

(Observer, main class)

(to host native frams server process from Java level)

CHANGELOG:
Remove redundant Observer class.

Clean up in AbstractJoinable?.

Update ExternalProcess? class to changes in joining model.

Another sweep through code with FindBugs?.

Find bug with not joining RemoteInstance?.

Joining almost works.

Much improved joining model.

More improvement to joining model.

Add logging messages around joinable operations.

Rename methods in AbstractJoinable?.

Improve Joinable.

Rewrite of entity structure.

More simplifications with entities.

Further improve joinables.

Let Frame compose from JFrame instead of inheriting.

Add join classes.

Improvements of closing.

Add Builder interface.

Add FramsServerTest?.xml

FramsServer? may be configured through xml.

Make Framsticks main class an Observer of Entities.

Make Observer a generic type.

Remove variables regarding to removed endpoint.

Simplify observer (remove endpoints).

More changes to Observer and Endpoint.

Minor improvements.

Add OutputListener? to ExternalProcess?.

Improve testing of ExternalProcess?.

Add ExternalProcess? runner.

Rename the Program class to Framsticks.

Migrate Program to use XmlLoader? configuration.

First steps with configuration using XmlLoader?.

Fix several bugs.

Move all f0 classes to apriopriate package.

XmlLoader? is able to load Schema.

XmlLoader? is loading classes and props.

Add GroupBuilder?.

File size: 9.7 KB
Line 
1package com.framsticks.core;
2
3import java.util.HashSet;
4import java.util.Iterator;
5import java.util.LinkedList;
6import java.util.List;
7import java.util.Set;
8
9import javax.annotation.Nonnull;
10import javax.annotation.OverridingMethodsMustInvokeSuper;
11
12import org.apache.log4j.Logger;
13
14import com.framsticks.communication.File;
15import com.framsticks.params.AccessInterface;
16import com.framsticks.params.ConstructionException;
17import com.framsticks.params.FramsClass;
18import com.framsticks.params.ListAccess;
19import com.framsticks.params.Param;
20import com.framsticks.params.Registry;
21import com.framsticks.params.ValueParam;
22import com.framsticks.params.annotations.FramsClassAnnotation;
23import com.framsticks.params.types.ObjectParam;
24import com.framsticks.parsers.Loaders;
25import com.framsticks.parsers.MultiParamLoader;
26import com.framsticks.util.StateFunctor;
27import com.framsticks.util.UnsupportedOperationException;
28import com.framsticks.util.dispatching.Dispatching;
29import com.framsticks.util.dispatching.Future;
30import com.framsticks.util.dispatching.RunAt;
31import com.framsticks.util.dispatching.Thread;
32import com.framsticks.util.lang.Casting;
33
34/**
35 * @author Piotr Sniegowski
36 */
37@FramsClassAnnotation
38public abstract class Instance extends Thread<Instance> implements Entity {
39
40        private static final Logger log = Logger.getLogger(Instance.class.getName());
41
42        protected Node root;
43
44        protected Set<InstanceListener> listeners = new HashSet<InstanceListener>();
45
46        public Instance() {
47                setName("entity");
48        }
49
50        protected void fetchInfo(Path path, Future<FramsClass> future) {
51                future.result(null, new UnsupportedOperationException());
52        }
53
54        public void resolve(Path path, Future<Path> future) {
55                assert isActive();
56                assert path.isOwner(this);
57                if (path.getTop().getObject() != null) {
58                        future.result(path, null);
59                        return;
60                }
61                AccessInterface access = bindAccess(path.getUnder());
62                Object object = access.get(path.getTop().getParam(), Object.class);
63                if (object == null) {
64                        future.result(path, null);
65                        return;
66                }
67                future.result(path.appendResolution(object), null);
68        }
69
70        public void fetchValue(Path path, Param param, StateFunctor stateFunctor) {
71                stateFunctor.call(null);
72        }
73
74        public void fetchValues(Path path, StateFunctor stateFunctor) {
75                stateFunctor.call(null);
76        }
77
78        protected void tryRegisterOnChangeEvents(Path path) {
79
80        }
81
82        public void storeValue(Path path, Param param, Object value, final StateFunctor stateFunctor) {
83                assert isActive();
84                invokeLater(new RunAt<Instance>() {
85                        @Override
86                        public void run() {
87                                stateFunctor.call(new UnsupportedOperationException());
88                        }
89                });
90        }
91
92        protected void fireRun(Exception e) {
93                for (InstanceListener l : this.listeners) {
94                        l.onRun(e);
95                }
96        }
97
98        protected void fireStop(Exception e) {
99                for (InstanceListener l : this.listeners) {
100                        l.onStop(e);
101                }
102        }
103
104        public void addListener(final InstanceListener listener) {
105                assert Dispatching.isThreadSafe();
106                Dispatching.invokeLaterOrNow(this, new RunAt<Instance>() {
107                        @Override
108                        public void run() {
109                                listeners.add(listener);
110                        }
111                });
112        }
113
114        public void removeListener(final InstanceListener listener) {
115                assert Dispatching.isThreadSafe();
116                Dispatching.invokeLaterOrNow(this, new RunAt<Instance>() {
117                        @Override
118                        public void run() {
119                                listeners.remove(listener);
120                        }
121                });
122        }
123
124        protected void fireListChange(Path path, ListChange change) {
125                assert isActive();
126                for (InstanceListener l : this.listeners) {
127                        l.onListChange(path, change);
128                }
129        }
130
131        protected void fireFetch(Path path) {
132                assert isActive();
133                for (InstanceListener l : this.listeners) {
134                        l.onFetch(path);
135                }
136        }
137
138        public final FramsClass getInfoFromCache(Path path) {
139                return getInfoFromCache(path.getTop().getParam().getContainedTypeName());
140        }
141
142        public FramsClass getInfoFromCache(String id) {
143                assert isActive();
144                return registry.getInfoFromCache(id);
145        }
146
147        protected Registry registry = new Registry();
148
149        public AccessInterface createAccess(String name) throws ConstructionException {
150                assert isActive();
151                return registry.createAccess(name);
152        }
153
154        // TODO: make ValueParam
155        public <T> T get(Node node, Param childParam, Class<T> type) {
156                return bindAccess(node).get((ValueParam) childParam, type);
157        }
158
159        public void findInfo(final Path path, final Future<FramsClass> future) {
160                assert isActive();
161                final String name = path.getTop().getParam().getContainedTypeName();
162                final FramsClass framsClass = getInfoFromCache(name);
163                if (framsClass != null) {
164                        log.trace("info for " + name + " found in cache");
165                        future.result(framsClass, null);
166                        return;
167                }
168                fetchInfo(path, future);
169        }
170
171        public final AccessInterface bindAccess(Node node) {
172                assert node.getObject() != null;
173
174                try {
175                        return registry.prepareAccess(node.getParam()).select(node.getObject());
176                } catch (ConstructionException e) {
177                        log.error("failed to bind access for " + node.getParam() + ": " + e);
178                }
179                return null;
180        }
181
182        public final <T> T getParam(Path path, String id, Class<T> type) {
183                return Casting.tryCast(type, registry.prepareAccess(path.getTop().getParam()).getParam(id));
184        }
185
186        public final AccessInterface bindAccess(Path path) {
187                assert path.isResolved();
188                return bindAccess(path.getTop());
189        }
190
191        public void resolve(final String targetPath, final Future<Path> future) {
192                assert isActive();
193                final Path path = getPath(targetPath);
194                resolve(path, new Future<Path>() {
195                        @Override
196                        public void result(Path result, Exception e) {
197                                assert isActive();
198                                if (e != null) {
199                                        future.result(path, e);
200                                        return;
201                                }
202                                if (path.isResolved(targetPath)) {
203                                        future.result(path, null);
204                                        return;
205                                }
206                                if (path.isResolved()) {
207                                        future.result(path, new Exception("testing"));
208                                        return;
209                                }
210                                resolve(targetPath, future);
211                        }
212                });
213        }
214
215        public void resolveAndFetch(final String targetPath, final Future<Path> future) {
216                assert isActive();
217                resolve(targetPath, new Future<Path>() {
218                        @Override
219                        public void result(final Path path, Exception e) {
220                                if (e != null) {
221                                        future.result(path, e);
222                                        return;
223                                }
224                                assert path.isResolved(targetPath);
225                                fetchValues(path, new StateFunctor() {
226                                        @Override
227                                        public void call(Exception e) {
228                                                future.result(path, e);
229                                        }
230                                });
231                        }
232                });
233        }
234
235        public Path createIfNeeded(String path) {
236                Path p;
237                while (!(p = getPath(path)).isResolved(path)) {
238                        create(p);
239                }
240                return p;
241        }
242
243        public Path createIfNeeded(Path path) {
244                assert isActive();
245                if (path.isResolved()) {
246                        return path;
247                }
248                return create(path);
249        }
250
251        public Path create(Path path) {
252                assert isActive();
253                assert !path.isResolved();
254                Path resolved = path.tryFindResolution();
255                if (!resolved.isResolved()) {
256                        log.debug("creating: " + path);
257                        AccessInterface access = registry.prepareAccess(path.getTop().getParam());
258                        assert access != null;
259                        Object child = access.createAccessee();
260                        assert child != null;
261                        if (path.size() == 1) {
262                                root = new Node(root.getParam(), child);
263                        } else {
264                                bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
265                        }
266                        resolved = path.appendResolution(child);
267                }
268                tryRegisterOnChangeEvents(resolved);
269                return resolved;
270        }
271
272
273
274
275        public @Nonnull FramsClass processFetchedInfo(File file) {
276                assert isActive();
277                FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
278                if ("/".equals(file.getPath())) {
279                        if (root.getParam().getContainedTypeName() == null) {
280                                root = new Node(Param.build().name("Instance").id(getName()).type("o " + framsClass.getId()), root.getObject());
281                        }
282                }
283                registry.putInfoIntoCache(framsClass);
284                return framsClass;
285        }
286
287        public void processFetchedValues(Path path, List<File> files) {
288                assert isActive();
289                assert files.size() == 1;
290                assert path.isTheSame(files.get(0).getPath());
291                Node node = path.getTop();
292                MultiParamLoader loader = new MultiParamLoader();
293                loader.setNewSource(files.get(0).getContent());
294                loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
295
296                try {
297                        if (node.getParam() instanceof ObjectParam) {
298                                loader.addAccessInterface(bindAccess(node));
299                                loader.go();
300                                fireFetch(path);
301        //            for (NodeListener l : listeners) {
302        //                l.onChange(this);
303        //            }
304                                return;
305                        }
306
307                        ListAccess listAccess = ((ListAccess)bindAccess(node));
308                        assert listAccess != null;
309                        listAccess.clearValues();
310
311                        AccessInterface elementAccess = listAccess.getElementAccess();
312                        loader.addAccessInterface(elementAccess);
313                        MultiParamLoader.Status status;
314                        while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
315                                if (status == MultiParamLoader.Status.AfterObject) {
316                                        AccessInterface accessInterface = loader.getLastAccessInterface();
317
318                                        String id = listAccess.computeIdentifierFor(accessInterface.getSelected());
319                                        //TODO listAccessParam
320                                        Param param = Param.build().type("o " + accessInterface.getId()).id(id).finish();
321                                        Object child = accessInterface.getSelected();
322                                        accessInterface.select(null);
323                                        assert child != null;
324                                        bindAccess(node).set((ValueParam) param, child);
325                                }
326                        }
327
328                        fireFetch(path);
329        //        for (NodeListener l : listeners) {
330        //            l.onChange(this);
331        //        }
332                } catch (Exception e) {
333                        log.error("exception occurred while loading: " + e);
334                }
335
336        }
337
338        public static Iterator<String> splitPath(String path) {
339                List<String> list = new LinkedList<String>();
340                for (String s : path.split("/")) {
341                        if (!s.isEmpty()) {
342                                list.add(s);
343                        }
344                }
345                return list.iterator();
346        }
347
348        public Registry getRegistry() {
349                return registry;
350        }
351
352        public Path getPath(String textual) {
353                return Path.build().resolve(this, textual).finish();
354        }
355
356        public Path getRootPath() {
357                return getPath("/");
358        }
359
360        @Override
361        @OverridingMethodsMustInvokeSuper
362        protected void firstTask() {
363                root = new Node(Param.build().name("Instance").id(getName()).type("o"), null);
364                com.framsticks.model.Package.register(registry);
365        }
366
367}
368
Note: See TracBrowser for help on using the repository browser.