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

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

HIGHLIGHTS:

CHANGELOG:
Make ProcedureParam? hold only ValueParams?.

Use id instead of names when naming gui components internally.

Basic procedure calling in GUI.

The actual procedure call is currently only backed
by the ObjectInstance?.

Add UnimplementedException?.

Improve naming of various gui elements.

Allow easy navigating in FEST Swing testing.

Add optional explicit order attribute to FramsClassAnnotation?.

That's because java reflection does return declared members
in any specific order. That ordering is needed only for
classes that have no representation in framsticks and need
a deterministic ordering of params.

Add ControlOwner? interface.

Add test for procedure calling in Browser.

First version of ParamAnnotation? for procedures.

Development of ProcedureParam?.

Add draft version of ProcedureParam? implementation in ReflectionAccess?.

Allow viewing FramsClasses? in gui Browser.

Extract ResourceBuilder? from ModelBuilder?.

Remove internalId from Param.

It was currently completely not utilised. Whether it is still needed
after introduction of ParamAnnotation? is arguable.

Add remaining param attributes to ParamAnnotation?.

Change AutoBuilder? semantics.

AutoBuilder? returns list of objects that are to be appended
with methods @AutoAppendAnnotation?.

This allows to omit explicit addition of ModelPackage? to instance
if the instance uses ModelBuilder? (registration of ModelPackage? comes
from schema).

Fix params ordering problem in auto created FramsClasses?.

Improve ObjectInstance?.

Several fixes to ModelBuilder?.

Improve test for ObjectInstance? in Browser.

Make initialization of robot static.

With robot recreated for second browser test, the test hanged
deep in AWT.

Add base convenience base test for Browser tests.

More tests to ObjectInstance?.

Rename Dispatcher.invokeLater() to dispatch().

Add assertDispatch.

It allows assertions in other threads, than TestNGInvoker.
Assertions are gathered after each method invocation and rethrown.

Use timeOut annotation attribute for tests involving some waiting.

Remove firstTask method (merge with joinableStart).

Clean up leftovers.

Remove unused FavouritesXMLFactory (the reading part is already
completely done with generic XmlLoader?, and writing part will be done
based on the same approach if needed).
Move UserFavourite? to the com.framsticks.gui.configuration package.

Remove GenotypeBrowser? as to specific.

This functionality will be available in ObjectInstance?.

Add interface ParamsPackage?.

Package containing registration of Java classes meant to use with
ReflectionAccess? may be in Instance using configuration.

Minor changes.

Make Group immutable.

Add AutoBuilder? interface extending Builder - only those would
be used to automatically build from XML.

Fix groups in FramsClass?.

Minor naming cleanup in Registry.

Add ModelComponent? interface.

All class creating the Model are implementing that interface.

Extract Model.build into ModelBuilder?.

ModelBuilder? will be compatible with other builders
and allow using it from configuration.

Fix NeuroConnection?.

Add synchronous get operation for dispatchers.

Rename JoinableMonitor? to Monitor.

Add ObjectInstance?.

This class is mainly for demonstration
and testing purposes.

Improve FramsServer? runner.

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