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 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
080 */
081public class DitStructureRule extends AbstractSchemaObject
082{
083    /** The mandatory serialVersionUID */
084    public static final long serialVersionUID = 1L;
085
086    /** The rule ID. A DSR does not have an OID */
087    private int ruleId;
088
089    /** The associated NameForm */
090    private String form;
091
092    /** The list of superiors rules */
093    private List<Integer> superRules;
094
095
096    /**
097     * Creates a new instance of DitStructureRule
098     * 
099     * @param ruleId The RuleId for this 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<>();
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
212     * 
213     * {@inheritDoc}
214     */
215    @Override
216    public String getOid()
217    {
218        // We cannot throw exception here. E.g. SchemaObjectWrapper will try to use this in hashcode.
219        return null;
220    }
221
222
223    /**
224     * {@inheritDoc}
225     */
226    @Override
227    public String toString()
228    {
229        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
230    }
231
232
233    /**
234     * {@inheritDoc}
235     */
236    @Override
237    public DitStructureRule copy()
238    {
239        DitStructureRule copy = new DitStructureRule( ruleId );
240
241        // Copy the SchemaObject common data
242        copy.copy( this );
243
244        // Copy the Superiors rules
245        copy.superRules = new ArrayList<>();
246
247        // Copy the form
248        copy.form = form;
249
250        for ( int superRule : superRules )
251        {
252            copy.superRules.add( superRule );
253        }
254
255        return copy;
256    }
257
258
259    /**
260     * {@inheritDoc}
261     */
262    @Override
263    public boolean equals( Object o )
264    {
265        if ( !super.equals( o ) )
266        {
267            return false;
268        }
269
270        if ( !( o instanceof DitStructureRule ) )
271        {
272            return false;
273        }
274
275        @SuppressWarnings("unused")
276        DitStructureRule that = ( DitStructureRule ) o;
277
278        // TODO : complete the test
279        return true;
280    }
281
282
283    /**
284     * {@inheritDoc}
285     */
286    @Override
287    public void clear()
288    {
289        // Clear the common elements
290        super.clear();
291
292        // Clear the references
293        superRules.clear();
294    }
295}