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