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;
027import org.apache.directory.api.util.exception.NotImplementedException;
028
029
030/**
031 * A dITStructureRule definition. A dITStructureRules is a rule governing the
032 * structure of the DIT by specifying a permitted superior to subordinate entry
033 * relationship. A structure rule relates a nameForm, and therefore a STRUCTURAL
034 * objectClass, to superior dITStructureRules. This permits entries of the
035 * STRUCTURAL objectClass identified by the nameForm to exist in the DIT as
036 * subordinates to entries governed by the indicated superior dITStructureRules.
037 * Hence dITStructureRules only apply to structural object classes.
038 * <p>
039 * According to ldapbis [MODELS]:
040 * </p>
041 * 
042 * <pre>
043 *  DIT structure rule descriptions are written according to the ABNF:
044 *  
045 *    DITStructureRuleDescription = LPAREN WSP
046 *        ruleid                    ; rule identifier
047 *        [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
048 *        [ SP &quot;DESC&quot; SP qdstring ] ; description
049 *        [ SP &quot;OBSOLETE&quot; ]         ; not active
050 *        SP &quot;FORM&quot; SP oid          ; NameForm
051 *        [ SP &quot;SUP&quot; ruleids ]      ; superior rules
052 *        extensions WSP RPAREN     ; extensions
053 * 
054 *    ruleids = ruleid / ( LPAREN WSP ruleidlist WSP RPAREN )
055 * 
056 *    ruleidlist = ruleid *( SP ruleid )
057 * 
058 *    ruleid = number
059 * 
060 *  where:
061 *    [ruleid] is the rule identifier of this DIT structure rule;
062 *    NAME [qdescrs] are short names (descriptors) identifying this DIT
063 *        structure rule;
064 *    DESC [qdstring] is a short descriptive string;
065 *    OBSOLETE indicates this DIT structure rule use is not active;
066 *    FORM is specifies the name form associated with this DIT structure
067 *        rule;
068 *    SUP identifies superior rules (by rule id); and
069 *    [extensions] describe extensions.
070 *  
071 *  If no superior rules are identified, the DIT structure rule applies
072 *  to an autonomous administrative point (e.g. the root vertex of the
073 *  subtree controlled by the subschema) [X.501].
074 * </pre>
075 * 
076 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC2252 Section 6.33</a>
077 * @see <a
078 *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
079 *      [MODELS]</a>
080 * @see DescriptionUtils#getDescription(DitStructureRule)
081 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
082 */
083public class DitStructureRule extends AbstractSchemaObject
084{
085    /** The mandatory serialVersionUID */
086    public static final long serialVersionUID = 1L;
087
088    /** The rule ID. A DSR does not have an OID */
089    private int ruleId;
090
091    /** The associated NameForm */
092    private String form;
093
094    /** The list of superiors rules */
095    private List<Integer> superRules;
096
097
098    /**
099     * Creates a new instance of DitStructureRule
100     */
101    public DitStructureRule( int ruleId )
102    {
103        super( SchemaObjectType.DIT_STRUCTURE_RULE, null );
104        this.ruleId = ruleId;
105        form = null;
106        superRules = new ArrayList<Integer>();
107    }
108
109
110    /**
111     *  @return The associated NameForm's OID
112     */
113    public String getForm()
114    {
115        return form;
116    }
117
118
119    /**
120     * Sets the associated NameForm's OID
121     *
122     * @param form The NameForm's OID
123     */
124    public void setForm( String form )
125    {
126        if ( locked )
127        {
128            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
129        }
130
131        if ( !isReadOnly )
132        {
133            this.form = form;
134        }
135    }
136
137
138    /**
139     * @return The Rule ID
140     */
141    public int getRuleId()
142    {
143        return ruleId;
144    }
145
146
147    /**
148     * Sets the rule identifier of this DIT structure rule;
149     *
150     * @param ruleId the rule identifier of this DIT structure rule;
151     */
152    public void setRuleId( int ruleId )
153    {
154        if ( locked )
155        {
156            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
157        }
158
159        if ( !isReadOnly )
160        {
161            this.ruleId = ruleId;
162        }
163    }
164
165
166    /**
167     * @return The list of superiors RuleIDs
168     */
169    public List<Integer> getSuperRules()
170    {
171        return superRules;
172    }
173
174
175    /**
176     * Sets the list of superior RuleIds
177     * 
178     * @param superRules the list of superior RuleIds
179     */
180    public void setSuperRules( List<Integer> superRules )
181    {
182        if ( locked )
183        {
184            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
185        }
186
187        if ( !isReadOnly )
188        {
189            this.superRules = superRules;
190        }
191    }
192
193
194    /**
195     * Adds a new superior RuleId
196     *
197     * @param superRule The superior RuleID to add
198     */
199    public void addSuperRule( Integer superRule )
200    {
201        if ( locked )
202        {
203            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
204        }
205
206        superRules.add( superRule );
207    }
208
209
210    /**
211     * The DIT structure rule does not have an OID, so this implementations always throws an exception.
212     * 
213     * {@inheritDoc}
214     */
215    @Override
216    public String getOid()
217    {
218        throw new NotImplementedException();
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}