001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.admin; 028 029 030 031 import org.opends.server.types.AttributeValue; 032 import org.opends.server.types.DN; 033 import org.opends.server.types.DirectoryException; 034 import org.opends.server.types.RDN; 035 import org.opends.server.util.StaticUtils; 036 037 038 039 /** 040 * A reference to another managed object. 041 * 042 * @param <C> 043 * The type of client managed object configuration that this 044 * reference refers to. 045 * @param <S> 046 * The type of server managed object configuration that this 047 * reference refers to. 048 */ 049 public final class Reference<C extends ConfigurationClient, 050 S extends Configuration> { 051 052 /** 053 * Parses a DN string value as a reference using the provided 054 * managed object path and relation definition. 055 * 056 * @param <C> 057 * The type of client managed object configuration that 058 * this reference refers to. 059 * @param <S> 060 * The type of server managed object configuration that 061 * this reference refers to. 062 * @param p 063 * The path of the referenced managed object's parent. 064 * @param rd 065 * The instantiable relation in the parent which contains 066 * the referenced managed object. 067 * @param s 068 * The DN string value. 069 * @return Returns the new reference based on the provided DN string 070 * value. 071 * @throws IllegalArgumentException 072 * If the DN string value could not be decoded as a DN or 073 * if the provided DN did not correspond to the provided 074 * path and relation. 075 */ 076 public static <C extends ConfigurationClient, S extends Configuration> 077 Reference<C, S> parseDN( 078 ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> rd, 079 String s) throws IllegalArgumentException { 080 AbstractManagedObjectDefinition<?, ?> d = p.getManagedObjectDefinition(); 081 RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName()); 082 if (tmp != rd) { 083 throw new IllegalArgumentException("The relation \"" + rd.getName() 084 + "\" is not associated with the definition \"" + d.getName() + "\""); 085 } 086 087 DN dn; 088 try { 089 dn = DN.decode(s); 090 } catch (DirectoryException e) { 091 throw new IllegalArgumentException("Unabled to decode the DN string: \"" 092 + s + "\""); 093 } 094 095 RDN rdn = dn.getRDN(); 096 if (rdn == null) { 097 throw new IllegalArgumentException("Unabled to decode the DN string: \"" 098 + s + "\""); 099 } 100 101 AttributeValue av = rdn.getAttributeValue(0); 102 if (av == null) { 103 throw new IllegalArgumentException("Unabled to decode the DN string: \"" 104 + s + "\""); 105 } 106 107 String name = av.getStringValue(); 108 109 // Check that the DN was valid. 110 DN expected = p.child(rd, name).toDN(); 111 if (!dn.equals(expected)) { 112 throw new IllegalArgumentException("Unabled to decode the DN string: \"" 113 + s + "\""); 114 } 115 116 return new Reference<C, S>(p, rd, name); 117 } 118 119 120 121 /** 122 * Parses a name as a reference using the provided managed object 123 * path and relation definition. 124 * 125 * @param <C> 126 * The type of client managed object configuration that 127 * this reference refers to. 128 * @param <S> 129 * The type of server managed object configuration that 130 * this reference refers to. 131 * @param p 132 * The path of the referenced managed object's parent. 133 * @param rd 134 * The instantiable relation in the parent which contains 135 * the referenced managed object. 136 * @param s 137 * The name of the referenced managed object. 138 * @return Returns the new reference based on the provided name. 139 * @throws IllegalArgumentException 140 * If the relation is not associated with the provided 141 * parent's definition, or if the provided name is empty. 142 */ 143 public static <C extends ConfigurationClient, S extends Configuration> 144 Reference<C, S> parseName( 145 ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> rd, 146 String s) throws IllegalArgumentException { 147 // Sanity checks. 148 AbstractManagedObjectDefinition<?, ?> d = p.getManagedObjectDefinition(); 149 RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName()); 150 if (tmp != rd) { 151 throw new IllegalArgumentException("The relation \"" + rd.getName() 152 + "\" is not associated with the definition \"" + d.getName() + "\""); 153 } 154 155 if (s.trim().length() == 0) { 156 throw new IllegalArgumentException("Empty names are not allowed"); 157 } 158 159 return new Reference<C, S>(p, rd, s); 160 } 161 162 // The name of the referenced managed object. 163 private final String name; 164 165 // The path of the referenced managed object. 166 private final ManagedObjectPath<C, S> path; 167 168 // The instantiable relation in the parent which contains the 169 // referenced managed object. 170 private final InstantiableRelationDefinition<C, S> relation; 171 172 173 174 // Private constructor. 175 private Reference(ManagedObjectPath<?, ?> parent, 176 InstantiableRelationDefinition<C, S> relation, String name) 177 throws IllegalArgumentException { 178 this.relation = relation; 179 this.name = name; 180 this.path = parent.child(relation, name); 181 } 182 183 184 185 /** 186 * Gets the name of the referenced managed object. 187 * 188 * @return Returns the name of the referenced managed object. 189 */ 190 public String getName() { 191 return name; 192 } 193 194 195 196 /** 197 * Gets the normalized name of the referenced managed object. 198 * 199 * @return Returns the normalized name of the referenced managed 200 * object. 201 */ 202 public String getNormalizedName() { 203 PropertyDefinition<?> pd = relation.getNamingPropertyDefinition(); 204 return normalizeName(pd); 205 } 206 207 208 209 /** 210 * Gets the DN of the referenced managed object. 211 * 212 * @return Returns the DN of the referenced managed object. 213 */ 214 public DN toDN() { 215 return path.toDN(); 216 } 217 218 219 220 /** 221 * {@inheritDoc} 222 */ 223 public String toString() { 224 return name; 225 } 226 227 228 229 // Normalize a value using the specified naming property definition 230 // if defined. 231 private <T> String normalizeName(PropertyDefinition<T> pd) { 232 if (pd != null) { 233 try { 234 T tvalue = pd.decodeValue(name); 235 return pd.normalizeValue(tvalue); 236 } catch (IllegalPropertyValueStringException e) { 237 // Fall through to default normalization. 238 } 239 } 240 241 // FIXME: should really use directory string normalizer. 242 String s = name.trim().replaceAll(" +", " "); 243 return StaticUtils.toLowerCase(s); 244 } 245 }