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