1 package org.apache.torque.generator.qname;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import org.apache.commons.lang.StringUtils;
28
29 /**
30 * An instance of this class represents a hierarchical namespace. The hierarchy
31 * parts are separated by dots.
32 *
33 * A namespace is in another namespace if it starts with all the components
34 * of the the other namespace (it may contain other components afterwards).
35 * For example, the namespace "org.apache.torque" is in the namespace
36 * "org.apache".
37 *
38 * Note that the components and their order need to be equal, it does not
39 * suffice if a namespace starts with another namespace. For example,
40 * the namespace "org.apache.torque" is not in the namespace
41 * "org.ap".
42 *
43 * Instances of this class are immutable. To guard against mutable subclasses,
44 * this class is final.
45 */
46 public final class Namespace
47 {
48 /**
49 * The separator between the hierachical parts of a namespace.
50 */
51 public static final char SEPARATOR = '.';
52
53 /**
54 * The root namespace.
55 */
56 public static final Namespace ROOT_NAMESPACE
57 = new Namespace(StringUtils.EMPTY);
58
59 /**
60 * The String representation of the namespace. Is never null.
61 */
62 private String namespace;
63
64 /**
65 * Constructs a namespace from its string representation.
66 * @param namespace teh string representation of the namespace.
67 * May not be null, and may not contain colons(:).
68 *
69 * @throws NullPointerException if namespace is null.
70 * @throws IllegalArgumentException if namespace contains colons.
71 */
72 public Namespace(String namespace)
73 {
74 if (namespace == null)
75 {
76 throw new NullPointerException("namespace must not be null");
77 }
78 this.namespace = namespace;
79 }
80
81 /**
82 * Copy-Contructor.
83 *
84 * @param toCopy the namespace to copy, not null.
85 * @throws NullPointerException if toCopy is null.
86 */
87 public Namespace(Namespace toCopy)
88 {
89 if (toCopy == null)
90 {
91 throw new NullPointerException("toCopy must not be null");
92 }
93 this.namespace = toCopy.namespace;
94 }
95
96 /**
97 * Creates a namespace from a hierarchical List of namespace parts.
98 *
99 * @param namespaceParts the parts of the namespace.
100 */
101 public Namespace(List<String> namespaceParts)
102 {
103 if (namespaceParts == null)
104 {
105 throw new NullPointerException("namespaceParts must not be null");
106 }
107 StringBuffer assembledNamespace = new StringBuffer();
108 for (Iterator<String> partIt
109 = namespaceParts.iterator(); partIt.hasNext();)
110 {
111 String part = partIt.next();
112
113 assembledNamespace.append(part);
114 if (partIt.hasNext())
115 {
116 assembledNamespace.append(SEPARATOR);
117 }
118 }
119 this.namespace = assembledNamespace.toString();
120 }
121
122
123 /**
124 * Returns the parts of the namespace in hierachical order.
125 * The most significant part, i.e the leftmost side, is returned first.
126 *
127 * @return the parts of the namespace, never null. An empty list
128 * is returned for the root namespace.
129 */
130 public List<String> getParts()
131 {
132 if (StringUtils.EMPTY.equals(namespace))
133 {
134 return new ArrayList<String>();
135 }
136 String[] partArray
137 = namespace.split("\\" + SEPARATOR);
138 return Arrays.asList(partArray);
139 }
140
141 /**
142 * Returns the parent of the given namespace. If this namespace's
143 * parent namespace is the root namespace, or this namespace is the root
144 * namespace, the root namespace is returned.
145 *
146 * @return the parent namespace of the namespace, never null
147 */
148 public Namespace getParent()
149 {
150 int separatorPos = namespace.lastIndexOf(SEPARATOR);
151 if (separatorPos == -1)
152 {
153 return ROOT_NAMESPACE;
154 }
155
156 String parentNamespace = namespace.substring(0, separatorPos);
157 return new Namespace(parentNamespace);
158 }
159
160 /**
161 * Returns if this namespace is visible to another namespace.
162 * This is true if this namespace is a "child" of the other namespace
163 * or equal to the other namespace.
164 * Note that for being a child, all the parts of the namespace separated
165 * by a dot must be equal.
166 * For example, "org.apache.torque" is visible to the namespace
167 * quot;org.apache" and "org" but not to
168 * "org.ap", as the second parts, "apache" and
169 * "ap" are not equal.
170 *
171 * @param otherNamespace the namespace against this namespace
172 * should be checked, not null.
173 * @return true if this namespace is visible to the given namespace,
174 * false otherwise.
175 * @throws NullPointerException if otherNamespace is null.
176 */
177 public boolean isVisibleTo(Namespace otherNamespace)
178 {
179 if (otherNamespace == null)
180 {
181 throw new NullPointerException("otherNamespace must not be null");
182 }
183 // All namespaces are in the root namespace.
184 if (ROOT_NAMESPACE.equals(otherNamespace))
185 {
186 return true;
187 }
188
189 // The root namespace is not contained in an non-root namespace.
190 if (ROOT_NAMESPACE.equals(this))
191 {
192 return false;
193 }
194
195 if (!this.namespace.startsWith(otherNamespace.namespace))
196 {
197 return false;
198 }
199
200 if (this.namespace.equals(otherNamespace.namespace))
201 {
202 return true;
203 }
204
205 if (this.namespace.charAt(otherNamespace.namespace.length())
206 == SEPARATOR)
207 {
208 return true;
209 }
210
211 return false;
212 }
213
214 /**
215 * Returns if this namespace is visible from another namespace.
216 * This is true if the other namespace is a "child" of this namespace.
217 * Note that for being a child, all the parts of the namespace separated
218 * by a dot must be equal.
219 * For example, "org.apache.torque" is visible from the namespace
220 * quot;org.apache.torque.generator", but not from
221 * "org.apache".
222 *
223 * @param otherNamespace the namespace against this namespace
224 * should be checked, not null.
225 * @return true if this namespace is visible from the other namespace,
226 * false otherwise.
227 * @throws NullPointerException if otherNamespace is null.
228 */
229 public boolean isVisibleFrom(Namespace otherNamespace)
230 {
231 if (otherNamespace == null)
232 {
233 throw new NullPointerException("otherNamespace is null "
234 + "(this namespace is " + this + ")");
235 }
236 return otherNamespace.isVisibleTo(this);
237 }
238
239 /**
240 * Returns whether this namespace is the root namespace.
241 *
242 * @return true if this namespace is the root namespace, false otherwise.
243 */
244 public boolean isRoot()
245 {
246 return ROOT_NAMESPACE.namespace.equals(namespace);
247 }
248
249 /**
250 * Returns if this object is equal to another object.
251 * This is true if and only if the other object is a namespace, and their
252 * string representations are equal.
253 *
254 * @param o the object to check equality.
255 * @return true if the object is equal to this namespace, false otherwise.
256 *
257 * @see java.lang.Object#equals(Object)
258 */
259 @Override
260 public boolean equals(Object o)
261 {
262 if (!(o instanceof Namespace))
263 {
264 return false;
265 }
266
267 Namespace otherNamespace = (Namespace) o;
268 return otherNamespace.namespace.equals(this.namespace);
269 }
270
271 /**
272 * Returns a hash code for this namespace. The hash code is consistent
273 * with <code>equals()</code>.
274 *
275 * @return a hach code for this object.
276 *
277 * @see java.lang.Object#hashCode()
278 */
279 @Override
280 public int hashCode()
281 {
282 return namespace.hashCode();
283 }
284
285 /**
286 * Returns a String representation of this namespace.
287 *
288 * @return a String representation of this namespace.
289 *
290 * @see java.lang.Object#toString()
291 */
292 @Override
293 public String toString()
294 {
295 return namespace;
296 }
297 }