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, "org.apache.torque:name" is visible from the 200 * namespaces quot;org.apache.torque.generator" and 201 * quot;org.apache.torque", but not from "org.apache". 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 }