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