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/**
030 * A dITStructureRule definition. A dITStructureRules is a rule governing the
031 * structure of the DIT by specifying a permitted superior to subordinate entry
032 * relationship. A structure rule relates a nameForm, and therefore a STRUCTURAL
033 * objectClass, to superior dITStructureRules. This permits entries of the
034 * STRUCTURAL objectClass identified by the nameForm to exist in the DIT as
035 * subordinates to entries governed by the indicated superior dITStructureRules.
036 * Hence dITStructureRules only apply to structural object classes.
037 * <p>
038 * According to ldapbis [MODELS]:
039 * </p>
040 * 
041 * <pre>
042 *  DIT structure rule descriptions are written according to the ABNF:
043 *  
044 *    DITStructureRuleDescription = LPAREN WSP
045 *        ruleid                    ; rule identifier
046 *        [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
047 *        [ SP &quot;DESC&quot; SP qdstring ] ; description
048 *        [ SP &quot;OBSOLETE&quot; ]         ; not active
049 *        SP &quot;FORM&quot; SP oid          ; NameForm
050 *        [ SP &quot;SUP&quot; ruleids ]      ; superior rules
051 *        extensions WSP RPAREN     ; extensions
052 * 
053 *    ruleids = ruleid / ( LPAREN WSP ruleidlist WSP RPAREN )
054 * 
055 *    ruleidlist = ruleid *( SP ruleid )
056 * 
057 *    ruleid = number
058 * 
059 *  where:
060 *    [ruleid] is the rule identifier of this DIT structure rule;
061 *    NAME [qdescrs] are short names (descriptors) identifying this DIT
062 *        structure rule;
063 *    DESC [qdstring] is a short descriptive string;
064 *    OBSOLETE indicates this DIT structure rule use is not active;
065 *    FORM is specifies the name form associated with this DIT structure
066 *        rule;
067 *    SUP identifies superior rules (by rule id); and
068 *    [extensions] describe extensions.
069 *  
070 *  If no superior rules are identified, the DIT structure rule applies
071 *  to an autonomous administrative point (e.g. the root vertex of the
072 *  subtree controlled by the subschema) [X.501].
073 * </pre>
074 * 
075 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC2252 Section 6.33</a>
076 * @see <a
077 *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
078 *      [MODELS]</a>
079 * @see DescriptionUtils#getDescription(DitStructureRule)
080 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
081 */
082public class DitStructureRule extends AbstractSchemaObject
083{
084    /** The mandatory serialVersionUID */
085    public static final long serialVersionUID = 1L;
086
087    /** The rule ID. A DSR does not have an OID */
088    private int ruleId;
089
090    /** The associated NameForm */
091    private String form;
092
093    /** The list of superiors rules */
094    private List<Integer> superRules;
095
096
097    /**
098     * Creates a new instance of DitStructureRule
099     */
100    public DitStructureRule( int ruleId )
101    {
102        super( SchemaObjectType.DIT_STRUCTURE_RULE, null );
103        this.ruleId = ruleId;
104        form = null;
105        superRules = new ArrayList<Integer>();
106    }
107
108
109    /**
110     *  @return The associated NameForm's OID
111     */
112    public String getForm()
113    {
114        return form;
115    }
116
117
118    /**
119     * Sets the associated NameForm's OID
120     *
121     * @param form The NameForm's OID
122     */
123    public void setForm( String form )
124    {
125        if ( locked )
126        {
127            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
128        }
129
130        if ( !isReadOnly )
131        {
132            this.form = form;
133        }
134    }
135
136
137    /**
138     * @return The Rule ID
139     */
140    public int getRuleId()
141    {
142        return ruleId;
143    }
144
145
146    /**
147     * Sets the rule identifier of this DIT structure rule;
148     *
149     * @param ruleId the rule identifier of this DIT structure rule;
150     */
151    public void setRuleId( int ruleId )
152    {
153        if ( locked )
154        {
155            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
156        }
157
158        if ( !isReadOnly )
159        {
160            this.ruleId = ruleId;
161        }
162    }
163
164
165    /**
166     * @return The list of superiors RuleIDs
167     */
168    public List<Integer> getSuperRules()
169    {
170        return superRules;
171    }
172
173
174    /**
175     * Sets the list of superior RuleIds
176     * 
177     * @param superRules the list of superior RuleIds
178     */
179    public void setSuperRules( List<Integer> superRules )
180    {
181        if ( locked )
182        {
183            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
184        }
185
186        if ( !isReadOnly )
187        {
188            this.superRules = superRules;
189        }
190    }
191
192
193    /**
194     * Adds a new superior RuleId
195     *
196     * @param superRule The superior RuleID to add
197     */
198    public void addSuperRule( Integer superRule )
199    {
200        if ( locked )
201        {
202            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
203        }
204
205        superRules.add( superRule );
206    }
207
208
209    /**
210     * The DIT structure rule does not have an OID
211     * 
212     * {@inheritDoc}
213     */
214    @Override
215    public String getOid()
216    {
217        // We cannot throw exception here. E.g. SchemaObjectWrapper will try to use this in hashcode.
218        return null;
219    }
220
221
222    /**
223     * {@inheritDoc}
224     */
225    @Override
226    public String toString()
227    {
228        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
229    }
230
231
232    /**
233     * {@inheritDoc}
234     */
235    public DitStructureRule copy()
236    {
237        DitStructureRule copy = new DitStructureRule( ruleId );
238
239        // Copy the SchemaObject common data
240        copy.copy( this );
241
242        // Copy the Superiors rules
243        copy.superRules = new ArrayList<Integer>();
244
245        // Copy the form
246        copy.form = form;
247
248        for ( int superRule : superRules )
249        {
250            copy.superRules.add( superRule );
251        }
252
253        return copy;
254    }
255
256
257    /**
258     * {@inheritDoc}
259     */
260    @Override
261    public boolean equals( Object o )
262    {
263        if ( !super.equals( o ) )
264        {
265            return false;
266        }
267
268        if ( !( o instanceof DitStructureRule ) )
269        {
270            return false;
271        }
272
273        @SuppressWarnings("unused")
274        DitStructureRule that = ( DitStructureRule ) o;
275
276        // TODO : complete the test
277        return true;
278    }
279
280
281    /**
282     * {@inheritDoc}
283     */
284    public void clear()
285    {
286        // Clear the common elements
287        super.clear();
288
289        // Clear the references
290        superRules.clear();
291    }
292}