source: java/main/src/main/java/com/framsticks/core/TreeOperations.java @ 99

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

HIGHLIGTS:

  • complete events implementation
  • add CLI in Java Framsticks server
  • add automatic registration for events in GUI
  • improve objects fetching (object are never overwritten with new instances)
  • properly react for ListChange? events
  • add ListPanel? with table view
    • columns to be shown may be statically specified in configuration
    • currently modyfying data through tables is not available
  • improve maven configuration
    • configuration file may be specified without touching pom.xml

CHANGELOG:
Extract constants from Flags into ParamFlags? and SetStateFlags?.

Extract flags I/O to FlagsUtils? class.

Configured maven to exec given resource configuration.

For example:
mvn exec:exec -Dframsticks.config=/configs/managed-console.xml

Cleanup pom.xml

Rename ObjectTree? to LocalTree? (also make LocalTree? and RemoteTree? final).

Minor change.

Add maximum number of columns in ListPanelProvider?.

Improve ColumnsConfig? interpretation.

Automatically fill FramsClass?.name if trying to construct empty.

Improve identitifer case mangling in XmlLoader?.

Introduce configurable ColumnsConfig?.

Draft working version of ListPanel?.

Table is being shown (although empty).

More improvements to table building.

Move some functionality from Frame to TreeModel?.

Move tree classes in gui to separate package.

Remove old table related classes.

Add draft implementation of TableModel?.

Redirect ParamBuilder?.forAccess to AccessInterface?.

Optimize ParamBuilder?.forAccess()

Do not clear list when loading.

Do not load fetched values directly.

Implement different AccessInterface? copying policy.

Optimize fetching values routine.

Remove Mode enum (work out get semantics).

Some improvements to ListChange? handling.

Improve UniqueListAccess?.

Add reaction for ListChanges? in the TreeNode?.

EventListeners? are being added in the TreeNode?.

Listeners for ListParams? are now very naive (they download
whole list).

Automatially register on events in GUI.

Events are working in RemoteTree? and Server.

Move listeners to the ClientSideManagedConnection?.

Remove old classes responsible for event subscriptions.

Improve event reading.

Improve events handling at server side.

Add register attribute in FramsClassAnnotation?
to automatically also register other classes.

Registering events works.

Setup for remote listeners registration.

More improvements.

Minor changes.

Add rootTree to the ClientAtServer?.

Moving CLI to the ClientAtServer?.

Fix bug: use Void.TYPE instead of Void.class

More development around CLI.

  • Improve Path resolving.

Add synthetic root to ObjectTree?.

It is needed to allow sybling for the original root
that would containg CLI.

Some work with registering events in RemoteTree?.

Draft implementation of listener registering in RemoteTree?.

Support events registration in the ObjectTree?.

Add events support to ReflectionAccess?.

EventParam? is recognized by ParamCandidate?.

Prepare interface for Events across project.

Add EventListener? and API for listeners in Tree.

File size: 8.1 KB
Line 
1package com.framsticks.core;
2
3
4import java.util.HashSet;
5import java.util.List;
6import java.util.Set;
7
8import javax.annotation.Nonnull;
9
10import org.apache.log4j.Logger;
11
12import com.framsticks.communication.File;
13import com.framsticks.params.AccessInterface;
14import com.framsticks.params.EventListener;
15import com.framsticks.params.FramsClass;
16import com.framsticks.params.ListAccess;
17import com.framsticks.params.Param;
18import com.framsticks.params.PrimitiveParam;
19import com.framsticks.params.UniqueListAccess;
20import com.framsticks.params.Util;
21import com.framsticks.params.types.EventParam;
22import com.framsticks.params.types.ObjectParam;
23import com.framsticks.params.types.ProcedureParam;
24import com.framsticks.parsers.Loaders;
25import com.framsticks.parsers.MultiParamLoader;
26import com.framsticks.util.FramsticksException;
27import com.framsticks.util.dispatching.Future;
28import com.framsticks.util.dispatching.FutureHandler;
29import com.framsticks.util.dispatching.RunAt;
30
31import static com.framsticks.util.dispatching.Dispatching.*;
32
33public final class TreeOperations {
34
35        private static final Logger log = Logger.getLogger(TreeOperations.class);
36
37        private TreeOperations() {
38        }
39
40        public static @Nonnull FramsClass processFetchedInfo(Tree tree, File file) {
41                assert tree.isActive();
42                FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
43                log.debug("process fetched info for " + tree + ": " + framsClass);
44                tree.putInfoIntoCache(framsClass);
45                return framsClass;
46        }
47
48        public static void processFetchedValues(Path path, List<File> files) {
49                Tree tree = path.getTree();
50                assert tree.isActive();
51                assert files.size() == 1;
52                assert path.isTheSame(files.get(0).getPath());
53
54                if (!path.isResolved()) {
55                        AccessInterface access = tree.prepareAccess(path.getTop().getParam());
56                        Object child = access.createAccessee();
57                        assert child != null;
58                        if (path.size() == 1) {
59                                tree.assignRootObject(child);
60                        } else {
61                                bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
62                        }
63                        path = path.appendResolution(child);
64                }
65
66                log.debug("process fetched values: " + path);
67                Node node = path.getTop();
68                MultiParamLoader loader = new MultiParamLoader();
69                loader.setNewSource(files.get(0).getContent());
70                loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
71
72                try {
73                        if (node.getParam() instanceof ObjectParam) {
74                                loader.addAccessInterface(bindAccess(node));
75                                loader.go();
76                                return;
77                        }
78
79                        ListAccess listAccess = (ListAccess) bindAccess(node);
80
81                        Set<String> oldValuesIds = new HashSet<>();
82                        for (Param p : listAccess.getParams()) {
83                                oldValuesIds.add(p.getId());
84                        }
85
86                        // listAccess.clearValues();
87
88                        AccessInterface elementAccess = listAccess.getElementAccess();
89                        AccessInterface clonerInterface = elementAccess.cloneAccess();
90
91                        loader.addAccessInterface(elementAccess);
92                        MultiParamLoader.Status status;
93                        int number = 0;
94                        while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
95                                if (status == MultiParamLoader.Status.AfterObject) {
96                                        AccessInterface accessInterface = loader.getLastAccessInterface();
97
98                                        String id;
99                                        if (listAccess instanceof UniqueListAccess) {
100                                                id = ((UniqueListAccess) listAccess).computeIdentifierFor(accessInterface.getSelected());
101                                        } else {
102                                                id = Integer.toString(number);
103                                        }
104                                        ++number;
105
106                                        Object childTo = listAccess.get(id, Object.class);
107                                        boolean newOne;
108                                        if (childTo == null) {
109                                                childTo = clonerInterface.createAccessee();
110                                                newOne = true;
111                                        } else {
112                                                assert oldValuesIds.contains(id);
113                                                newOne = false;
114                                        }
115                                        oldValuesIds.remove(id);
116                                        clonerInterface.select(childTo);
117                                        Util.takeAllNonNullValues(clonerInterface, accessInterface);
118                                        if (newOne) {
119                                                listAccess.set(id, childTo);
120                                        }
121
122                                        // listAccess.set(id, accessInterface.getSelected());
123                                        accessInterface.select(null);
124
125                                }
126                        }
127                        /** It looks tricky for ArrayListAccess but should also work.
128                         *
129                         * They should be sorted.
130                         */
131                        for (String id : oldValuesIds) {
132                                listAccess.set(id, null);
133                        }
134
135                } catch (FramsticksException e) {
136                        throw new FramsticksException().msg("exception occurred while loading").cause(e);
137                }
138        }
139
140        public static FramsClass getInfo(Path path) {
141                Tree tree = path.getTree();
142                assert tree.isActive();
143                log.debug("get info for: " + path);
144                final String name = path.getTop().getParam().getContainedTypeName();
145                return tree.getInfoFromCache(name);
146        }
147
148        public static void findInfo(final Path path, final Future<FramsClass> future) {
149                log.debug("find info for: " + path);
150                try {
151                        Tree tree = path.getTree();
152                        assert tree.isActive();
153                        final FramsClass framsClass = getInfo(path);
154                        if (framsClass != null) {
155                                future.pass(framsClass);
156                                return;
157                        }
158                        tree.info(path, future);
159                } catch (FramsticksException e) {
160                        future.handle(e);
161                }
162        }
163
164
165
166        public static @Nonnull AccessInterface bindAccess(Tree tree, String path) {
167                log.debug("bind access for textual: " + path + " in " + tree);
168                return bindAccess(Path.to(tree, path));
169        }
170
171        public static @Nonnull AccessInterface bindAccess(Node node) {
172                Tree tree = node.getTree();
173                assert tree.isActive();
174                assert node.getObject() != null;
175
176                try {
177                        return tree.prepareAccess(node.getParam()).select(node.getObject());
178                } catch (FramsticksException e) {
179                        throw new FramsticksException().msg("failed to prepare access for param").arg("param", node.getParam()).cause(e);
180                        // log.error("failed to bind access for " + node.getParam() + ": " + e);
181                }
182        }
183
184        public static @Nonnull AccessInterface bindAccess(Path path) {
185                assert path.getTree().isActive();
186                path.assureResolved();
187                log.debug("bind access for: " + path);
188                return bindAccess(path.getTop());
189        }
190
191        public static void set(final Path path, final PrimitiveParam<?> param, final Object value, final Future<Integer> future) {
192                final Tree tree = path.getTree();
193
194                dispatchIfNotActive(tree, new RunAt<Tree>(future) {
195                        @Override
196                        protected void runAt() {
197                                tree.set(path, param, value, future);
198                        }
199                });
200        }
201
202        public static void call(final Path path, final ProcedureParam param, final Object[] arguments, final Future<Object> future) {
203                final Tree tree = path.getTree();
204
205                dispatchIfNotActive(tree, new RunAt<Tree>(future) {
206                        @Override
207                        protected void runAt() {
208                                tree.call(path, param, arguments, future);
209                        }
210                });
211        }
212
213        public static <A> void addListener(final Path path, final EventParam param, final EventListener<A> listener, final Class<A> argument, final Future<Void> future) {
214                final Tree tree = path.getTree();
215
216                dispatchIfNotActive(tree, new RunAt<Tree>(future) {
217                        @Override
218                        protected void runAt() {
219                                tree.addListener(path, param, listener, argument, future);
220                        }
221                });
222        }
223
224        public static void removeListener(final Path path, final EventParam param, final EventListener<?> listener, final Future<Void> future) {
225                final Tree tree = path.getTree();
226
227                dispatchIfNotActive(tree, new RunAt<Tree>(future) {
228                        @Override
229                        protected void runAt() {
230                                tree.removeListener(path, param, listener, future);
231                        }
232                });
233        }
234
235
236        /**
237         *
238         * If StackOverflow occurs in that loop in LocalTree it is probably caused
239         * the by the fact, that get operation may find the object, but Path resolution
240         * cannot.
241         * */
242        public static void tryGet(final Tree tree, final String targetPath, final Future<Path> future) {
243                log.debug("resolve textual: " + targetPath + " for " + tree);
244                dispatchIfNotActive(tree, new RunAt<Tree>(future) {
245
246                        @Override
247                        protected void runAt() {
248                                final Path path = Path.tryTo(tree, targetPath).tryResolveIfNeeded();
249                                log.debug("found: " + path);
250                                if (path.isResolved()) {
251                                        future.pass(path);
252                                        return;
253                                }
254
255                                tree.get(path, new FutureHandler<Path>(future) {
256                                        @Override
257                                        protected void result(Path result) {
258                                                // if (result.isResolved(targetPath)) {
259                                                //      future.pass(result);
260                                                //      return;
261                                                // }
262                                                log.debug("retrying resolve textual: " + targetPath + " for " + tree + " with " + result);
263                                                tryGet(tree, targetPath, future);
264                                        }
265                                });
266                        }
267                });
268        }
269
270        public static FramsClass getInfoFromCache(Path path) {
271                assert path.getTree().isActive();
272                return path.getTree().getInfoFromCache(path.getTop().getParam().getContainedTypeName());
273        }
274
275}
Note: See TracBrowser for help on using the repository browser.