001 /*
002 * Copyright 2007-2016 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2016 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.ldap.sdk.schema;
022
023
024
025 import java.util.ArrayList;
026 import java.util.Collection;
027 import java.util.Collections;
028 import java.util.Map;
029 import java.util.LinkedHashMap;
030
031 import com.unboundid.ldap.sdk.LDAPException;
032 import com.unboundid.ldap.sdk.ResultCode;
033 import com.unboundid.util.NotMutable;
034 import com.unboundid.util.ThreadSafety;
035 import com.unboundid.util.ThreadSafetyLevel;
036
037 import static com.unboundid.ldap.sdk.schema.SchemaMessages.*;
038 import static com.unboundid.util.StaticUtils.*;
039 import static com.unboundid.util.Validator.*;
040
041
042
043 /**
044 * This class provides a data structure that describes an LDAP DIT content rule
045 * schema element.
046 */
047 @NotMutable()
048 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
049 public final class DITContentRuleDefinition
050 extends SchemaElement
051 {
052 /**
053 * The serial version UID for this serializable class.
054 */
055 private static final long serialVersionUID = 3224440505307817586L;
056
057
058
059 // Indicates whether this DIT content rule is declared obsolete.
060 private final boolean isObsolete;
061
062 // The set of extensions for this DIT content rule.
063 private final Map<String,String[]> extensions;
064
065 // The description for this DIT content rule.
066 private final String description;
067
068 // The string representation of this DIT content rule.
069 private final String ditContentRuleString;
070
071 // The OID of the structural object class with which this DIT content rule is
072 // associated.
073 private final String oid;
074
075 // The names/OIDs of the allowed auxiliary classes.
076 private final String[] auxiliaryClasses;
077
078 // The set of names for this DIT content rule.
079 private final String[] names;
080
081 // The names/OIDs of the optional attributes.
082 private final String[] optionalAttributes;
083
084 // The names/OIDs of the prohibited attributes.
085 private final String[] prohibitedAttributes;
086
087 // The names/OIDs of the required attributes.
088 private final String[] requiredAttributes;
089
090
091
092 /**
093 * Creates a new DIT content rule from the provided string representation.
094 *
095 * @param s The string representation of the DIT content rule to create,
096 * using the syntax described in RFC 4512 section 4.1.6. It must
097 * not be {@code null}.
098 *
099 * @throws LDAPException If the provided string cannot be decoded as a DIT
100 * content rule definition.
101 */
102 public DITContentRuleDefinition(final String s)
103 throws LDAPException
104 {
105 ensureNotNull(s);
106
107 ditContentRuleString = s.trim();
108
109 // The first character must be an opening parenthesis.
110 final int length = ditContentRuleString.length();
111 if (length == 0)
112 {
113 throw new LDAPException(ResultCode.DECODING_ERROR,
114 ERR_DCR_DECODE_EMPTY.get());
115 }
116 else if (ditContentRuleString.charAt(0) != '(')
117 {
118 throw new LDAPException(ResultCode.DECODING_ERROR,
119 ERR_DCR_DECODE_NO_OPENING_PAREN.get(
120 ditContentRuleString));
121 }
122
123
124 // Skip over any spaces until we reach the start of the OID, then read the
125 // OID until we find the next space.
126 int pos = skipSpaces(ditContentRuleString, 1, length);
127
128 StringBuilder buffer = new StringBuilder();
129 pos = readOID(ditContentRuleString, pos, length, buffer);
130 oid = buffer.toString();
131
132
133 // Technically, DIT content elements are supposed to appear in a specific
134 // order, but we'll be lenient and allow remaining elements to come in any
135 // order.
136 final ArrayList<String> nameList = new ArrayList<String>(1);
137 final ArrayList<String> reqAttrs = new ArrayList<String>();
138 final ArrayList<String> optAttrs = new ArrayList<String>();
139 final ArrayList<String> notAttrs = new ArrayList<String>();
140 final ArrayList<String> auxOCs = new ArrayList<String>();
141 final Map<String,String[]> exts = new LinkedHashMap<String,String[]>();
142 Boolean obsolete = null;
143 String descr = null;
144
145 while (true)
146 {
147 // Skip over any spaces until we find the next element.
148 pos = skipSpaces(ditContentRuleString, pos, length);
149
150 // Read until we find the next space or the end of the string. Use that
151 // token to figure out what to do next.
152 final int tokenStartPos = pos;
153 while ((pos < length) && (ditContentRuleString.charAt(pos) != ' '))
154 {
155 pos++;
156 }
157
158 // It's possible that the token could be smashed right up against the
159 // closing parenthesis. If that's the case, then extract just the token
160 // and handle the closing parenthesis the next time through.
161 String token = ditContentRuleString.substring(tokenStartPos, pos);
162 if ((token.length() > 1) && (token.endsWith(")")))
163 {
164 token = token.substring(0, token.length() - 1);
165 pos--;
166 }
167
168 final String lowerToken = toLowerCase(token);
169 if (lowerToken.equals(")"))
170 {
171 // This indicates that we're at the end of the value. There should not
172 // be any more closing characters.
173 if (pos < length)
174 {
175 throw new LDAPException(ResultCode.DECODING_ERROR,
176 ERR_DCR_DECODE_CLOSE_NOT_AT_END.get(
177 ditContentRuleString));
178 }
179 break;
180 }
181 else if (lowerToken.equals("name"))
182 {
183 if (nameList.isEmpty())
184 {
185 pos = skipSpaces(ditContentRuleString, pos, length);
186 pos = readQDStrings(ditContentRuleString, pos, length, nameList);
187 }
188 else
189 {
190 throw new LDAPException(ResultCode.DECODING_ERROR,
191 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get(
192 ditContentRuleString, "NAME"));
193 }
194 }
195 else if (lowerToken.equals("desc"))
196 {
197 if (descr == null)
198 {
199 pos = skipSpaces(ditContentRuleString, pos, length);
200
201 buffer = new StringBuilder();
202 pos = readQDString(ditContentRuleString, pos, length, buffer);
203 descr = buffer.toString();
204 }
205 else
206 {
207 throw new LDAPException(ResultCode.DECODING_ERROR,
208 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get(
209 ditContentRuleString, "DESC"));
210 }
211 }
212 else if (lowerToken.equals("obsolete"))
213 {
214 if (obsolete == null)
215 {
216 obsolete = true;
217 }
218 else
219 {
220 throw new LDAPException(ResultCode.DECODING_ERROR,
221 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get(
222 ditContentRuleString, "OBSOLETE"));
223 }
224 }
225 else if (lowerToken.equals("aux"))
226 {
227 if (auxOCs.isEmpty())
228 {
229 pos = skipSpaces(ditContentRuleString, pos, length);
230 pos = readOIDs(ditContentRuleString, pos, length, auxOCs);
231 }
232 else
233 {
234 throw new LDAPException(ResultCode.DECODING_ERROR,
235 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get(
236 ditContentRuleString, "AUX"));
237 }
238 }
239 else if (lowerToken.equals("must"))
240 {
241 if (reqAttrs.isEmpty())
242 {
243 pos = skipSpaces(ditContentRuleString, pos, length);
244 pos = readOIDs(ditContentRuleString, pos, length, reqAttrs);
245 }
246 else
247 {
248 throw new LDAPException(ResultCode.DECODING_ERROR,
249 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get(
250 ditContentRuleString, "MUST"));
251 }
252 }
253 else if (lowerToken.equals("may"))
254 {
255 if (optAttrs.isEmpty())
256 {
257 pos = skipSpaces(ditContentRuleString, pos, length);
258 pos = readOIDs(ditContentRuleString, pos, length, optAttrs);
259 }
260 else
261 {
262 throw new LDAPException(ResultCode.DECODING_ERROR,
263 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get(
264 ditContentRuleString, "MAY"));
265 }
266 }
267 else if (lowerToken.equals("not"))
268 {
269 if (notAttrs.isEmpty())
270 {
271 pos = skipSpaces(ditContentRuleString, pos, length);
272 pos = readOIDs(ditContentRuleString, pos, length, notAttrs);
273 }
274 else
275 {
276 throw new LDAPException(ResultCode.DECODING_ERROR,
277 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get(
278 ditContentRuleString, "NOT"));
279 }
280 }
281 else if (lowerToken.startsWith("x-"))
282 {
283 pos = skipSpaces(ditContentRuleString, pos, length);
284
285 final ArrayList<String> valueList = new ArrayList<String>();
286 pos = readQDStrings(ditContentRuleString, pos, length, valueList);
287
288 final String[] values = new String[valueList.size()];
289 valueList.toArray(values);
290
291 if (exts.containsKey(token))
292 {
293 throw new LDAPException(ResultCode.DECODING_ERROR,
294 ERR_DCR_DECODE_DUP_EXT.get(
295 ditContentRuleString, token));
296 }
297
298 exts.put(token, values);
299 }
300 else
301 {
302 throw new LDAPException(ResultCode.DECODING_ERROR,
303 ERR_DCR_DECODE_DUP_EXT.get(
304 ditContentRuleString, token));
305 }
306 }
307
308 description = descr;
309
310 names = new String[nameList.size()];
311 nameList.toArray(names);
312
313 auxiliaryClasses = new String[auxOCs.size()];
314 auxOCs.toArray(auxiliaryClasses);
315
316 requiredAttributes = new String[reqAttrs.size()];
317 reqAttrs.toArray(requiredAttributes);
318
319 optionalAttributes = new String[optAttrs.size()];
320 optAttrs.toArray(optionalAttributes);
321
322 prohibitedAttributes = new String[notAttrs.size()];
323 notAttrs.toArray(prohibitedAttributes);
324
325 isObsolete = (obsolete != null);
326
327 extensions = Collections.unmodifiableMap(exts);
328 }
329
330
331
332 /**
333 * Creates a new DIT content rule with the provided information.
334 *
335 * @param oid The OID for the structural object class with
336 * which this DIT content rule is associated.
337 * It must not be {@code null}.
338 * @param name The name for this DIT content rule. It may
339 * be {@code null} if the DIT content rule
340 * should only be referenced by OID.
341 * @param description The description for this DIT content rule.
342 * It may be {@code null} if there is no
343 * description.
344 * @param auxiliaryClasses The names/OIDs of the auxiliary object
345 * classes that may be present in entries
346 * containing this DIT content rule.
347 * @param requiredAttributes The names/OIDs of the attributes which must
348 * be present in entries containing this DIT
349 * content rule.
350 * @param optionalAttributes The names/OIDs of the attributes which may be
351 * present in entries containing this DIT
352 * content rule.
353 * @param prohibitedAttributes The names/OIDs of the attributes which may
354 * not be present in entries containing this DIT
355 * content rule.
356 * @param extensions The set of extensions for this DIT content
357 * rule. It may be {@code null} or empty if
358 * there should not be any extensions.
359 */
360 public DITContentRuleDefinition(final String oid, final String name,
361 final String description,
362 final String[] auxiliaryClasses,
363 final String[] requiredAttributes,
364 final String[] optionalAttributes,
365 final String[] prohibitedAttributes,
366 final Map<String,String[]> extensions)
367 {
368 this(oid, ((name == null) ? null : new String[] { name }), description,
369 false, auxiliaryClasses, requiredAttributes, optionalAttributes,
370 prohibitedAttributes, extensions);
371 }
372
373
374
375 /**
376 * Creates a new DIT content rule with the provided information.
377 *
378 * @param oid The OID for the structural object class with
379 * which this DIT content rule is associated.
380 * It must not be {@code null}.
381 * @param name The name for this DIT content rule. It may
382 * be {@code null} if the DIT content rule
383 * should only be referenced by OID.
384 * @param description The description for this DIT content rule.
385 * It may be {@code null} if there is no
386 * description.
387 * @param auxiliaryClasses The names/OIDs of the auxiliary object
388 * classes that may be present in entries
389 * containing this DIT content rule.
390 * @param requiredAttributes The names/OIDs of the attributes which must
391 * be present in entries containing this DIT
392 * content rule.
393 * @param optionalAttributes The names/OIDs of the attributes which may be
394 * present in entries containing this DIT
395 * content rule.
396 * @param prohibitedAttributes The names/OIDs of the attributes which may
397 * not be present in entries containing this DIT
398 * content rule.
399 * @param extensions The set of extensions for this DIT content
400 * rule. It may be {@code null} or empty if
401 * there should not be any extensions.
402 */
403 public DITContentRuleDefinition(final String oid, final String name,
404 final String description,
405 final Collection<String> auxiliaryClasses,
406 final Collection<String> requiredAttributes,
407 final Collection<String> optionalAttributes,
408 final Collection<String> prohibitedAttributes,
409 final Map<String,String[]> extensions)
410 {
411 this(oid, ((name == null) ? null : new String[] { name }), description,
412 false, toArray(auxiliaryClasses), toArray(requiredAttributes),
413 toArray(optionalAttributes), toArray(prohibitedAttributes),
414 extensions);
415 }
416
417
418
419 /**
420 * Creates a new DIT content rule with the provided information.
421 *
422 * @param oid The OID for the structural object class with
423 * which this DIT content rule is associated.
424 * It must not be {@code null}.
425 * @param names The set of names for this DIT content rule.
426 * It may be {@code null} or empty if the DIT
427 * content rule should only be referenced by
428 * OID.
429 * @param description The description for this DIT content rule.
430 * It may be {@code null} if there is no
431 * description.
432 * @param isObsolete Indicates whether this DIT content rule is
433 * declared obsolete.
434 * @param auxiliaryClasses The names/OIDs of the auxiliary object
435 * classes that may be present in entries
436 * containing this DIT content rule.
437 * @param requiredAttributes The names/OIDs of the attributes which must
438 * be present in entries containing this DIT
439 * content rule.
440 * @param optionalAttributes The names/OIDs of the attributes which may be
441 * present in entries containing this DIT
442 * content rule.
443 * @param prohibitedAttributes The names/OIDs of the attributes which may
444 * not be present in entries containing this DIT
445 * content rule.
446 * @param extensions The set of extensions for this DIT content
447 * rule. It may be {@code null} or empty if
448 * there should not be any extensions.
449 */
450 public DITContentRuleDefinition(final String oid, final String[] names,
451 final String description,
452 final boolean isObsolete,
453 final String[] auxiliaryClasses,
454 final String[] requiredAttributes,
455 final String[] optionalAttributes,
456 final String[] prohibitedAttributes,
457 final Map<String,String[]> extensions)
458 {
459 ensureNotNull(oid);
460
461 this.oid = oid;
462 this.isObsolete = isObsolete;
463 this.description = description;
464
465 if (names == null)
466 {
467 this.names = NO_STRINGS;
468 }
469 else
470 {
471 this.names = names;
472 }
473
474 if (auxiliaryClasses == null)
475 {
476 this.auxiliaryClasses = NO_STRINGS;
477 }
478 else
479 {
480 this.auxiliaryClasses = auxiliaryClasses;
481 }
482
483 if (requiredAttributes == null)
484 {
485 this.requiredAttributes = NO_STRINGS;
486 }
487 else
488 {
489 this.requiredAttributes = requiredAttributes;
490 }
491
492 if (optionalAttributes == null)
493 {
494 this.optionalAttributes = NO_STRINGS;
495 }
496 else
497 {
498 this.optionalAttributes = optionalAttributes;
499 }
500
501 if (prohibitedAttributes == null)
502 {
503 this.prohibitedAttributes = NO_STRINGS;
504 }
505 else
506 {
507 this.prohibitedAttributes = prohibitedAttributes;
508 }
509
510 if (extensions == null)
511 {
512 this.extensions = Collections.emptyMap();
513 }
514 else
515 {
516 this.extensions = Collections.unmodifiableMap(extensions);
517 }
518
519 final StringBuilder buffer = new StringBuilder();
520 createDefinitionString(buffer);
521 ditContentRuleString = buffer.toString();
522 }
523
524
525
526 /**
527 * Constructs a string representation of this DIT content rule definition in
528 * the provided buffer.
529 *
530 * @param buffer The buffer in which to construct a string representation of
531 * this DIT content rule definition.
532 */
533 private void createDefinitionString(final StringBuilder buffer)
534 {
535 buffer.append("( ");
536 buffer.append(oid);
537
538 if (names.length == 1)
539 {
540 buffer.append(" NAME '");
541 buffer.append(names[0]);
542 buffer.append('\'');
543 }
544 else if (names.length > 1)
545 {
546 buffer.append(" NAME (");
547 for (final String name : names)
548 {
549 buffer.append(" '");
550 buffer.append(name);
551 buffer.append('\'');
552 }
553 buffer.append(" )");
554 }
555
556 if (description != null)
557 {
558 buffer.append(" DESC '");
559 encodeValue(description, buffer);
560 buffer.append('\'');
561 }
562
563 if (isObsolete)
564 {
565 buffer.append(" OBSOLETE");
566 }
567
568 if (auxiliaryClasses.length == 1)
569 {
570 buffer.append(" AUX ");
571 buffer.append(auxiliaryClasses[0]);
572 }
573 else if (auxiliaryClasses.length > 1)
574 {
575 buffer.append(" AUX (");
576 for (int i=0; i < auxiliaryClasses.length; i++)
577 {
578 if (i >0)
579 {
580 buffer.append(" $ ");
581 }
582 else
583 {
584 buffer.append(' ');
585 }
586 buffer.append(auxiliaryClasses[i]);
587 }
588 buffer.append(" )");
589 }
590
591 if (requiredAttributes.length == 1)
592 {
593 buffer.append(" MUST ");
594 buffer.append(requiredAttributes[0]);
595 }
596 else if (requiredAttributes.length > 1)
597 {
598 buffer.append(" MUST (");
599 for (int i=0; i < requiredAttributes.length; i++)
600 {
601 if (i >0)
602 {
603 buffer.append(" $ ");
604 }
605 else
606 {
607 buffer.append(' ');
608 }
609 buffer.append(requiredAttributes[i]);
610 }
611 buffer.append(" )");
612 }
613
614 if (optionalAttributes.length == 1)
615 {
616 buffer.append(" MAY ");
617 buffer.append(optionalAttributes[0]);
618 }
619 else if (optionalAttributes.length > 1)
620 {
621 buffer.append(" MAY (");
622 for (int i=0; i < optionalAttributes.length; i++)
623 {
624 if (i > 0)
625 {
626 buffer.append(" $ ");
627 }
628 else
629 {
630 buffer.append(' ');
631 }
632 buffer.append(optionalAttributes[i]);
633 }
634 buffer.append(" )");
635 }
636
637 if (prohibitedAttributes.length == 1)
638 {
639 buffer.append(" NOT ");
640 buffer.append(prohibitedAttributes[0]);
641 }
642 else if (prohibitedAttributes.length > 1)
643 {
644 buffer.append(" NOT (");
645 for (int i=0; i < prohibitedAttributes.length; i++)
646 {
647 if (i > 0)
648 {
649 buffer.append(" $ ");
650 }
651 else
652 {
653 buffer.append(' ');
654 }
655 buffer.append(prohibitedAttributes[i]);
656 }
657 buffer.append(" )");
658 }
659
660 for (final Map.Entry<String,String[]> e : extensions.entrySet())
661 {
662 final String name = e.getKey();
663 final String[] values = e.getValue();
664 if (values.length == 1)
665 {
666 buffer.append(' ');
667 buffer.append(name);
668 buffer.append(" '");
669 encodeValue(values[0], buffer);
670 buffer.append('\'');
671 }
672 else
673 {
674 buffer.append(' ');
675 buffer.append(name);
676 buffer.append(" (");
677 for (final String value : values)
678 {
679 buffer.append(" '");
680 encodeValue(value, buffer);
681 buffer.append('\'');
682 }
683 buffer.append(" )");
684 }
685 }
686
687 buffer.append(" )");
688 }
689
690
691
692 /**
693 * Retrieves the OID for the structural object class associated with this
694 * DIT content rule.
695 *
696 * @return The OID for the structural object class associated with this DIT
697 * content rule.
698 */
699 public String getOID()
700 {
701 return oid;
702 }
703
704
705
706 /**
707 * Retrieves the set of names for this DIT content rule.
708 *
709 * @return The set of names for this DIT content rule, or an empty array if
710 * it does not have any names.
711 */
712 public String[] getNames()
713 {
714 return names;
715 }
716
717
718
719 /**
720 * Retrieves the primary name that can be used to reference this DIT content
721 * rule. If one or more names are defined, then the first name will be used.
722 * Otherwise, the structural object class OID will be returned.
723 *
724 * @return The primary name that can be used to reference this DIT content
725 * rule.
726 */
727 public String getNameOrOID()
728 {
729 if (names.length == 0)
730 {
731 return oid;
732 }
733 else
734 {
735 return names[0];
736 }
737 }
738
739
740
741 /**
742 * Indicates whether the provided string matches the OID or any of the names
743 * for this DIT content rule.
744 *
745 * @param s The string for which to make the determination. It must not be
746 * {@code null}.
747 *
748 * @return {@code true} if the provided string matches the OID or any of the
749 * names for this DIT content rule, or {@code false} if not.
750 */
751 public boolean hasNameOrOID(final String s)
752 {
753 for (final String name : names)
754 {
755 if (s.equalsIgnoreCase(name))
756 {
757 return true;
758 }
759 }
760
761 return s.equalsIgnoreCase(oid);
762 }
763
764
765
766 /**
767 * Retrieves the description for this DIT content rule, if available.
768 *
769 * @return The description for this DIT content rule, or {@code null} if
770 * there is no description defined.
771 */
772 public String getDescription()
773 {
774 return description;
775 }
776
777
778
779 /**
780 * Indicates whether this DIT content rule is declared obsolete.
781 *
782 * @return {@code true} if this DIT content rule is declared obsolete, or
783 * {@code false} if it is not.
784 */
785 public boolean isObsolete()
786 {
787 return isObsolete;
788 }
789
790
791
792 /**
793 * Retrieves the names or OIDs of the auxiliary object classes that may be
794 * present in entries containing the structural class for this DIT content
795 * rule.
796 *
797 * @return The names or OIDs of the auxiliary object classes that may be
798 * present in entries containing the structural class for this DIT
799 * content rule.
800 */
801 public String[] getAuxiliaryClasses()
802 {
803 return auxiliaryClasses;
804 }
805
806
807
808 /**
809 * Retrieves the names or OIDs of the attributes that are required to be
810 * present in entries containing the structural object class for this DIT
811 * content rule.
812 *
813 * @return The names or OIDs of the attributes that are required to be
814 * present in entries containing the structural object class for this
815 * DIT content rule, or an empty array if there are no required
816 * attributes.
817 */
818 public String[] getRequiredAttributes()
819 {
820 return requiredAttributes;
821 }
822
823
824
825 /**
826 * Retrieves the names or OIDs of the attributes that are optionally allowed
827 * to be present in entries containing the structural object class for this
828 * DIT content rule.
829 *
830 * @return The names or OIDs of the attributes that are optionally allowed to
831 * be present in entries containing the structural object class for
832 * this DIT content rule, or an empty array if there are no required
833 * attributes.
834 */
835 public String[] getOptionalAttributes()
836 {
837 return optionalAttributes;
838 }
839
840
841
842 /**
843 * Retrieves the names or OIDs of the attributes that are not allowed to be
844 * present in entries containing the structural object class for this DIT
845 * content rule.
846 *
847 * @return The names or OIDs of the attributes that are not allowed to be
848 * present in entries containing the structural object class for this
849 * DIT content rule, or an empty array if there are no required
850 * attributes.
851 */
852 public String[] getProhibitedAttributes()
853 {
854 return prohibitedAttributes;
855 }
856
857
858
859 /**
860 * Retrieves the set of extensions for this DIT content rule. They will be
861 * mapped from the extension name (which should start with "X-") to the set of
862 * values for that extension.
863 *
864 * @return The set of extensions for this DIT content rule.
865 */
866 public Map<String,String[]> getExtensions()
867 {
868 return extensions;
869 }
870
871
872
873 /**
874 * {@inheritDoc}
875 */
876 @Override()
877 public int hashCode()
878 {
879 return oid.hashCode();
880 }
881
882
883
884 /**
885 * {@inheritDoc}
886 */
887 @Override()
888 public boolean equals(final Object o)
889 {
890 if (o == null)
891 {
892 return false;
893 }
894
895 if (o == this)
896 {
897 return true;
898 }
899
900 if (! (o instanceof DITContentRuleDefinition))
901 {
902 return false;
903 }
904
905 final DITContentRuleDefinition d = (DITContentRuleDefinition) o;
906 return (oid.equals(d.oid) &&
907 stringsEqualIgnoreCaseOrderIndependent(names, d.names) &&
908 stringsEqualIgnoreCaseOrderIndependent(auxiliaryClasses,
909 d.auxiliaryClasses) &&
910 stringsEqualIgnoreCaseOrderIndependent(requiredAttributes,
911 d.requiredAttributes) &&
912 stringsEqualIgnoreCaseOrderIndependent(optionalAttributes,
913 d.optionalAttributes) &&
914 stringsEqualIgnoreCaseOrderIndependent(prohibitedAttributes,
915 d.prohibitedAttributes) &&
916 bothNullOrEqualIgnoreCase(description, d.description) &&
917 (isObsolete == d.isObsolete) &&
918 extensionsEqual(extensions, d.extensions));
919 }
920
921
922
923 /**
924 * Retrieves a string representation of this DIT content rule definition, in
925 * the format described in RFC 4512 section 4.1.6.
926 *
927 * @return A string representation of this DIT content rule definition.
928 */
929 @Override()
930 public String toString()
931 {
932 return ditContentRuleString;
933 }
934 }