source: java/main/src/main/java/com/framsticks/core/Path.java @ 101

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

HIGHLIGHTS:

  • improve tree side notes
  • improve GUI layout
  • add foldable list of occured events to EventControl?
  • improve automatic type conversion in proxy listeners
  • implement several Access functionalities as algorithms independent of Access type
  • introduce draft base classes for distributed experiments
  • automatically register dependant Java classes to FramsClass? registry
  • add testing prime experiment and configuration
  • simplify and improve task dispatching

CHANGELOG:
Improve task dispatching in RemoteTree?.

GUI no longer hangs on connection problems.

Make all dispatchers joinables.

Refactorize Thread dispatcher.

Remove Task and PeriodicTask?.

Use Java utilities in those situations.

Reworking tasks dispatching.

Fix bug in EventControl? listener dispatching.

Minor improvements.

Add testing configuration for ExternalProcess? in GUI.

More improvement to prime.

Support for USERREADONLY in GUI.

Add that flag to various params in Java classes.

Remove redundant register clauses from several FramsClassAnnotations?.

Automatically gather and register dependant classes.

Add configuration for prime.

Improve Simulator class.

Add prime.xml configuration.

Introduce draft Experiment and Simulator classes.

Add prime experiment tests.

Enclose typical map with listeners into SimpleUniqueList?.

Needfile works in GUI.

Improve needfile handling in Browser.

More improvement with NeedFile?.

Implementing needfile.

Update test.

Rename ChangeEvent? to TestChangeEvent?.

Automatic argument type search in RemoteTree? listeners.

MultiParamLoader? uses AccessProvider?. By default old implementation
enclosed in AccessStash? or Registry.

Minor changes.

Rename SourceInterface? to Source.

Also improve toString of File and ListSource?.

Remove unused SimpleSource? class.

Add clearing in HistoryControl?.

Show entries in table at EventControl?.

Improve EventControl?.

Add listeners registration to EventControl?.

Add foldable table to HistoryControl?.

Add control row to Procedure and Event controls.

Improve layout of controls.

Another minor change to gui layout.

Minor improvement in the SliderControl?.

Minor changes.

Move ReflectionAccess?.Backend to separate file.

It was to cluttered.

Cleanup in ReflectionAccess?.

Move setMin, setMax, setDef to AccessOperations?.

Extract loading operation into AccessOperations?.

Append Framsticks to name of UnsupportedOperationException?.

The java.lang.UnsupportedOperationException? was shadowing this class.

Rename params.Util to params.ParamsUtil?.

Several improvements.

Minor changes.

Implement revert functionality.

Improve local changes management.

Minor improvement.

Remove methods rendered superfluous after SideNoteKey? improvement.

Improve SideNoteKey?.

It is now generic type, so explicit type specification at
call site is no more needed.

Introduce SideNoteKey? interface.

Only Objects implementing that key may be used as side note keys.

Minor improvements.

Use strings instead of ValueControls? in several gui mappings.

File size: 8.9 KB
Line 
1package com.framsticks.core;
2
3import com.framsticks.params.Access;
4import com.framsticks.params.CompositeParam;
5import com.framsticks.params.Param;
6import com.framsticks.util.FramsticksException;
7import com.framsticks.util.dispatching.Dispatching;
8import com.framsticks.util.dispatching.ExceptionResultHandler;
9import com.framsticks.util.dispatching.IgnoreExceptionHandler;
10import com.framsticks.util.lang.Pair;
11
12import java.util.Iterator;
13import java.util.LinkedList;
14import java.util.List;
15import java.util.regex.Pattern;
16
17import javax.annotation.Nonnull;
18import javax.annotation.concurrent.Immutable;
19
20import org.apache.commons.collections.ListUtils;
21
22/**
23 * @author Piotr Sniegowski
24 */
25@Immutable
26public final class Path {
27        // private final static Logger log = LogManager.getLogger(Path.class.getName());
28
29        final Tree tree;
30        final String textual;
31        final LinkedList<Node> nodes;
32
33        public static final SideNoteKey<CompositeParam> OBJECT_PARAM_KEY = SideNoteKey.make(CompositeParam.class);
34
35        protected static Object getKnownChild(Tree tree, Access access, CompositeParam param, ExceptionResultHandler handler) {
36                Object child = access.get(param, Object.class);
37                if (child == null) {
38                        return null;
39                }
40                try {
41                        tree.prepareAccess(param);
42                        tree.putSideNote(child, OBJECT_PARAM_KEY, param);
43                        return child;
44                } catch (FramsticksException e) {
45                        handler.handle(e);
46                }
47                return null;
48        }
49
50        /**
51         * @param tree
52         * @param textual
53         * @param nodes
54         */
55        Path(Tree tree, String textual, LinkedList<Node> nodes) {
56                this.tree = tree;
57                this.textual = textual;
58                this.nodes = nodes;
59        }
60
61        public Path appendNode(Node node) {
62                assert isResolved();
63                return new PathBuilder().tree(tree).textual(textual + ((size() == 1) ? "" : "/") + node.getParam().getId()).add(nodes).add(node).finish();
64        }
65
66        public Path appendParam(CompositeParam param) {
67                assert isResolved();
68                return appendNode(new Node(tree, param, null));
69        }
70
71        public static class PathBuilder {
72
73                Tree tree;
74                String textual;
75                final LinkedList<Node> nodes = new LinkedList<Node>();
76
77                public Path finish() {
78                        assert tree != null;
79                        assert textual != null;
80                        return new Path(tree, textual, nodes);
81                }
82
83                public PathBuilder()
84                {
85                }
86
87                public PathBuilder tree(Tree tree) {
88                        this.tree = tree;
89                        return this;
90                }
91
92                public PathBuilder textual(String textual) {
93                        this.textual = textual;
94                        return this;
95                }
96
97                public PathBuilder add(List<Node> nodes) {
98                        this.nodes.addAll(nodes);
99                        return this;
100                }
101
102                public PathBuilder add(Node node) {
103                        this.nodes.add(node);
104                        return this;
105                }
106
107                public PathBuilder setLast(Object object) {
108                        Node n = nodes.pollLast();
109                        nodes.add(new Node(n.getTree(), n.getParam(), object));
110                        return this;
111                }
112
113                public PathBuilder buildUpTo(List<Node> nodes, Node node) {
114                        StringBuilder b = new StringBuilder();
115                        boolean add = false;
116                        for (Node n : nodes) {
117                                this.nodes.add(n);
118                                if (add) {
119                                        b.append("/").append(n.getParam().getId());
120                                }
121                                add = true;
122                                if (n == node) {
123                                        break;
124                                }
125                        }
126                        this.textual = (nodes.size() == 1) ? "/" : b.toString();
127                        return this;
128                }
129
130                public static Iterator<String> splitPath(String path) {
131                        List<String> list = new LinkedList<String>();
132                        for (String s : path.split("/")) {
133                                if (!s.isEmpty()) {
134                                        list.add(s);
135                                }
136                        }
137                        return list.iterator();
138                }
139
140                public PathBuilder resolve(@Nonnull Tree tree, String textual) {
141                        return resolve(tree, textual, IgnoreExceptionHandler.getInstance());
142                }
143
144                public PathBuilder resolve(@Nonnull Tree tree, String textual, ExceptionResultHandler handler) {
145
146                        assert nodes.isEmpty();
147                        assert tree.isActive();
148                        this.tree = tree;
149
150                        Node current = tree.getAssignedRoot();
151                        nodes.add(current);
152
153                        StringBuilder b = new StringBuilder();
154                        Iterator<String> i = splitPath(textual);
155                        while (i.hasNext() && current.getObject() != null) {
156                                Access access = TreeOperations.bindAccess(current);// tree.prepareAccess(current.getParam());
157                                String e = i.next();
158                                Param p = access.getParam(e);
159                                if (p == null) {
160                                        break;
161                                }
162                                if (!(p instanceof CompositeParam)) {
163                                        throw new FramsticksException().msg("param is not a composite").arg("param", p).arg("tree", tree).arg("textual", textual).arg("access", access);
164                                }
165                                CompositeParam c = (CompositeParam) p;
166                                b.append("/").append(e);
167                                access.select(current.getObject());
168                                tree.putSideNote(current.getObject(), OBJECT_PARAM_KEY, current.getParam());
169                                current = new Node(current.getTree(), c, getKnownChild(tree, access, c, handler));
170                                nodes.add(current);
171                        }
172                        this.textual = (nodes.size() == 1) ? "/" : b.toString();
173
174                        return this;
175                }
176        }
177
178        public static PathBuilder build() {
179                return new PathBuilder();
180        }
181
182        public Path appendResolution(Object object) {
183                assert !isResolved();
184                Path result = new PathBuilder().textual(textual).tree(tree).add(nodes).setLast(object).finish();
185                assert size() == result.size();
186                return result;
187        }
188
189        public final Object getTopObject() {
190                return getTop().getObject();
191        }
192
193        public final Node getTop() {
194                return nodes.getLast();
195        }
196
197        public final Node getUnder() {
198                assert nodes.size() >= 2;
199                return nodes.get(nodes.size() - 2);
200        }
201
202        public final String getTextual() {
203                return textual;
204        }
205
206        public String toString() {
207                return tree + textual + (!isResolved() ? "!" : "");
208        }
209
210        public String getFullTextual() {
211                return tree.getName() + textual;
212        }
213
214        public final int size() {
215                assert Dispatching.isThreadSafe();
216                return nodes.size();
217        }
218
219        public final boolean isResolved() {
220                assert Dispatching.isThreadSafe();
221                return getTop().getObject() != null;
222        }
223
224        public final boolean isResolved(String textual) {
225                assert Dispatching.isThreadSafe();
226                return isTheSame(textual) && isResolved();
227        }
228
229        public final boolean isTheSame(String textual) {
230                assert Dispatching.isThreadSafe();
231                return this.textual.equals(textual);
232        }
233
234        public final boolean isTheSameTextually(Path path) {
235                assert Dispatching.isThreadSafe();
236                return (tree == path.getTree()) && textual.equals(path.getTextual());
237        }
238
239        public final @Nonnull Tree getTree() {
240                assert Dispatching.isThreadSafe();
241                return tree;
242        }
243
244        public Path tryResolveIfNeeded() {
245                if (isResolved()) {
246                        return this;
247                }
248                return tryFindResolution();
249        }
250
251        /** Attach resolution at end, if available.
252         *
253         * @return Modified path, if resolution was available, this otherwise.
254         */
255        public Path tryFindResolution() {
256                assert tree.isActive();
257                assert !isResolved();
258                if (size() == 1) {
259                        return Path.build().resolve(tree, "/").finish();
260                }
261                Object child = getKnownChild(tree, TreeOperations.bindAccess(getUnder()), getTop().getParam(), IgnoreExceptionHandler.getInstance());
262                if (child == null) {
263                        return this;
264                }
265                return appendResolution(child);
266        }
267
268
269        public String getLastElement() {
270                return getTop().getParam().getId();
271        }
272
273        public final boolean isOwner(Tree tree) {
274                return this.tree == tree;
275        }
276
277        @SuppressWarnings("unchecked")
278        public
279        List<Node> getNodes() {
280                return ListUtils.unmodifiableList(nodes);
281        }
282
283        public Path assureResolved() {
284                if (!isResolved()) {
285                        throw new FramsticksException().msg("path is not resolved").arg("path", this);
286                }
287                return this;
288        }
289
290        public static Path tryTo(@Nonnull Tree tree, String textual) {
291                return Path.build().resolve(tree, textual).finish();
292        }
293
294        public static Path to(@Nonnull Tree tree, String textual) {
295                Path path = tryTo(tree, textual);
296                if (path.getTextual().equals(textual)) {
297                        return path;
298                }
299                throw new FramsticksException().msg("failed to create path").arg("textual", textual).arg("result", path).arg("tree", tree);
300        }
301
302        public boolean isTheSameObjects(Path path) {
303                if (tree != path.getTree()) {
304                        return false;
305                }
306                if (size() != path.size()) {
307                        return false;
308                }
309                if (!getTextual().equals(path.getTextual())) {
310                        return false;
311                }
312                Iterator<Node> a = nodes.iterator();
313                Iterator<Node> b = path.getNodes().iterator();
314                while (a.hasNext()) {
315                        assert b.hasNext();
316                        if (a.next() != b.next()) {
317                                return false;
318                        }
319                }
320                return true;
321        }
322
323        public static final Pattern pathPattern = Pattern.compile("(\\/)|((\\/[^/]+)+)");
324
325        public static boolean isValidString(String path) {
326                return pathPattern.matcher(path).matches();
327        }
328
329        public static String appendString(String path, String element) {
330                if (path.equals("/")) {
331                        return path + element;
332                }
333                return path + "/" + element;
334        }
335
336        public static Pair<String, String> removeLastElement(String path) {
337                assert isValidString(path);
338                if (path.equals("/")) {
339                        throw new FramsticksException().msg("cannot remove last element from root path");
340                }
341                int index = path.lastIndexOf('/');
342                assert index != -1;
343                if (index == 0) {
344                        return new Pair<String, String>("/", path.substring(1));
345                }
346                return new Pair<String, String>(path.substring(0, index), path.substring(index + 1));
347        }
348
349        public static String validateString(String path) {
350                if (!isValidString(path)) {
351                        throw new FramsticksException().msg("path string validation failured").arg("path", path);
352                }
353                return path;
354        }
355
356
357        // public boolean isEmpty() {
358        //      return nodes.isEmpty();
359        // }
360}
361
Note: See TracBrowser for help on using the repository browser.