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.io.Serializable;
024    import javax.naming.NamingException;
025    
026    
027    /**
028     * Attribute specification bean used to store the schema information for an
029     * attributeType definition.
030     * 
031     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
032     * @version $Rev: 702493 $
033     */
034    public abstract class AbstractAttributeType extends AbstractSchemaObject implements Serializable, AttributeType
035    {
036        // ------------------------------------------------------------------------
037        // Specification Attributes
038        // ------------------------------------------------------------------------
039    
040        /** whether or not this type is single valued */
041        private boolean isSingleValue = false;
042    
043        /** whether or not this type is a collective attribute */
044        private boolean isCollective = false;
045    
046        /** whether or not this type can be modified by directory users */
047        private boolean canUserModify = true;
048    
049        /** the usage for this attributeType */
050        private UsageEnum usage = UsageEnum.USER_APPLICATIONS;
051    
052        /** the length of this attribute in bytes */
053        private int length = -1;
054    
055    
056        // ------------------------------------------------------------------------
057        // C O N S T R U C T O R S
058        // ------------------------------------------------------------------------
059    
060        /**
061         * Creates an AttributeType using a unique OID.
062         * 
063         * @param oid
064         *            the IANA OID number for the attributeType
065         */
066        protected AbstractAttributeType( String oid )
067        {
068            super( oid );
069        }
070    
071    
072        // ------------------------------------------------------------------------
073        // Accessor Methods for Specification Properties
074        // ------------------------------------------------------------------------
075    
076        /**
077         * @see AttributeType#isSingleValue()
078         * @return true if only one value can exist for this AttributeType, false
079         *         otherwise
080         */
081        public boolean isSingleValue()
082        {
083            return isSingleValue;
084        }
085    
086    
087        /**
088         * @see AttributeType#isCollective()
089         * @return true if the attribute is collective, false otherwise
090         */
091        public boolean isCollective()
092        {
093            return isCollective;
094        }
095    
096    
097        /**
098         * @see AttributeType#isCanUserModify()
099         * @return true if users can modify it, false if only the directory can.
100         */
101        public boolean isCanUserModify()
102        {
103            return canUserModify;
104        }
105    
106    
107        /**
108         * @see AttributeType#getUsage()
109         * @return a type safe UsageEnum
110         */
111        public UsageEnum getUsage()
112        {
113            return usage;
114        }
115    
116    
117        /**
118         * @see AttributeType#getLength()
119         * @return the length of the attribute
120         */
121        public int getLength()
122        {
123            return length;
124        }
125    
126    
127        // ------------------------------------------------------------------------
128        // M U T A T O R S
129        // ------------------------------------------------------------------------
130    
131    
132        /**
133         * Sets whether or not an attribute of this AttributeType single valued or
134         * multi-valued.
135         * 
136         * @param singleValue
137         *            true if its is single valued, false if multi-valued
138         */
139        protected void setSingleValue( boolean singleValue )
140        {
141            isSingleValue = singleValue;
142        }
143    
144    
145        /**
146         * Sets whether or not an attribute of this AttributeType is a collective.
147         * 
148         * @param collective
149         *            true if it is collective, false otherwise
150         */
151        protected void setCollective( boolean collective )
152        {
153            isCollective = collective;
154        }
155    
156    
157        /**
158         * Sets whether or not an attribute of this AttributeType can be modified by
159         * directory users.
160         * 
161         * @param canUserModify
162         *            true if directory users can modify, false otherwise
163         */
164        protected void setCanUserModify( boolean canUserModify )
165        {
166            this.canUserModify = canUserModify;
167        }
168    
169    
170        /**
171         * The usage class for this attributeType.
172         * 
173         * @param usage
174         *            the way attributes of this AttributeType are used in the DSA
175         */
176        protected void setUsage( UsageEnum usage )
177        {
178            this.usage = usage;
179        }
180    
181    
182        /**
183         * Sets the length limit of this AttributeType based on its associated
184         * syntax.
185         * 
186         * @param length
187         *            the new length to set
188         */
189        protected void setLength( int length )
190        {
191            this.length = length;
192        }
193    
194    
195        // -----------------------------------------------------------------------
196        // Additional Methods
197        // -----------------------------------------------------------------------
198        /**
199         * Checks to see if this AttributeType is the ancestor of another
200         * attributeType.
201         *
202         * @param descendant the perspective descendant to check
203         * @return true if the descendant is truly a derived from this AttributeType
204         * @throws NamingException if there are problems resolving superior types
205         */
206        public boolean isAncestorOf( AttributeType descendant ) throws NamingException
207        {
208            if ( ( descendant == null ) || equals( descendant ) )
209            {
210                return false;
211            }
212    
213            return isAncestorOrEqual( this, descendant );
214        }
215    
216    
217        /**
218         * Checks to see if this AttributeType is the descendant of another
219         * attributeType.
220         *
221         * @param ancestor the perspective ancestor to check
222         * @return true if this AttributeType truly descends from the ancestor
223         * @throws NamingException if there are problems resolving superior types
224         */
225        public boolean isDescendantOf( AttributeType ancestor ) throws NamingException
226        {
227            if ( ( ancestor == null ) || equals( ancestor ) )
228            {
229                return false;
230            }
231    
232            return isAncestorOrEqual( ancestor, this );
233        }
234    
235    
236        /**
237         * Recursive method which checks to see if a descendant is really an ancestor or if the two
238         * are equal.
239         *
240         * @param ancestor the possible ancestor of the descendant
241         * @param descendant the possible descendant of the ancestor
242         * @return true if the ancestor equals the descendant or if the descendant is really
243         * a subtype of the ancestor. otherwise false
244         * @throws NamingException if there are issues with superior attribute resolution
245         */
246        private boolean isAncestorOrEqual( AttributeType ancestor, AttributeType descendant ) throws NamingException
247        {
248            if ( ( ancestor == null ) || ( descendant == null ) )
249            {
250                return false;
251            }
252    
253            if ( ancestor.equals( descendant ) )
254            {
255                return true;
256            }
257    
258            return isAncestorOrEqual( ancestor, descendant.getSuperior() );
259        }
260    }