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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2008 Sun Microsystems, Inc.
025 *      Portions Copyright 2013-2015 ForgeRock AS.
026 */
027package org.opends.server.types;
028
029import java.util.LinkedHashMap;
030import java.util.LinkedHashSet;
031import java.util.List;
032import java.util.Map;
033import java.util.Set;
034
035import org.forgerock.i18n.slf4j.LocalizedLogger;
036
037import static org.forgerock.util.Reject.*;
038import static org.opends.server.util.ServerConstants.*;
039
040/**
041 * This class defines a DIT structure rule, which is used to indicate
042 * the types of children that entries may have.
043 */
044@org.opends.server.types.PublicAPI(
045     stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
046     mayInstantiate=false,
047     mayExtend=false,
048     mayInvoke=true)
049public final class DITStructureRule
050       implements SchemaFileElement
051{
052  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
053
054  /** Indicates whether this DIT structure rule is declared "obsolete". */
055  private final boolean isObsolete;
056
057  /** The rule ID for this DIT structure rule. */
058  private final int ruleID;
059
060  /** The name form for this DIT structure rule. */
061  private final NameForm nameForm;
062
063  /**
064   * The set of additional name-value pairs associated with this DIT
065   * structure rule.
066   */
067  private final Map<String,List<String>> extraProperties;
068
069  /**
070   * The set of names for this DIT structure rule, in a mapping
071   * between the all-lowercase form and the user-defined form.
072   */
073  private final Map<String,String> names;
074
075  /** The set of superior DIT structure rules. */
076  private final Set<DITStructureRule> superiorRules;
077
078  /** The definition string for this DIT structure rule. */
079  private final String definition;
080
081  /** The description for this DIT structure rule. */
082  private final String description;
083
084
085
086  /**
087   * Creates a new DIT structure rule with the provided information.
088   *
089   * @param  definition       The definition string used to create
090   *                          this DIT structure rule.  It must not be
091   *                          {@code null}.
092   * @param  names            The set of names for this DIT structure
093   *                          rule, mapping the lowercase names to the
094   *                          user-defined values.
095   * @param  ruleID           The rule ID for this DIT structure rule.
096   * @param  description      The description for this DIT structure
097   *                          rule.
098   * @param  isObsolete       Indicates whether this DIT structure
099   *                          rule is declared "obsolete".
100   * @param  nameForm         The name form for this DIT structure
101   *                          rule.
102   * @param  superiorRules    References to the superior rules for
103   *                          this DIT structure rule.
104   * @param  extraProperties  The set of "extra" properties associated
105   *                          with this DIT structure rules.
106   */
107  public DITStructureRule(String definition, Map<String,String> names,
108                          int ruleID, String description,
109                          boolean isObsolete, NameForm nameForm,
110                          Set<DITStructureRule> superiorRules,
111                          Map<String,List<String>> extraProperties)
112  {
113    ifNull(definition);
114
115    this.ruleID      = ruleID;
116    this.description = description;
117    this.isObsolete  = isObsolete;
118    this.nameForm    = nameForm;
119
120    int schemaFilePos = definition.indexOf(SCHEMA_PROPERTY_FILENAME);
121    if (schemaFilePos > 0)
122    {
123      String defStr;
124      try
125      {
126        int firstQuotePos = definition.indexOf('\'', schemaFilePos);
127        int secondQuotePos = definition.indexOf('\'',
128                                                firstQuotePos+1);
129
130        defStr = definition.substring(0, schemaFilePos).trim() + " " +
131                 definition.substring(secondQuotePos+1).trim();
132      }
133      catch (Exception e)
134      {
135        logger.traceException(e);
136
137        defStr = definition;
138      }
139
140      this.definition = defStr;
141    }
142    else
143    {
144      this.definition = definition;
145    }
146
147    if (names == null || names.isEmpty())
148    {
149      this.names = new LinkedHashMap<>(0);
150    }
151    else
152    {
153      this.names = new LinkedHashMap<>(names);
154    }
155
156    if (superiorRules == null || superiorRules.isEmpty())
157    {
158      this.superiorRules = new LinkedHashSet<>(0);
159    }
160    else
161    {
162      this.superiorRules = new LinkedHashSet<>(superiorRules);
163    }
164
165    if (extraProperties == null || extraProperties.isEmpty())
166    {
167      this.extraProperties = new LinkedHashMap<>(0);
168    }
169    else
170    {
171      this.extraProperties = new LinkedHashMap<>(extraProperties);
172    }
173  }
174
175
176
177  /**
178   * Retrieves the set of names that may be used to reference this DIT
179   * structure rule.  The returned mapping will be between an all
180   * lower-case form of the name and a name in the user-defined form
181   * (which may include mixed capitalization).
182   *
183   * @return  The set of names that may be used to reference this DIT
184   *          structure rule.
185   */
186  public Map<String,String> getNames()
187  {
188    return names;
189  }
190
191
192
193  /**
194   * Indicates whether this DIT structure rule has the specified name.
195   *
196   * @param  lowerName  The lowercase name for which to make the
197   *                    determination.
198   *
199   * @return  {@code true} if the specified name is assigned to this
200   *          DIT structure rule, or {@code false} if not.
201   */
202  public boolean hasName(String lowerName)
203  {
204    return names.containsKey(lowerName);
205  }
206
207
208
209  /**
210   * Retrieves the rule ID for this DIT structure rule.
211   *
212   * @return  The rule ID for this DIT structure rule.
213   */
214  public int getRuleID()
215  {
216    return ruleID;
217  }
218
219
220
221  /**
222   * Retrieves the name or rule ID for this DIT structure rule.  If it
223   * has one or more names, then the primary name will be returned.
224   * If it does not have any names, then the rule ID will be returned.
225   *
226   * @return  The name or rule ID for this DIT structure rule.
227   */
228  public String getNameOrRuleID()
229  {
230    if (names.isEmpty())
231    {
232      return String.valueOf(ruleID);
233    }
234    else
235    {
236      return names.values().iterator().next();
237    }
238  }
239
240
241
242  /**
243   * Retrieves the description for this DIT structure rule.
244   *
245   * @return  The description for this DIT structure rule.
246   */
247  public String getDescription()
248  {
249    return description;
250  }
251
252
253
254  /**
255   * Retrieves the name form for this DIT structure rule.
256   *
257   * @return  The name form for this DIT structure rule.
258   */
259  public NameForm getNameForm()
260  {
261    return nameForm;
262  }
263
264
265
266  /**
267   * Retrieves the structural objectclass for the name form with which
268   * this DIT structure rule is associated.
269   *
270   * @return  The structural objectclass for the name form with which
271   *          this DIT structure rule is associated.
272   */
273  public ObjectClass getStructuralClass()
274  {
275    return nameForm.getStructuralClass();
276  }
277
278
279
280  /**
281   * Retrieves the set of superior rules for this DIT structure rule.
282   *
283   * @return  The set of superior rules for this DIT structure rule.
284   */
285  public Set<DITStructureRule> getSuperiorRules()
286  {
287    return superiorRules;
288  }
289
290
291
292  /**
293   * Indicates whether this DIT structure rule has one or more
294   * superior rules.
295   *
296   * @return  {@code true} if this DIT structure rule has one or more
297   *          superior rules, or {@code false} if not.
298   */
299  boolean hasSuperiorRules()
300  {
301    return superiorRules != null && !superiorRules.isEmpty();
302  }
303
304
305
306  /**
307   * Indicates whether this DIT structure rule is declared "obsolete".
308   *
309   * @return  {@code true} if this DIT structure rule is declared
310   *          "obsolete", or {@code false} if not.
311   */
312  public boolean isObsolete()
313  {
314    return isObsolete;
315  }
316
317
318
319  /**
320   * Retrieves a mapping between the names of any extra non-standard
321   * properties that may be associated with this DIT structure rule
322   * and the value for that property.
323   *
324   * @return  A mapping between the names of any extra non-standard
325   *          properties that may be associated with this DIT
326   *          structure rule and the value for that property.
327   */
328  @Override
329  public Map<String,List<String>> getExtraProperties()
330  {
331    return extraProperties;
332  }
333
334
335
336  /**
337   * Indicates whether the provided object is equal to this DIT
338   * structure rule.  The object will be considered equal if it is a
339   * DIT structure rule with the same OID as the current type.
340   *
341   * @param  o  The object for which to make the determination.
342   *
343   * @return  {@code true} if the provided object is equal to this
344   *          attribute, or {@code false} if not.
345   */
346  @Override
347  public boolean equals(Object o)
348  {
349    if (this == o)
350    {
351      return true;
352    }
353    if (!(o instanceof DITStructureRule))
354    {
355      return false;
356    }
357    return ruleID == ((DITStructureRule) o).ruleID;
358  }
359
360
361
362  /**
363   * Retrieves the hash code for this DIT structure rule.  It will be
364   * equal to the rule ID.
365   *
366   * @return  The hash code for this DIT structure rule.
367   */
368  @Override
369  public int hashCode()
370  {
371    return ruleID;
372  }
373
374
375
376  /**
377   * Retrieves the string representation of this attribute type in the
378   * form specified in RFC 2252.
379   *
380   * @return  The string representation of this attribute type in the
381   *          form specified in RFC 2252.
382   */
383  @Override
384  public String toString()
385  {
386    return definition;
387  }
388
389}