001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.shared.ldap.schema;
021
022
023 import java.util.ArrayList;
024 import java.util.List;
025
026 import org.apache.directory.shared.i18n.I18n;
027 import org.apache.directory.shared.ldap.exception.LdapException;
028 import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry;
029 import org.apache.directory.shared.ldap.schema.registries.ObjectClassRegistry;
030 import org.apache.directory.shared.ldap.schema.registries.Registries;
031
032
033 /**
034 * A ditContentRule specification. ditContentRules identify the content of
035 * entries of a particular structural objectClass. They specify the AUXILIARY
036 * objectClasses and additional attribute types permitted to appear, or excluded
037 * from appearing in entries of the indicated STRUCTURAL objectClass.
038 * <p>
039 * According to ldapbis [MODELS]:
040 * </p>
041 *
042 * <pre>
043 * 4.1.6. DIT Content Rules
044 *
045 * A DIT content rule is a "rule governing the content of entries of a
046 * particular structural object class" [X.501].
047 *
048 * For DIT entries of a particular structural object class, a DIT content
049 * rule specifies which auxiliary object classes the entries are allowed
050 * to belong to and which additional attributes (by type) are required,
051 * allowed or not allowed to appear in the entries.
052 *
053 * The list of precluded attributes cannot include any attribute listed
054 * as mandatory in rule, the structural object class, or any of the
055 * allowed auxiliary object classes.
056 *
057 * Each content rule is identified by the object identifier, as well as
058 * any short names (descriptors), of the structural object class it
059 * applies to.
060 *
061 * An entry may only belong to auxiliary object classes listed in the
062 * governing content rule.
063 *
064 * An entry must contain all attributes required by the object classes
065 * the entry belongs to as well as all attributed required by the
066 * governing content rule.
067 *
068 * An entry may contain any non-precluded attributes allowed by the
069 * object classes the entry belongs to as well as all attributes allowed
070 * by the governing content rule.
071 *
072 * An entry cannot include any attribute precluded by the governing
073 * content rule.
074 *
075 * An entry is governed by (if present and active in the subschema) the
076 * DIT content rule which applies to the structural object class of the
077 * entry (see Section 2.4.2). If no active rule is present for the
078 * entry's structural object class, the entry's content is governed by
079 * the structural object class (and possibly other aspects of user and
080 * system schema).
081 *
082 * DIT content rule descriptions are written according to the ABNF:
083 *
084 * DITContentRuleDescription = LPAREN WSP
085 * numericoid ; object identifier
086 * [ SP "NAME" SP qdescrs ] ; short names (descriptors)
087 * [ SP "DESC" SP qdstring ] ; description
088 * [ SP "OBSOLETE" ] ; not active
089 * [ SP "AUX" SP oids ] ; auxiliary object classes
090 * [ SP "MUST" SP oids ] ; attribute types
091 * [ SP "MAY" SP oids ] ; attribute types
092 * [ SP "NOT" SP oids ] ; attribute types
093 * extensions WSP RPAREN ; extensions
094 *
095 * where:
096 *
097 * [numericoid] is the object identifier of the structural object class
098 * associated with this DIT content rule;
099 * NAME [qdescrs] are short names (descriptors) identifying this DIT
100 * content rule;
101 * DESC [qdstring] is a short descriptive string;
102 * OBSOLETE indicates this DIT content rule use is not active;
103 * AUX specifies a list of auxiliary object classes which entries
104 * subject to this DIT content rule may belong to;
105 * MUST, MAY, and NOT specify lists of attribute types which are
106 * required, allowed, or precluded, respectively, from appearing in
107 * entries subject to this DIT content rule; and
108 * [extensions] describe extensions.
109 * </pre>
110 *
111 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 5.4.3</a>
112 * @see <a
113 * href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
114 * [MODELS]</a>
115 * @see DescriptionUtils#getDescription(DITContentRule)
116 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
117 * @version $Rev: 927122 $
118 */
119 public class DITContentRule extends AbstractSchemaObject
120 {
121 /** The serialVersionUID */
122 public static final long serialVersionUID = 1L;
123
124 /** The list of Auxiliary ObjectClass OIDs entries may belong to */
125 private List<String> auxObjectClassOids;
126
127 /** The list of Auxiliary ObjectClass entries may belong to */
128 private List<ObjectClass> auxObjectClasses;
129
130 /** The list of allowed AttributeType OIDs */
131 private List<String> mayAttributeTypeOids;
132
133 /** The list of allowed AttributeTypes */
134 private List<AttributeType> mayAttributeTypes;
135
136 /** The list of required AttributeType OIDs */
137 private List<String> mustAttributeTypeOids;
138
139 /** The list of required AttributeTypes */
140 private List<AttributeType> mustAttributeTypes;
141
142 /** The list of precluded AttributeType OIDs */
143 private List<String> notAttributeTypeOids;
144
145 /** The list of precluded AttributeTypes */
146 private List<AttributeType> notAttributeTypes;
147
148
149 /**
150 * Creates a DITContentRule object using a unique OID.
151 *
152 * @param oid the OID for this DITContentRule
153 */
154 public DITContentRule( String oid )
155 {
156 super( SchemaObjectType.DIT_CONTENT_RULE, oid );
157
158 mayAttributeTypeOids = new ArrayList<String>();
159 mustAttributeTypeOids = new ArrayList<String>();
160 notAttributeTypeOids = new ArrayList<String>();
161 auxObjectClassOids = new ArrayList<String>();
162
163 mayAttributeTypes = new ArrayList<AttributeType>();
164 mustAttributeTypes = new ArrayList<AttributeType>();
165 notAttributeTypes = new ArrayList<AttributeType>();
166 auxObjectClasses = new ArrayList<ObjectClass>();
167 }
168
169
170 /**
171 * @return the auxObjectClassOids
172 */
173 public List<String> getAuxObjectClassOids()
174 {
175 return auxObjectClassOids;
176 }
177
178
179 /**
180 * Add an Auxiliary ObjectClass Oid
181 *
182 * @param oid The ObjectClass oid
183 */
184 public void addAuxObjectClassOidOids( String oid )
185 {
186 if ( locked )
187 {
188 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
189 }
190
191 if ( !isReadOnly )
192 {
193 auxObjectClassOids.add( oid );
194 }
195 }
196
197
198 /**
199 * Add an Auxiliary ObjectClass
200 *
201 * @param oid The ObjectClass
202 */
203 public void addAuxObjectClasses( ObjectClass objectClass )
204 {
205 if ( locked )
206 {
207 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
208 }
209
210 if ( !isReadOnly )
211 {
212 if ( !auxObjectClassOids.contains( objectClass.getOid() ) )
213 {
214 auxObjectClasses.add( objectClass );
215 auxObjectClassOids.add( objectClass.getOid() );
216 }
217 }
218 }
219
220
221 /**
222 * @param auxObjectClassOids the auxObjectClassOids to set
223 */
224 public void setAuxObjectClassOids( List<String> auxObjectClassOids )
225 {
226 if ( locked )
227 {
228 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
229 }
230
231 if ( !isReadOnly )
232 {
233 this.auxObjectClassOids = auxObjectClassOids;
234 }
235 }
236
237
238 /**
239 * @param auxObjectClasses the auxObjectClasses to set
240 */
241 public void setAuxObjectClasses( List<ObjectClass> auxObjectClasses )
242 {
243 if ( locked )
244 {
245 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
246 }
247
248 if ( !isReadOnly )
249 {
250 this.auxObjectClasses = auxObjectClasses;
251
252 // update the OIDS now
253 auxObjectClassOids.clear();
254
255 for ( ObjectClass oc : auxObjectClasses )
256 {
257 auxObjectClassOids.add( oc.getOid() );
258 }
259 }
260 }
261
262
263 /**
264 * @return the auxObjectClasses
265 */
266 public List<ObjectClass> getAuxObjectClasses()
267 {
268 return auxObjectClasses;
269 }
270
271
272 /**
273 * @return the mayAttributeTypeOids
274 */
275 public List<String> getMayAttributeTypeOids()
276 {
277 return mayAttributeTypeOids;
278 }
279
280
281 /**
282 * Add an allowed AttributeType
283 *
284 * @param oid The attributeType oid
285 */
286 public void addMayAttributeTypeOids( String oid )
287 {
288 if ( locked )
289 {
290 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
291 }
292
293 if ( !isReadOnly )
294 {
295 mayAttributeTypeOids.add( oid );
296 }
297 }
298
299
300 /**
301 * Add an allowed AttributeType
302 *
303 * @param attributeType The attributeType
304 */
305 public void addMayAttributeTypes( AttributeType attributeType )
306 {
307 if ( locked )
308 {
309 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
310 }
311
312 if ( !isReadOnly )
313 {
314 if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) )
315 {
316 mayAttributeTypes.add( attributeType );
317 mayAttributeTypeOids.add( attributeType.getOid() );
318 }
319 }
320 }
321
322
323 /**
324 * @param mayAttributeTypeOids the mayAttributeTypeOids to set
325 */
326 public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids )
327 {
328 if ( locked )
329 {
330 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
331 }
332
333 if ( !isReadOnly )
334 {
335 this.mayAttributeTypeOids = mayAttributeTypeOids;
336 }
337 }
338
339
340 /**
341 * Sets the list of allowed AttributeTypes
342 *
343 * @param mayAttributeTypes the list of allowed AttributeTypes
344 */
345 public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes )
346 {
347 if ( locked )
348 {
349 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
350 }
351
352 if ( !isReadOnly )
353 {
354 this.mayAttributeTypes = mayAttributeTypes;
355
356 // update the OIDS now
357 mayAttributeTypeOids.clear();
358
359 for ( AttributeType may : mayAttributeTypes )
360 {
361 mayAttributeTypeOids.add( may.getOid() );
362 }
363 }
364 }
365
366
367 /**
368 * @return the mayAttributeTypes
369 */
370 public List<AttributeType> getMayAttributeTypes()
371 {
372 return mayAttributeTypes;
373 }
374
375
376 /**
377 * @return the mustAttributeTypeOids
378 */
379 public List<String> getMustAttributeTypeOids()
380 {
381 return mustAttributeTypeOids;
382 }
383
384
385 /**
386 * Add a required AttributeType OID
387 *
388 * @param oid The attributeType OID
389 */
390 public void addMustAttributeTypeOids( String oid )
391 {
392 if ( locked )
393 {
394 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
395 }
396
397 if ( !isReadOnly )
398 {
399 mustAttributeTypeOids.add( oid );
400 }
401 }
402
403
404 /**
405 * Add a required AttributeType
406 *
407 * @param attributeType The attributeType
408 */
409 public void addMustAttributeTypes( AttributeType attributeType )
410 {
411 if ( locked )
412 {
413 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
414 }
415
416 if ( !isReadOnly )
417 {
418 if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) )
419 {
420 mustAttributeTypes.add( attributeType );
421 mustAttributeTypeOids.add( attributeType.getOid() );
422 }
423 }
424 }
425
426
427 /**
428 * @param mustAttributeTypeOids the mustAttributeTypeOids to set
429 */
430 public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids )
431 {
432 if ( locked )
433 {
434 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
435 }
436
437 if ( !isReadOnly )
438 {
439 this.mustAttributeTypeOids = mustAttributeTypeOids;
440 }
441 }
442
443
444 /**
445 * Sets the list of required AttributeTypes
446 *
447 * @param mayAttributeTypes the list of required AttributeTypes
448 */
449 public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes )
450 {
451 if ( locked )
452 {
453 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
454 }
455
456 if ( !isReadOnly )
457 {
458 this.mustAttributeTypes = mustAttributeTypes;
459
460 // update the OIDS now
461 mustAttributeTypeOids.clear();
462
463 for ( AttributeType may : mustAttributeTypes )
464 {
465 mustAttributeTypeOids.add( may.getOid() );
466 }
467 }
468 }
469
470
471 /**
472 * @return the mustAttributeTypes
473 */
474 public List<AttributeType> getMustAttributeTypes()
475 {
476 return mustAttributeTypes;
477 }
478
479
480 /**
481 * @return the notAttributeTypeOids
482 */
483 public List<String> getNotAttributeTypeOids()
484 {
485 return notAttributeTypeOids;
486 }
487
488
489 /**
490 * Add a precluded AttributeType
491 *
492 * @param oid The attributeType oid
493 */
494 public void addNotAttributeTypeOids( String oid )
495 {
496 if ( locked )
497 {
498 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
499 }
500
501 if ( !isReadOnly )
502 {
503 notAttributeTypeOids.add( oid );
504 }
505 }
506
507
508 /**
509 * Add a precluded AttributeType
510 *
511 * @param attributeType The attributeType
512 */
513 public void addNotAttributeTypes( AttributeType attributeType )
514 {
515 if ( locked )
516 {
517 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
518 }
519
520 if ( !isReadOnly )
521 {
522 if ( !notAttributeTypeOids.contains( attributeType.getOid() ) )
523 {
524 notAttributeTypes.add( attributeType );
525 notAttributeTypeOids.add( attributeType.getOid() );
526 }
527 }
528 }
529
530
531 /**
532 * @param notAttributeTypeOids the notAttributeTypeOids to set
533 */
534 public void setNotAttributeTypeOids( List<String> notAttributeTypeOids )
535 {
536 if ( locked )
537 {
538 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
539 }
540
541 if ( !isReadOnly )
542 {
543 this.notAttributeTypeOids = notAttributeTypeOids;
544 }
545 }
546
547
548 /**
549 * Sets the list of precluded AttributeTypes
550 *
551 * @param mayAttributeTypes the list of precluded AttributeTypes
552 */
553 public void setNotAttributeTypes( List<AttributeType> notAttributeTypes )
554 {
555 if ( locked )
556 {
557 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
558 }
559
560 if ( !isReadOnly )
561 {
562 this.notAttributeTypes = notAttributeTypes;
563
564 // update the OIDS now
565 notAttributeTypeOids.clear();
566
567 for ( AttributeType not : notAttributeTypes )
568 {
569 notAttributeTypeOids.add( not.getOid() );
570 }
571 }
572 }
573
574
575 /**
576 * @return the notAttributeTypes
577 */
578 public List<AttributeType> getNotAttributeTypes()
579 {
580 return notAttributeTypes;
581 }
582
583
584 /**
585 * Inject the DITContentRule into the registries, updating the references to
586 * other SchemaObject
587 *
588 * @param registries The Registries
589 * @exception If the addition failed
590 */
591 public void addToRegistries( Registries registries ) throws LdapException
592 {
593 if ( registries != null )
594 {
595 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
596 ObjectClassRegistry ocRegistry = registries.getObjectClassRegistry();
597
598 if ( mayAttributeTypeOids != null )
599 {
600 mayAttributeTypes = new ArrayList<AttributeType>( mayAttributeTypeOids.size() );
601
602 for ( String oid : mayAttributeTypeOids )
603 {
604 mayAttributeTypes.add( atRegistry.lookup( oid ) );
605 }
606 }
607
608 if ( mustAttributeTypeOids != null )
609 {
610 mustAttributeTypes = new ArrayList<AttributeType>( mustAttributeTypeOids.size() );
611
612 for ( String oid : mustAttributeTypeOids )
613 {
614 mustAttributeTypes.add( atRegistry.lookup( oid ) );
615 }
616 }
617
618 if ( notAttributeTypeOids != null )
619 {
620 notAttributeTypes = new ArrayList<AttributeType>( notAttributeTypeOids.size() );
621
622 for ( String oid : notAttributeTypeOids )
623 {
624 notAttributeTypes.add( atRegistry.lookup( oid ) );
625 }
626 }
627
628 if ( auxObjectClassOids != null )
629 {
630 auxObjectClasses = new ArrayList<ObjectClass>( auxObjectClassOids.size() );
631
632 for ( String oid : auxObjectClassOids )
633 {
634 auxObjectClasses.add( ocRegistry.lookup( oid ) );
635 }
636 }
637 }
638 }
639
640
641 /**
642 * @see Object#toString()
643 */
644 public String toString()
645 {
646 return objectType + " " + DescriptionUtils.getDescription( this );
647 }
648
649
650 /**
651 * Copy a DITContentRule
652 */
653 public DITContentRule copy()
654 {
655 DITContentRule copy = new DITContentRule( oid );
656
657 // Copy the SchemaObject common data
658 copy.copy( this );
659
660 // copy the AUX ObjectClasses OIDs
661 copy.auxObjectClassOids = new ArrayList<String>();
662
663 for ( String oid : auxObjectClassOids )
664 {
665 copy.auxObjectClassOids.add( oid );
666 }
667
668 // copy the AUX ObjectClasses ( will be empty )
669 copy.auxObjectClasses = new ArrayList<ObjectClass>();
670
671 // Clone the MAY AttributeTypes OIDs
672 copy.mayAttributeTypeOids = new ArrayList<String>();
673
674 for ( String oid : mayAttributeTypeOids )
675 {
676 copy.mayAttributeTypeOids.add( oid );
677 }
678
679 // Clone the MAY AttributeTypes ( will be empty )
680 copy.mayAttributeTypes = new ArrayList<AttributeType>();
681
682 // Clone the MUST AttributeTypes OIDs
683 copy.mustAttributeTypeOids = new ArrayList<String>();
684
685 for ( String oid : mustAttributeTypeOids )
686 {
687 copy.mustAttributeTypeOids.add( oid );
688 }
689
690 // Clone the MUST AttributeTypes ( will be empty )
691 copy.mustAttributeTypes = new ArrayList<AttributeType>();
692
693 // Clone the NOT AttributeTypes OIDs
694 copy.notAttributeTypeOids = new ArrayList<String>();
695
696 for ( String oid : notAttributeTypeOids )
697 {
698 copy.notAttributeTypeOids.add( oid );
699 }
700
701 // Clone the NOT AttributeTypes ( will be empty )
702 copy.notAttributeTypes = new ArrayList<AttributeType>();
703
704 return copy;
705 }
706
707
708 /**
709 * @see Object#equals(Object)
710 */
711 public boolean equals( Object o )
712 {
713 if ( !super.equals( o ) )
714 {
715 return false;
716 }
717
718 if ( !( o instanceof DITContentRule ) )
719 {
720 return false;
721 }
722
723 DITContentRule that = ( DITContentRule ) o;
724
725 // TODO : complete the check
726 return true;
727 }
728
729
730 /**
731 * {@inheritDoc}
732 */
733 public void clear()
734 {
735 // Clear the common elements
736 super.clear();
737
738 // Clear the references
739 auxObjectClasses.clear();
740 auxObjectClassOids.clear();
741 mayAttributeTypes.clear();
742 mayAttributeTypeOids.clear();
743 mustAttributeTypes.clear();
744 mustAttributeTypeOids.clear();
745 notAttributeTypes.clear();
746 notAttributeTypeOids.clear();
747 }
748 }