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

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

HIGHLIGHTS:

  • add proper exception passing between communication sides:

if exception occur during handling client request, it is
automatically passed as comment to error response.

it may be used to snoop communication between peers

  • fix algorithm choosing text controls in GUI
  • allow GUI testing in virtual frame buffer (xvfb)

FEST had some problem with xvfb but workaround was found

supports tab-completion based on requests history

CHANGELOG:
Further improve handling of exceptions in GUI.

Add StatusBar? implementing ExceptionResultHandler?.

Make completion processing asynchronous.

Minor changes.

Improve completion in console.

Improve history in InteractiveConsole?.

First working version of DirectConsole?.

Minor changes.

Make Connection.address non final.

It is more suitable to use in configuration.

Improvement of consoles.

Improve PopupMenu? and closing of FrameJoinable?.

Fix BrowserTest?.

Found bug with FEST running under xvfb.

JButtonFixture.click() is not working under xvfb.
GuiTest? has wrapper which uses JButton.doClick() directly.

Store CompositeParam? param in TreeNode?.

Simplify ClientSideManagedConnection? connecting.

There is now connectedFunctor needed, ApplicationRequests? can be
send right after creation. They are buffered until the version
and features are negotiated.

Narow down interface of ClientSideManagedConnection?.

Allow that connection specialization send only
ApplicationRequests?.

Improve policy of text control choosing.

Change name of Genotype in BrowserTest?.

Make BrowserTest? change name of Genotype.

Minor change.

First working draft of TrackConsole?.

Simplify Consoles.

More improvements with gui joinables.

Unify initialization on gui joinables.

More rework of Frame based entities.

Refactorize structure of JFrames based entities.

Extract GuiTest? from BrowserBaseTest?.

Reorganize Console classes structure.

Add Collection view to JoinableCollection?.

Configure timeout in testing.

Minor changes.

Rework connections hierarchy.

Add Mode to the get operation.

Make get and set in Tree take PrimitiveParam?.

Unify naming of operations.

Make RunAt? use the given ExceptionHandler?.

It wraps the virtual runAt() method call with
try-catch passing exception to handler.

Force RunAt? to include ExceptionHandler?.

Improve ClientAtServer?.

Minor change.

Another sweep with FindBugs?.

Rename Instance to Tree.

Minor changes.

Minor changes.

Further clarify semantics of Futures.

Add FutureHandler?.

FutureHandler? is refinement of Future, that proxifies
exception handling to ExceptionResultHandler? given
at construction time.

Remove StateFunctor? (use Future<Void> instead).

Make Connection use Future<Void>.

Unparametrize *ResponseFuture?.

Remove StateCallback? not needed anymore.

Distinguish between sides of ResponseFuture?.

Base ResponseCallback? on Future (now ResponseFuture?).

Make asynchronous store taking Future for flags.

Implement storeValue in ObjectInstance?.

File size: 6.5 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;
8
9import java.util.Iterator;
10import java.util.LinkedList;
11import java.util.List;
12
13import javax.annotation.Nonnull;
14import javax.annotation.concurrent.Immutable;
15
16import org.apache.commons.collections.ListUtils;
17
18/**
19 * @author Piotr Sniegowski
20 */
21@Immutable
22public final class Path {
23        // private final static Logger log = Logger.getLogger(Path.class.getName());
24
25        final Tree tree;
26        final String textual;
27        final LinkedList<Node> nodes;
28
29        protected static Object getKnownChild(Tree tree, AccessInterface access, CompositeParam param) {
30                Object child = access.get(param, Object.class);
31                if (child == null) {
32                        return null;
33                }
34                try {
35                        tree.prepareAccess(param);
36                        return child;
37                } catch (FramsticksException e) {
38                }
39                return null;
40        }
41
42        /**
43         * @param tree
44         * @param textual
45         * @param nodes
46         */
47        Path(Tree tree, String textual, LinkedList<Node> nodes) {
48                this.tree = tree;
49                this.textual = textual;
50                this.nodes = nodes;
51        }
52
53        public Path appendNode(Node node) {
54                assert isResolved();
55                return new PathBuilder().tree(tree).textual(textual + ((size() == 1) ? "" : "/") + node.getParam().getId()).add(nodes).add(node).finish();
56        }
57
58        public Path appendParam(CompositeParam param) {
59                assert isResolved();
60                return appendNode(new Node(param, null));
61        }
62
63        public static class PathBuilder {
64
65                Tree tree;
66                String textual;
67                final LinkedList<Node> nodes = new LinkedList<Node>();
68
69                public Path finish() {
70                        assert tree != null;
71                        assert textual != null;
72                        return new Path(tree, textual, nodes);
73                }
74
75                public PathBuilder()
76                {
77                }
78
79                public PathBuilder tree(Tree tree) {
80                        this.tree = tree;
81                        return this;
82                }
83
84                public PathBuilder textual(String textual) {
85                        this.textual = textual;
86                        return this;
87                }
88
89                public PathBuilder add(List<Node> nodes) {
90                        this.nodes.addAll(nodes);
91                        return this;
92                }
93
94                public PathBuilder add(Node node) {
95                        this.nodes.add(node);
96                        return this;
97                }
98
99                public PathBuilder setLast(Object object) {
100                        Node n = nodes.pollLast();
101                        nodes.add(new Node(n.getParam(), object));
102                        return this;
103                }
104
105                public PathBuilder buildUpTo(List<Node> nodes, Node node) {
106                        StringBuilder b = new StringBuilder();
107                        boolean add = false;
108                        for (Node n : nodes) {
109                                this.nodes.add(n);
110                                if (add) {
111                                        b.append("/").append(n.getParam().getId());
112                                }
113                                add = true;
114                                if (n == node) {
115                                        break;
116                                }
117                        }
118                        this.textual = (nodes.size() == 1) ? "/" : b.toString();
119                        return this;
120                }
121
122                public static Iterator<String> splitPath(String path) {
123                        List<String> list = new LinkedList<String>();
124                        for (String s : path.split("/")) {
125                                if (!s.isEmpty()) {
126                                        list.add(s);
127                                }
128                        }
129                        return list.iterator();
130                }
131
132                public PathBuilder resolve(@Nonnull Tree tree, String textual) {
133
134                        assert nodes.isEmpty();
135                        assert tree.isActive();
136                        this.tree = tree;
137
138                        nodes.add(tree.getRoot());
139                        Node current = tree.getRoot();
140
141                        StringBuilder b = new StringBuilder();
142                        Iterator<String> i = splitPath(textual);
143                        while (i.hasNext() && current.getObject() != null) {
144                                AccessInterface access = tree.prepareAccess(current.getParam());
145                                if (access == null) {
146                                        break;
147                                }
148                                String e = i.next();
149                                Param p = access.getParam(e);
150                                if (!(p instanceof CompositeParam)) {
151                                        //entries.add(new Entry());
152                                        break;
153                                }
154                                CompositeParam c = (CompositeParam)p;
155                                b.append("/").append(e);
156                                access.select(current.getObject());
157                                current = new Node(c, getKnownChild(tree, access, c));
158                                nodes.add(current);
159                        }
160                        this.textual = (nodes.size() == 1) ? "/" : b.toString();
161
162                        return this;
163                }
164        }
165
166        public static PathBuilder build() {
167                return new PathBuilder();
168        }
169
170        public Path appendResolution(Object object) {
171                assert !isResolved();
172                Path result = new PathBuilder().textual(textual).tree(tree).add(nodes).setLast(object).finish();
173                assert size() == result.size();
174                return result;
175        }
176
177        public final Object getTopObject() {
178                return getTop().getObject();
179        }
180
181        public final Node getTop() {
182                return nodes.getLast();
183        }
184
185        public final Node getUnder() {
186                assert nodes.size() >= 2;
187                return nodes.get(nodes.size() - 2);
188        }
189
190        public final String getTextual() {
191                return textual;
192        }
193
194        public String toString() {
195                return tree + textual + (!isResolved() ? "!" : "");
196        }
197
198        public String getFullTextual() {
199                return tree.getName() + textual;
200        }
201
202        public final int size() {
203                assert Dispatching.isThreadSafe();
204                return nodes.size();
205        }
206
207        public final boolean isResolved() {
208                assert Dispatching.isThreadSafe();
209                return getTop().getObject() != null;
210        }
211
212        public final boolean isResolved(String textual) {
213                assert Dispatching.isThreadSafe();
214                return isTheSame(textual) && isResolved();
215        }
216
217        public final boolean isTheSame(String textual) {
218                assert Dispatching.isThreadSafe();
219                return this.textual.equals(textual);
220        }
221
222        public final @Nonnull Tree getTree() {
223                assert Dispatching.isThreadSafe();
224                return tree;
225        }
226
227        public Path tryResolveIfNeeded() {
228                if (isResolved()) {
229                        return this;
230                }
231                return tryFindResolution();
232        }
233
234        /** Attach resolution at end, if available.
235         *
236         * @return Modified path, if resolution was available, this otherwise.
237         */
238        public Path tryFindResolution() {
239                assert tree.isActive();
240                assert !isResolved();
241                if (size() == 1) {
242                        return Path.build().resolve(tree, "/").finish();
243                }
244                Object child = getKnownChild(tree, TreeOperations.bindAccess(tree, getUnder()), getTop().getParam());
245                if (child == null) {
246                        return this;
247                }
248                return appendResolution(child);
249        }
250
251        public boolean matches(Path p) {
252                assert Dispatching.isThreadSafe();
253                assert tree == p.tree;
254                Iterator<Node> a = nodes.iterator();
255                Iterator<Node> b = p.nodes.iterator();
256                while (a.hasNext() && b.hasNext()) {
257                        Node an = a.next();
258                        Node bn = b.next();
259                        if (an.object != bn.object) {
260                                return false;
261                        }
262                }
263                return a.hasNext() == b.hasNext();
264        }
265
266        public String getLastElement() {
267                return getTop().getParam().getId();
268        }
269
270        public final boolean isOwner(Tree tree) {
271                return this.tree == tree;
272        }
273
274        @SuppressWarnings("unchecked")
275        public
276        List<Node> getNodes() {
277                return ListUtils.unmodifiableList(nodes);
278        }
279
280        public void assureResolved() {
281                if (!isResolved()) {
282                        throw new FramsticksException().msg("path is not resolved").arg("path", this);
283                }
284        }
285
286        public static Path to(@Nonnull Tree tree, String textual) {
287                return Path.build().resolve(tree, textual).finish();
288        }
289}
290
Note: See TracBrowser for help on using the repository browser.