001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008 Sun Microsystems, Inc. 015 * Portions Copyright 2015-2016 ForgeRock AS. 016 */ 017package org.forgerock.opendj.config; 018 019import static com.forgerock.opendj.util.StaticUtils.*; 020 021import org.forgerock.opendj.ldap.DN; 022import org.forgerock.opendj.ldap.RDN; 023 024/** 025 * A reference to another managed object. 026 * 027 * @param <C> 028 * The type of client managed object configuration that this 029 * reference refers to. 030 * @param <S> 031 * The type of server managed object configuration that this 032 * reference refers to. 033 */ 034public final class Reference<C extends ConfigurationClient, S extends Configuration> { 035 036 /** 037 * Parses a DN string value as a reference using the provided managed object 038 * path and relation definition. 039 * 040 * @param <C> 041 * The type of client managed object configuration that this 042 * reference refers to. 043 * @param <S> 044 * The type of server managed object configuration that this 045 * reference refers to. 046 * @param path 047 * The path of the referenced managed object's parent. 048 * @param relationDef 049 * The instantiable relation in the parent which contains the 050 * referenced managed object. 051 * @param dnAsString 052 * The DN string value. 053 * @return Returns the new reference based on the provided DN string value. 054 * @throws IllegalArgumentException 055 * If the DN string value could not be decoded as a DN or if the 056 * provided DN did not correspond to the provided path and 057 * relation. 058 */ 059 public static <C extends ConfigurationClient, S extends Configuration> Reference<C, S> parseDN( 060 ManagedObjectPath<?, ?> path, InstantiableRelationDefinition<C, S> relationDef, String dnAsString) { 061 AbstractManagedObjectDefinition<?, ?> definition = path.getManagedObjectDefinition(); 062 RelationDefinition<?, ?> tmp = definition.getRelationDefinition(relationDef.getName()); 063 if (tmp != relationDef) { 064 // TODO : i18n ? 065 throw new IllegalArgumentException("The relation \"" + relationDef.getName() 066 + "\" is not associated with the definition \"" + definition.getName() + "\""); 067 } 068 069 DN dn = DN.valueOf(dnAsString); 070 RDN rdn = dn.rdn(); 071 if (rdn == null) { 072 // TODO : i18n ? 073 throw new IllegalArgumentException("Unabled to decode the DN string: \"" + dnAsString + "\""); 074 } 075 076 // Check that the DN was valid. 077 String name = rdn.getFirstAVA().getAttributeValue().toString(); 078 DN expected = path.child(relationDef, name).toDN(); 079 if (!dn.equals(expected)) { 080 // TODO : i18n ? 081 throw new IllegalArgumentException("Unabled to decode the DN string: \"" + dnAsString + "\""); 082 } 083 084 return new Reference<>(path, relationDef, name); 085 } 086 087 /** 088 * Parses a name as a reference using the provided managed object path and 089 * relation definition. 090 * 091 * @param <C> 092 * The type of client managed object configuration that this 093 * reference refers to. 094 * @param <S> 095 * The type of server managed object configuration that this 096 * reference refers to. 097 * @param p 098 * The path of the referenced managed object's parent. 099 * @param rd 100 * The instantiable relation in the parent which contains the 101 * referenced managed object. 102 * @param s 103 * The name of the referenced managed object. 104 * @return Returns the new reference based on the provided name. 105 * @throws IllegalArgumentException 106 * If the relation is not associated with the provided parent's 107 * definition, or if the provided name is empty. 108 */ 109 public static <C extends ConfigurationClient, S extends Configuration> Reference<C, S> parseName( 110 ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> rd, String s) { 111 // Sanity checks. 112 AbstractManagedObjectDefinition<?, ?> d = p.getManagedObjectDefinition(); 113 RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName()); 114 if (tmp != rd) { 115 throw new IllegalArgumentException("The relation \"" + rd.getName() 116 + "\" is not associated with the definition \"" + d.getName() + "\""); 117 } 118 119 if (s.trim().length() == 0) { 120 throw new IllegalArgumentException("Empty names are not allowed"); 121 } 122 123 return new Reference<>(p, rd, s); 124 } 125 126 /** The name of the referenced managed object. */ 127 private final String name; 128 129 /** The path of the referenced managed object. */ 130 private final ManagedObjectPath<C, S> path; 131 132 /** The instantiable relation in the parent which contains the referenced managed object. */ 133 private final InstantiableRelationDefinition<C, S> relation; 134 135 /** Private constructor. */ 136 private Reference(ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> relation, String name) { 137 this.relation = relation; 138 this.name = name; 139 this.path = parent.child(relation, name); 140 } 141 142 /** 143 * Gets the name of the referenced managed object. 144 * 145 * @return Returns the name of the referenced managed object. 146 */ 147 public String getName() { 148 return name; 149 } 150 151 /** 152 * Gets the normalized name of the referenced managed object. 153 * 154 * @return Returns the normalized name of the referenced managed object. 155 */ 156 public String getNormalizedName() { 157 PropertyDefinition<?> pd = relation.getNamingPropertyDefinition(); 158 return normalizeName(pd); 159 } 160 161 /** 162 * Gets the DN of the referenced managed object. 163 * 164 * @return Returns the DN of the referenced managed object. 165 */ 166 public DN toDN() { 167 return path.toDN(); 168 } 169 170 @Override 171 public String toString() { 172 return name; 173 } 174 175 /** Normalize a value using the specified naming property definition if defined. */ 176 private <T> String normalizeName(PropertyDefinition<T> pd) { 177 if (pd != null) { 178 try { 179 // TODO : is it correct to have no validation ? 180 T tvalue = pd.decodeValue(name); 181 return pd.normalizeValue(tvalue); 182 } catch (PropertyException e) { 183 // Fall through to default normalization. 184 } 185 } 186 187 // FIXME: should really use directory string normalizer. 188 String s = name.trim().replaceAll(" +", " "); 189 return toLowerCase(s); 190 } 191}