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 }