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