View Javadoc

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 org.apache.commons.lang.StringUtils;
23  
24  
25  /**
26   * This class contains a name which has a namespace. The namespace defines the
27   * scope where the name is valid, and is made up of hierarchical bits
28   * separated by a dot (<code>SEPARATOR<code>).
29   * A qualified name is in the scope of its own namespace and all children
30   * namespaces of its own namespace (i.e. the namespaces "deeper down"
31   * the hierarchy). For example, the namespace org.apache.torque
32   * is in the scope of org.apache but not in the scope of
33   * org.apache.torque.generator.
34   * As a special case, if the namespace is the empty String,
35   * the name is valid in all namespaces.
36   *
37   * The namespace and the name are also separated by a dot
38   * (<code>SEPARATOR<code>).
39   *
40   * Instances of this class are immutable. To prevent mutable subclasses,
41   * this class is final.
42   */
43  public final class QualifiedName
44  {
45      /**
46       * The separator between namespace parts and between namespacee
47       * and local name in the string representation of a QualifiedName.
48       */
49      public static final char SEPARATOR = '.';
50  
51      /**
52       * The local name part of the qualifiedName. Is never null or empty.
53       */
54      private String name;
55  
56      /**
57       * The namespace of the qualifiedName. Is never null.
58       */
59      private Namespace namespace;
60  
61      /**
62       * Creates a QualifiedName from its string representation, which is
63       * namespace:name. The namespace part may be empty (in which case
64       * the default namespace is used), but not the name part.
65       *
66       * @param qualifiedName the string representation of the QualifiedName,
67       *        must contain a non-empty name part.
68       * @throws NullPointerException if qualifiedName is null
69       */
70      public QualifiedName(String qualifiedName)
71      {
72          this(qualifiedName, (Namespace) null);
73      }
74  
75      /**
76       * Creates a QualifiedName from a fully qualified name or the name and the
77       * namespace parts of a QualifiedName.
78       *
79       * @param nameOrQualifiedName either the name part of the QualifiedName,
80       *        or a fully qualified name. May not be null and must contain
81       *        an non-empty name part.
82       * @param defaultNamespace the namespace of the QualifiedName,
83       *        may be null if nameOrQualifiedName has a namespace part.
84       *
85       * @throws IllegalArgumentException if name has an empty name part, or
86       *         if no namespace is found (nameOrQualifiedName has no namespace
87       *         part and defaultNamespace is null)
88       * @throw NullPointerException if name is null.
89       */
90      public QualifiedName(String nameOrQualifiedName, String defaultNamespace)
91      {
92          this(nameOrQualifiedName,
93                  defaultNamespace != null
94                      ? new Namespace(defaultNamespace)
95                      : null);
96     }
97  
98      /**
99       * Creates a QualifiedName from a fully qualified name or the name and the
100      * namespace parts of a QualifiedName.
101      *
102      * @param nameOrQualifiedName either the name part of the QualifiedName,
103      *        or a fully qualified name. May not be null and must contain
104      *        an non-empty name part.
105      * @param defaultNamespace the namespace of the QualifiedName,
106      *        may be null if nameOrQualifiedName has a namespace part.
107      *
108      * @throws IllegalArgumentException if name has an empty name part, or
109      *         if no namespace is found (nameOrQualifiedName has no namespace
110      *         part and defaultNamespace is null)
111      * @throw NullPointerException if name is null.
112      */
113     public QualifiedName(String nameOrQualifiedName, Namespace defaultNamespace)
114     {
115         if (nameOrQualifiedName == null)
116         {
117             throw new NullPointerException(
118                     "nameOrQualifiedName must not be null");
119         }
120         int dotIndex = nameOrQualifiedName.lastIndexOf(SEPARATOR);
121         if (dotIndex == -1)
122         {
123             if (defaultNamespace == null)
124             {
125                 defaultNamespace = Namespace.ROOT_NAMESPACE;
126             }
127             setName(nameOrQualifiedName);
128             this.namespace = defaultNamespace;
129         }
130         else
131         {
132             setName(nameOrQualifiedName.substring(dotIndex + 1).trim());
133             String namespacePart
134                     = nameOrQualifiedName.substring(0, dotIndex).trim();
135             setNamespace(namespacePart);
136         }
137     }
138 
139     /**
140      * Returns the name part of the QualifiedName.
141      *
142      * @return the name part of the QualifiedName, never null.
143      */
144     public String getName()
145     {
146         return name;
147     }
148 
149     /**
150      * Sets the name part of this Qualified name.
151      * This method is private because this object is immutable.
152      *
153      * @param name the name, not blank,
154      *        must not contain a dot (<code>SEPARATOR</code>).
155      */
156     private void setName(String name)
157     {
158         if (name.indexOf(SEPARATOR) != -1)
159         {
160             throw new IllegalArgumentException(
161                     "name \"" + name + "\" must not contain "
162                         + SEPARATOR);
163         }
164         if (StringUtils.isBlank(name))
165         {
166             throw new IllegalArgumentException("name must not be blank");
167         }
168         this.name = name;
169     }
170 
171     /**
172      * Sets the namespace part of this Qualified name.
173      * This method is private because this object is immutable.
174      *
175      * @param namespace the name, not null,
176      *        must not contain <code>NAMESPACE_NAME_SEPARATOR</code>
177      */
178     private void setNamespace(String namespace)
179     {
180         this.namespace = new Namespace(namespace);
181     }
182 
183     /**
184      * Returns the namespace of the QualifiedName.
185      *
186      * @return the namespace of the QualifiedName, may be null.
187      */
188     public Namespace getNamespace()
189     {
190         return namespace;
191     }
192 
193     /**
194      * Returns if this qualified name is visible from another namespace.
195      * This is true if the namespace is a "child" of this
196      * qualified name's  namespace.
197      * Note that for being a child, all the parts of the namespace separated
198      * by a dot must be equal.
199      * For example, &quot;org.apache.torque:name&quot; is visible from the
200      * namespaces quot;org.apache.torque.generator&quot; and
201      * quot;org.apache.torque&quot;, but not from &quot;org.apache&quot.
202      *
203      * @param otherNamespace the namespace against this QualifiedName
204      *        should be checked, not null.
205      *
206      * @return true if this QualifiedName is visible from the given namespace,
207      *         false otherwise.
208      *
209      * @throws NullPointerException if otherNamespace is null.
210      */
211     public boolean isVisibleFrom(Namespace otherNamespace)
212     {
213         return namespace.isVisibleFrom(otherNamespace);
214     }
215 
216     /**
217      * Returns the parent of the Qualified name's namespace.
218      * If this qualified name is in the root namespace, the root namespace
219      * is returned.
220      *
221      * @return the parent namespace of the qualified name's namespace,
222      *         never null.
223      *
224      * @see Namespace#getParent()
225      */
226     public Namespace getParentNamespace()
227     {
228         return namespace.getParent();
229     }
230 
231     /**
232      * Returns if the namespace of this qualified name is the root namespace.
233      *
234      * @return true if the namespace is the root namespace, false otherwise.
235      */
236     public boolean isInRootNamespace()
237     {
238         return namespace.isRoot();
239     }
240 
241     /**
242      * Returns the String representation of the QualifiedName,
243      * which is namespace.name if namespace is not empty,
244      * or name if namespace is empty.
245      *
246      * @return a String representation of the QualifiedName.
247      */
248     @Override
249     public String toString()
250     {
251         if (isInRootNamespace())
252         {
253             return name;
254         }
255         return namespace.toString() + SEPARATOR + name;
256     }
257 
258     /**
259      * Returns if this object equals another object. This is the case if
260      * the other object is also a QualifiedName and its name and namespace
261      * are the same as this object's name and namespace.
262      *
263      * @param o the other object to compare this object to.
264      * @return true if this object equals the other object, false otherwise.
265      *
266      * @see java.lang.Object#equals(Object)
267      */
268     @Override
269     public boolean equals(Object o)
270     {
271         if (!(o instanceof QualifiedName))
272         {
273             return false;
274         }
275 
276         QualifiedName qualifiedName = (QualifiedName) o;
277 
278         if (!qualifiedName.name.equals(name))
279         {
280             return false;
281         }
282 
283         return qualifiedName.namespace.equals(namespace);
284     }
285 
286     /**
287      * Returns a hashcode for the QualifiedName. The hashcode is consistent
288      * with equals.
289      *
290      * @return a hashcode for the qualified name.
291      *
292      * @see java.lang.Object#hashCode()
293      */
294     @Override
295     public int hashCode()
296     {
297         return toString().hashCode();
298     }
299 }