source: java/main/src/main/java/com/framsticks/structure/Path.java @ 105

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

HIGHLIGHTS:

  • import refactorization: move Tree, Path, etc.

from core to structure package

  • initial serialization implementation
  • improve PrimeExperiment? test
  • many organizational changes and convenience improvements

CHANGELOG:
Make registry in AbstractTree? final.

Move most classes from core to structure package.

Minor changes.

Switch names of Future and FutureHandler?.

Rename ExceptionResultHandler? to ExceptionHandler?.

Rename ExceptionHandler? to ExceptionDispatcherHandler?.

Fix bug in ParamCandidate? cache.

Add missing synchronization to the BufferedDispatcher?.

Develop @Serialized support.

Rework serialization further.

Add serialization/deserialization interface to ValueParam?.

Move getStorageType and isNumeric from Param down to params hierarchy.

Minor changes.

Improve param type induction.

Add TestSerializedClass? for testing new serialization.

Add info files gor GenePool? and Population.

Add standard.expt exemplary netfile.

Add type name field to PropertiesObject?.

Use PropertiesObject? for PropertiesAccess? instead of ordinary map.

Hide getFramsClass is several more places.

More unification accross FramsClass?, Access and Path.

Add ParamCollection?.

Simplify interface for getting params from FramsClass?, Access
or Path.

Make Access.call() interface variadic.

Add arguments(args) convenience wrapper around new Object[] {args}.

Upgrade to apache.commons.lang version 3.1

Minor improvement with Response constructors.

Develop proper result printing in ClientAtServer?.

Add experimentNetsave to PrimeExperiment?.

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