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