samer@0
|
1 /*
|
samer@0
|
2 * Node.java
|
samer@0
|
3 *
|
samer@0
|
4 * Copyright (c) 2000, Samer Abdallah, King's College London.
|
samer@0
|
5 * All rights reserved.
|
samer@0
|
6 *
|
samer@0
|
7 * This software is provided AS iS and WITHOUT ANY WARRANTY;
|
samer@0
|
8 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
9 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
10 *
|
samer@0
|
11 * Change history:
|
samer@0
|
12 *
|
samer@0
|
13 * Removed all references to parent nodes - each node now
|
samer@0
|
14 * stores its full name. Uses more memory but simpler in the
|
samer@0
|
15 * long run, I think.
|
samer@0
|
16 */
|
samer@0
|
17
|
samer@0
|
18 package samer.core;
|
samer@0
|
19 import java.util.*;
|
samer@0
|
20
|
samer@0
|
21 /**
|
samer@0
|
22 <p> A Node is essentially a path in a hierarchical
|
samer@0
|
23 name space. Each node is an independent object.
|
samer@0
|
24 A Node can be constructed either with an explicit
|
samer@0
|
25 parent Node, or with an absolute path, or as a child
|
samer@0
|
26 of the current Node maintained by the current Shell.
|
samer@0
|
27 Names are constructed in parts, concatenated with
|
samer@0
|
28 dots, eg,
|
samer@0
|
29 <code>
|
samer@0
|
30 Node A=new Node("top",null);
|
samer@0
|
31 Node B=new Node("middle",A);
|
samer@0
|
32 Node C=new Node("bottom",B);
|
samer@0
|
33 </code>
|
samer@0
|
34 Then node A is "top", node B is "top.middle" and node
|
samer@0
|
35 C is "top.middle.bottom"
|
samer@0
|
36
|
samer@0
|
37 <p>The top level Environment (see Environment)
|
samer@0
|
38 actually uses a nameless top level node: "", so that
|
samer@0
|
39 all fully specified node paths begin with ".", eg
|
samer@0
|
40 ".antelope.gibbon.firebucket"
|
samer@0
|
41 This is so that names that <I>don't</I> start with a
|
samer@0
|
42 dot are treated as relative to the current Environment's node.
|
samer@0
|
43 */
|
samer@0
|
44
|
samer@0
|
45 public class Node implements java.io.Serializable
|
samer@0
|
46 {
|
samer@0
|
47 private final String name;
|
samer@0
|
48
|
samer@0
|
49 /** Construct new Node with given name as a child of the
|
samer@0
|
50 current Environment's base node, ie
|
samer@0
|
51 <code>Shell.env().node()</code>
|
samer@0
|
52 */
|
samer@0
|
53 public Node(String name) {
|
samer@0
|
54 if (name==null || name.equals(""))
|
samer@0
|
55 throw new Error("Node with empty name");
|
samer@0
|
56
|
samer@0
|
57 if (isAbsolute(name)) this.name=name;
|
samer@0
|
58 else this.name=Shell.env().node().fullNameFor(name);
|
samer@0
|
59 }
|
samer@0
|
60
|
samer@0
|
61
|
samer@0
|
62 private Node() { name=""; }
|
samer@0
|
63
|
samer@0
|
64 /** Construct new Node with given name and parent
|
samer@0
|
65 If parent is null, a top level node is created
|
samer@0
|
66 */
|
samer@0
|
67 public Node(String name, Node parent) { this.name = parent.fullName()+"."+name; }
|
samer@0
|
68
|
samer@0
|
69 /** Returns parent Node, or null if no parent */
|
samer@0
|
70 public Node getParent() { return new Node(name.substring(0,name.lastIndexOf('.'))); }
|
samer@0
|
71 public static String lastPart(String str) { return str.substring(1+str.lastIndexOf('.')); }
|
samer@0
|
72 public String fullName() { return name; }
|
samer@0
|
73 public String shortName() { return lastPart(name); }
|
samer@0
|
74
|
samer@0
|
75 /** Return full name of hypothetical Node with given name
|
samer@0
|
76 as a child of this Node, ie, this node's full name + "."+ nm.
|
samer@0
|
77 */
|
samer@0
|
78 public String fullNameFor(String nm) { return name+"."+nm; }
|
samer@0
|
79
|
samer@0
|
80 /** Absolute names start with a . This is only true of the top
|
samer@0
|
81 level Node has an empty name!
|
samer@0
|
82 */
|
samer@0
|
83 public static boolean isAbsolute(String nm) { return (nm.charAt(0)=='.'); }
|
samer@0
|
84
|
samer@0
|
85 /** Returns true if and only if the given name is a child of this one.
|
samer@0
|
86 This is trivially true if the given name is relative (ie doesn't start
|
samer@0
|
87 with a dot). If it does, then the initial substrings must match.
|
samer@0
|
88 */
|
samer@0
|
89 public boolean isSubnode(String nm) {
|
samer@0
|
90 if (!isAbsolute(nm)) return true;
|
samer@0
|
91 return nm.startsWith(name);
|
samer@0
|
92 }
|
samer@0
|
93
|
samer@0
|
94 /** Returns the full name of this node. */
|
samer@0
|
95 public String toString() { return name; }
|
samer@0
|
96
|
samer@0
|
97 /** Returns a NEW top-level node each time it is called. */
|
samer@0
|
98 public static Node root() { return new Node(); }
|
samer@0
|
99 }
|