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