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.server.utils; 
021    
022    
023    import java.util.Comparator; 
024    
025    import javax.naming.NamingException;
026    
027    import org.apache.directory.server.constants.MetaSchemaConstants;
028    import org.apache.directory.server.core.entry.DefaultServerAttribute;
029    import org.apache.directory.server.core.entry.DefaultServerEntry;
030    import org.apache.directory.server.core.entry.ServerEntry;
031    import org.apache.directory.server.schema.bootstrap.Schema;
032    import org.apache.directory.server.schema.registries.Registries;
033    import org.apache.directory.shared.ldap.constants.SchemaConstants;
034    import org.apache.directory.shared.ldap.entry.EntryAttribute;
035    import org.apache.directory.shared.ldap.schema.AttributeType;
036    import org.apache.directory.shared.ldap.schema.DITContentRule;
037    import org.apache.directory.shared.ldap.schema.DITStructureRule;
038    import org.apache.directory.shared.ldap.schema.MatchingRule;
039    import org.apache.directory.shared.ldap.schema.MatchingRuleUse;
040    import org.apache.directory.shared.ldap.schema.NameForm;
041    import org.apache.directory.shared.ldap.schema.Normalizer;
042    import org.apache.directory.shared.ldap.schema.ObjectClass;
043    import org.apache.directory.shared.ldap.schema.SchemaObject;
044    import org.apache.directory.shared.ldap.schema.Syntax;
045    import org.apache.directory.shared.ldap.schema.SyntaxChecker;
046    import org.apache.directory.shared.ldap.util.DateUtils;
047    
048    
049    /**
050     * A factory that generates an entry using the meta schema for schema 
051     * elements.
052     *
053     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
054     * @version $Rev$
055     */
056    public class AttributesFactory
057    {
058        public ServerEntry getAttributes( SchemaObject obj, Schema schema, Registries registries ) throws NamingException
059        {
060            if ( obj instanceof Syntax )
061            {
062                return getAttributes( ( Syntax ) obj, schema, registries );
063            }
064            else if ( obj instanceof MatchingRule )
065            {
066                return getAttributes( ( MatchingRule ) obj, schema, registries );
067            }
068            else if ( obj instanceof AttributeType )
069            {
070                return getAttributes( ( AttributeType ) obj, schema, registries );
071            }
072            else if ( obj instanceof ObjectClass )
073            {
074                return getAttributes( ( ObjectClass ) obj, schema, registries );
075            }
076            else if ( obj instanceof MatchingRuleUse )
077            {
078                return getAttributes( ( MatchingRuleUse ) obj, schema, registries );
079            }
080            else if ( obj instanceof DITStructureRule )
081            {
082                return getAttributes( ( DITStructureRule ) obj, schema, registries );
083            }
084            else if ( obj instanceof DITContentRule )
085            {
086                return getAttributes( ( DITContentRule ) obj, schema, registries );
087            }
088            else if ( obj instanceof NameForm )
089            {
090                return getAttributes( ( NameForm ) obj, schema, registries );
091            }
092            
093            throw new IllegalArgumentException( "Unknown SchemaObject type: " + obj.getClass() );
094        }
095        
096        
097        public ServerEntry getAttributes( Schema schema, Registries registries ) throws NamingException
098        {
099            ServerEntry entry = new DefaultServerEntry( registries );
100    
101            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_SCHEMA_OC );
102            entry.put( SchemaConstants.CN_AT, schema.getSchemaName() );
103            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
104            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
105            
106            if ( schema.isDisabled() )
107            {
108                entry.put( MetaSchemaConstants.M_DISABLED_AT, "TRUE" );
109            }
110            
111            String[] dependencies = schema.getDependencies();
112            
113            if ( dependencies != null && dependencies.length > 0 )
114            {
115                EntryAttribute attr = new DefaultServerAttribute( registries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_DEPENDENCIES_AT ) );
116                
117                for ( String dependency:dependencies )
118                {
119                    attr.add( dependency );
120                }
121                
122                entry.put( attr );
123            }
124            
125            return entry;
126        }
127        
128        
129        public ServerEntry getAttributes( SyntaxChecker syntaxChecker, Schema schema, Registries registries )
130        {
131            ServerEntry entry = new DefaultServerEntry( registries );
132    
133            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_SYNTAX_CHECKER_OC );
134            entry.put( MetaSchemaConstants.M_OID_AT, syntaxChecker.getSyntaxOid() );
135            entry.put( MetaSchemaConstants.M_FQCN_AT, syntaxChecker.getClass().getName() );
136            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
137            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
138            
139            return entry;
140        }
141    
142        
143        public ServerEntry getAttributes( Syntax syntax, Schema schema, Registries registries ) throws NamingException
144        {
145            ServerEntry entry = new DefaultServerEntry( registries );
146    
147            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_SYNTAX_OC );
148            entry.put( MetaSchemaConstants.X_HUMAN_READABLE_AT, getBoolean( syntax.isHumanReadable() ) );
149            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
150            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
151            injectCommon( syntax, entry, registries );
152            
153            return entry;
154        }
155    
156        
157        public ServerEntry getAttributes( String oid, Normalizer normalizer, Schema schema, Registries registries )
158        {
159            ServerEntry entry = new DefaultServerEntry( registries );
160    
161            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_NORMALIZER_OC );
162            entry.put( MetaSchemaConstants.M_OID_AT, oid );
163            entry.put( MetaSchemaConstants.M_FQCN_AT, normalizer.getClass().getName() );
164            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
165            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
166            return entry;
167        }
168    
169        
170        public ServerEntry getAttributes( String oid, Comparator comparator, Schema schema, Registries registries )
171        {
172            ServerEntry entry = new DefaultServerEntry( registries );
173    
174            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_COMPARATOR_OC );
175            entry.put( MetaSchemaConstants.M_OID_AT, oid );
176            entry.put( MetaSchemaConstants.M_FQCN_AT, comparator.getClass().getName() );
177            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
178            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
179            return entry;
180        }
181    
182    
183        /**
184         * 
185         * @param matchingRule
186         * @return Attributes
187         * @throws NamingException
188         */
189        public ServerEntry getAttributes( MatchingRule matchingRule, Schema schema, Registries registries ) throws NamingException
190        {
191            ServerEntry entry = new DefaultServerEntry( registries );
192    
193            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_MATCHING_RULE_OC );
194            entry.put( MetaSchemaConstants.M_SYNTAX_AT, matchingRule.getSyntax().getOid() );
195            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
196            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
197            injectCommon( matchingRule, entry, registries );
198            return entry;
199        }
200    
201        
202        public ServerEntry getAttributes( MatchingRuleUse matchingRuleUse, Schema schema, Registries registries )
203        {
204            ServerEntry entry = new DefaultServerEntry( registries );
205    
206            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, "" );
207            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
208            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
209            return entry;
210        }
211    
212        
213        public ServerEntry getAttributes( DITStructureRule dITStructureRule, Schema schema, Registries registries )
214        {
215            ServerEntry entry = new DefaultServerEntry( registries );
216    
217            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, "" );
218            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
219            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
220            return entry;
221        }
222    
223        
224        public ServerEntry getAttributes( DITContentRule dITContentRule, Schema schema, Registries registries )
225        {
226            ServerEntry entry = new DefaultServerEntry( registries );
227    
228            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, "" );
229            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
230            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
231            return entry;
232        }
233    
234        
235        public ServerEntry getAttributes( NameForm nameForm, Schema schema, Registries registries )
236        {
237            ServerEntry entry = new DefaultServerEntry( registries );
238    
239            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, "" );
240            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
241            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
242            return entry;
243        }
244    
245    
246        /**
247         * <pre>
248         *    objectclass ( 1.3.6.1.4.1.18060.0.4.0.3.3
249         *       NAME 'metaAttributeType'
250         *       DESC 'meta definition of the AttributeType object'
251         *       SUP metaTop
252         *       STRUCTURAL
253         *       MUST ( m-name $ m-syntax )
254         *       MAY ( m-supAttributeType $ m-obsolete $ m-equality $ m-ordering $ 
255         *             m-substr $ m-singleValue $ m-collective $ m-noUserModification $ 
256         *             m-usage $ m-extensionAttributeType )
257         *    )
258         * </pre>
259         * 
260         * @param attributeType
261         * @return Attributes
262         * @throws NamingException
263         */
264        public ServerEntry getAttributes( AttributeType attributeType, Schema schema, Registries registries ) throws NamingException
265        {
266            ServerEntry entry = new DefaultServerEntry( registries );
267    
268            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_ATTRIBUTE_TYPE_OC );
269            entry.put( MetaSchemaConstants.M_SYNTAX_AT, attributeType.getSyntax().getOid() );
270            entry.put( MetaSchemaConstants.M_COLLECTIVE_AT, getBoolean( attributeType.isCollective() ) );
271            entry.put( MetaSchemaConstants.M_NO_USER_MODIFICATION_AT, getBoolean( ! attributeType.isCanUserModify() ) );
272            entry.put( MetaSchemaConstants.M_SINGLE_VALUE_AT, getBoolean( attributeType.isSingleValue() ) );
273            entry.put( MetaSchemaConstants.M_USAGE_AT, attributeType.getUsage().toString() );
274            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
275            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
276    
277            injectCommon( attributeType, entry, registries );
278            
279            AttributeType superior = attributeType.getSuperior();
280            
281            if ( superior != null )
282            {
283                // use name if we can for clarity
284                String sup = superior.getName();
285                
286                if ( sup == null )
287                {
288                    sup = superior.getOid();
289                }
290                
291                entry.put( MetaSchemaConstants.M_SUP_ATTRIBUTE_TYPE_AT, sup );
292            }
293            
294            if ( attributeType.getEquality() != null )
295            {
296                String equality = attributeType.getEquality().getName();
297                
298                if ( equality == null )
299                {
300                    equality = attributeType.getEquality().getOid();
301                }
302                
303                entry.put( MetaSchemaConstants.M_EQUALITY_AT, equality );
304            }
305    
306            if ( attributeType.getSubstr() != null )
307            {
308                String substr = attributeType.getSubstr().getName();
309                
310                if ( substr == null )
311                {
312                    substr = attributeType.getSubstr().getOid();
313                }
314                
315                entry.put( MetaSchemaConstants.M_SUBSTR_AT, substr );
316            }
317    
318            if ( attributeType.getOrdering() != null )
319            {
320                String ordering = attributeType.getOrdering().getName();
321                
322                if ( ordering == null )
323                {
324                    ordering = attributeType.getOrdering().getOid();
325                }
326                
327                entry.put( MetaSchemaConstants.M_ORDERING_AT, ordering );
328            }
329    
330            return entry;
331        }
332    
333        
334        /**
335         * Creates the attributes of an entry representing an objectClass.
336         * 
337         * <pre>
338         *  objectclass ( 1.3.6.1.4.1.18060.0.4.0.3.2
339         *      NAME 'metaObjectClass'
340         *      DESC 'meta definition of the objectclass object'
341         *      SUP metaTop
342         *      STRUCTURAL
343         *      MUST m-oid
344         *      MAY ( m-name $ m-obsolete $ m-supObjectClass $ m-typeObjectClass $ m-must $ 
345         *            m-may $ m-extensionObjectClass )
346         *  )
347         * </pre>
348         * 
349         * @param objectClass the objectClass to produce a meta schema entry for
350         * @return the attributes of the metaSchema entry representing the objectClass
351         * @throws NamingException if there are any problems
352         */
353        public ServerEntry getAttributes( ObjectClass objectClass, Schema schema, Registries registries ) throws NamingException
354        {
355            ServerEntry entry = new DefaultServerEntry( registries );
356    
357            entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_OBJECT_CLASS_OC );
358            entry.put( MetaSchemaConstants.M_TYPE_OBJECT_CLASS_AT, objectClass.getType().toString() );
359            entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
360            entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
361            
362            injectCommon( objectClass, entry, registries );
363    
364            // handle the superior objectClasses 
365            if ( objectClass.getSuperClasses() != null && objectClass.getSuperClasses().length != 0 )
366            {
367                EntryAttribute attr = new DefaultServerAttribute( registries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_SUP_OBJECT_CLASS_AT ) );
368                ObjectClass[] superClasses = objectClass.getSuperClasses();
369                
370                for ( ObjectClass superClass:superClasses )
371                {
372                    attr.add( getNameOrNumericoid( superClass ) ); 
373                }
374                
375                entry.put( attr );
376            }
377    
378            // add the must list
379            if ( objectClass.getMustList() != null && objectClass.getMustList().length != 0 )
380            {
381                EntryAttribute attr = new DefaultServerAttribute( registries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_MUST_AT ) );
382                AttributeType[] mustList = objectClass.getMustList();
383    
384                for ( AttributeType attributeType:mustList )
385                {
386                    attr.add( getNameOrNumericoid( attributeType ) );
387                }
388                
389                entry.put( attr );
390            }
391            
392            // add the may list
393            if ( objectClass.getMayList() != null && objectClass.getMayList().length != 0 )
394            {
395                EntryAttribute attr = new DefaultServerAttribute( registries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_MAY_AT ) );
396                AttributeType[] mayList = objectClass.getMayList();
397    
398                for ( AttributeType attributeType:mayList )
399                {
400                    attr.add( getNameOrNumericoid( attributeType ) );
401                }
402                
403                entry.put( attr );
404            }
405            
406            return entry;
407        }
408    
409        
410        private final String getNameOrNumericoid( SchemaObject object )
411        {
412            // first try to use user friendly name if we can
413            if ( object.getName() != null )
414            {
415                return object.getName();
416            }
417            
418            return object.getOid();
419        }
420        
421        
422        private final void injectCommon( SchemaObject object, ServerEntry entry, Registries registries ) throws NamingException
423        {
424            injectNames( object.getNamesRef(), entry, registries );
425            entry.put( MetaSchemaConstants.M_OBSOLETE_AT, getBoolean( object.isObsolete() ) );
426            entry.put( MetaSchemaConstants.M_OID_AT, object.getOid() );
427            
428            if ( object.getDescription() != null )
429            {
430                entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, object.getDescription() );
431            }
432        }
433        
434        
435        private final void injectNames( String[] names, ServerEntry entry, Registries registries ) throws NamingException
436        {
437            if ( names == null || names.length == 0 )
438            {
439                return;
440            }
441            
442            EntryAttribute attr = new DefaultServerAttribute( registries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_NAME_AT ) );
443    
444            for ( String name:names )
445            {
446                attr.add( name );
447            }
448            
449            entry.put( attr );
450        }
451    
452        
453        private final String getBoolean( boolean value )
454        {
455            if ( value ) 
456            {
457                return "TRUE";
458            }
459            else
460            {
461                return "FALSE";
462            }
463        }
464    }