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 2015-2016 ForgeRock AS. 015 */ 016package org.opends.server.schema; 017 018import static org.opends.server.util.ServerConstants.*; 019 020import java.util.Arrays; 021import java.util.List; 022import java.util.Map; 023 024import org.forgerock.opendj.ldap.schema.AttributeType; 025import org.forgerock.opendj.ldap.schema.Schema; 026import org.forgerock.opendj.ldap.schema.SchemaBuilder; 027import org.opends.server.config.ConfigConstants; 028import org.opends.server.core.ServerContext; 029import org.opends.server.types.CommonSchemaElements; 030import org.opends.server.types.ObjectClass; 031import org.opends.server.types.SchemaFileElement; 032import org.opends.server.util.RemoveOnceSDKSchemaIsUsed; 033import org.opends.server.util.ServerConstants; 034 035/** 036 * Represents a schema element which is either a SDK attribute type or an objectclass from the server. 037 * <p> 038 * In absence of a common interface, this class allows to process all elements in the same way, 039 * and to provide useful server-oriented methods like {@code getSchemaFile()} or 040 * {@code getOrigin()}. 041 */ 042@RemoveOnceSDKSchemaIsUsed("This class is a temporary mechanism" 043 + " to manage in the same way SDK and server schema element classes") 044public class SomeSchemaElement implements SchemaFileElement 045{ 046 private final ObjectClass objectClass; 047 private AttributeType attributeType; 048 049 /** 050 * Builds SomeSchemaElement. 051 * 052 * @param objectClass 053 * the common schema element to wrap 054 */ 055 public SomeSchemaElement(ObjectClass objectClass) 056 { 057 this.objectClass = objectClass; 058 this.attributeType = null; 059 } 060 061 /** 062 * Builds SomeSchemaElement. 063 * 064 * @param attributeType 065 * the attribute type element to wrap 066 */ 067 public SomeSchemaElement(AttributeType attributeType) 068 { 069 this.objectClass = null; 070 this.attributeType = attributeType; 071 } 072 073 /** 074 * Returns the wrapped schema element as an object class. 075 * 076 * @return the wrapped object class 077 */ 078 public ObjectClass getObjectClass() 079 { 080 return objectClass; 081 } 082 083 /** 084 * Returns the wrapped schema element as an attribute type. 085 * 086 * @return the wrapped attribute type 087 */ 088 public AttributeType getAttributeType() 089 { 090 return attributeType; 091 } 092 093 /** 094 * Returns whether the wrapped element is an attribute type. 095 * 096 * @return {@code true} when the wrapped element is an attribute type, {@code false} otherwise 097 */ 098 public boolean isAttributeType() 099 { 100 return attributeType != null; 101 } 102 103 /** 104 * Returns whether the wrapped element is an object class. 105 * 106 * @return {@code true} when the wrapped element is an object class, {@code false} otherwise 107 */ 108 public boolean isObjectClass() 109 { 110 return objectClass != null; 111 } 112 113 /** 114 * Returns the OID of the wrapped element. 115 * 116 * @return the OID of the wrapped element. 117 */ 118 public String getOID() 119 { 120 return attributeType != null ? attributeType.getOID() : objectClass.getOID(); 121 } 122 123 /** 124 * Returns the name or OID of the wrapped element. 125 * 126 * @return the name or OID of the wrapped element. 127 */ 128 public String getNameOrOID() 129 { 130 return attributeType != null ? attributeType.getNameOrOID() : objectClass.getNameOrOID(); 131 } 132 133 /** 134 * Returns the names of the wrapped element. 135 * 136 * @return the names of the wrapped element. 137 */ 138 public Iterable<String> getNames() 139 { 140 return attributeType != null ? attributeType.getNames() : objectClass.getNormalizedNames(); 141 } 142 143 @Override 144 public Map<String, List<String>> getExtraProperties() 145 { 146 return attributeType != null ? attributeType.getExtraProperties() : objectClass.getExtraProperties(); 147 } 148 149 @Override 150 public String toString() 151 { 152 return attributeType != null ? attributeType.toString() : objectClass.toString(); 153 } 154 155 /** 156 * Retrieves the definition string used to create this attribute 157 * type and including the X-SCHEMA-FILE extension. 158 * 159 * @return The definition string used to create this attribute 160 * type including the X-SCHEMA-FILE extension. 161 */ 162 public String getDefinitionWithFileName() 163 { 164 final String schemaFile = getSchemaFile(); 165 final String definition = toString(); 166 if (schemaFile != null) 167 { 168 int pos = definition.lastIndexOf(')'); 169 return definition.substring(0, pos).trim() + " " + SCHEMA_PROPERTY_FILENAME + " '" + schemaFile + "' )"; 170 } 171 return definition; 172 } 173 174 /** 175 * Returns the name of the schema file that contains the definition of the wrapped element. 176 * 177 * @return the name of the schema file that contains the definition of the wrapped element. 178 */ 179 public String getSchemaFile() 180 { 181 return getExtraPropertySingleValue(ServerConstants.SCHEMA_PROPERTY_FILENAME); 182 } 183 184 /** 185 * Sets the name of the schema file that contains the definition of the wrapped element. 186 * 187 * @param serverContext 188 * the server context 189 * @param schemaFile 190 * the name of the schema file that contains the definition of the wrapped element. 191 */ 192 public void setSchemaFile(ServerContext serverContext, String schemaFile) 193 { 194 setExtraPropertySingleValue(serverContext, SCHEMA_PROPERTY_FILENAME, schemaFile); 195 } 196 197 /** 198 * Returns the origin of the provided schema element. 199 * @return the origin of the provided schema element. 200 */ 201 public String getOrigin() 202 { 203 return getExtraPropertySingleValue(ServerConstants.SCHEMA_PROPERTY_ORIGIN); 204 } 205 206 private String getExtraPropertySingleValue(String schemaPropertyOrigin) 207 { 208 if (objectClass != null) 209 { 210 return CommonSchemaElements.getSingleValueProperty(objectClass, schemaPropertyOrigin); 211 } 212 List<String> values = attributeType.getExtraProperties().get(schemaPropertyOrigin); 213 return values != null && !values.isEmpty() ? values.get(0) : null; 214 } 215 216 /** 217 * Returns the attribute name of the wrapped element. 218 * @return the attribute name of the wrapped element. 219 */ 220 public String getAttributeName() 221 { 222 return attributeType!= null ? ConfigConstants.ATTR_ATTRIBUTE_TYPES : ConfigConstants.ATTR_OBJECTCLASSES; 223 } 224 225 /** 226 * Sets a single-valued extra property on the wrapped element. 227 * 228 * @param serverContext 229 * the server context 230 * @param property 231 * the property to set 232 * @param value 233 * the value to set 234 */ 235 public void setExtraPropertySingleValue(ServerContext serverContext, String property, String value) 236 { 237 if (attributeType != null) 238 { 239 List<String> values = value != null ? Arrays.asList(value) : null; 240 setExtraPropertyMultipleValues(serverContext, property, values); 241 } 242 else 243 { 244 CommonSchemaElements.setExtraProperty(objectClass, property, value); 245 } 246 } 247 248 /** 249 * Sets a multi-valued extra property on the wrapped element. 250 * 251 * @param serverContext 252 * the server context 253 * @param property 254 * the property to set 255 * @param values 256 * the values to set 257 */ 258 public void setExtraPropertyMultipleValues(ServerContext serverContext, String property, List<String> values) 259 { 260 if (attributeType != null) 261 { 262 SchemaBuilder schemaBuilder = serverContext != null ? 263 new SchemaBuilder(serverContext.getSchemaNG()) : new SchemaBuilder(Schema.getDefaultSchema()); 264 AttributeType.Builder builder = 265 schemaBuilder.buildAttributeType(attributeType).removeExtraProperty(property, (String) null); 266 if (values != null && !values.isEmpty()) 267 { 268 builder.extraProperties(property, values); 269 } 270 attributeType = builder.addToSchemaOverwrite().toSchema().getAttributeType(attributeType.getNameOrOID()); 271 } 272 else 273 { 274 objectClass.setExtraProperty(property, values); 275 } 276 } 277 278 /** 279 * Returns a copy of the provided attribute type, changing the superior attribute type. 280 * 281 * @param attributeType 282 * the attribute type for which a modified copy must be built 283 * @param newSuperiorType 284 * the new superior attribute type to set, {@code null} means remove the superior type 285 * @return an attribute type builder to build an updated copy of the provided attribute type 286 */ 287 public static AttributeType changeSuperiorType(AttributeType attributeType, AttributeType newSuperiorType) 288 { 289 String superiorTypeOID = newSuperiorType != null ? newSuperiorType.getNameOrOID() : null; 290 Schema schema = new SchemaBuilder() 291 .buildAttributeType(attributeType) 292 .superiorType(superiorTypeOID) 293 .addToSchemaOverwrite() 294 .toSchema(); 295 return schema.getAttributeType(attributeType.getNameOrOID()); 296 } 297}