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

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

Add new java codebase.

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