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 *    https://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.List;
024import java.util.Map;
025
026import org.apache.directory.api.i18n.I18n;
027import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
028import org.apache.directory.api.ldap.model.constants.SchemaConstants;
029import org.apache.directory.api.ldap.model.entry.Attribute;
030import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
031import org.apache.directory.api.ldap.model.entry.DefaultEntry;
032import org.apache.directory.api.ldap.model.entry.Entry;
033import org.apache.directory.api.ldap.model.exception.LdapException;
034import org.apache.directory.api.ldap.model.schema.registries.Schema;
035import org.apache.directory.api.util.DateUtils;
036import org.apache.directory.api.util.TimeProvider;
037
038
039/**
040 * A factory that generates an entry using the meta schema for schema
041 * elements.
042 *
043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
044 */
045public class AttributesFactory
046{
047    private TimeProvider timeProvider = TimeProvider.DEFAULT;
048    
049    /**
050     * Get a SchemaObject as an Entry
051     *
052     * @param obj The schema oobject to convert
053     * @param schema The schema which this object belongs to
054     * @param schemaManager The SchemaManager
055     * @return The converted schema object as an Entry
056     * @throws LdapException If we can't convert teh schema object
057     */
058    public Entry getAttributes( SchemaObject obj, Schema schema, SchemaManager schemaManager ) throws LdapException
059    {
060        if ( obj instanceof LdapSyntax )
061        {
062            return convert( ( LdapSyntax ) obj, schema, schemaManager );
063        }
064        else if ( obj instanceof MatchingRule )
065        {
066            return convert( ( MatchingRule ) obj, schema, schemaManager );
067        }
068        else if ( obj instanceof AttributeType )
069        {
070            return convert( ( AttributeType ) obj, schema, schemaManager );
071        }
072        else if ( obj instanceof ObjectClass )
073        {
074            return convert( ( ObjectClass ) obj, schema, schemaManager );
075        }
076        else if ( obj instanceof MatchingRuleUse )
077        {
078            return convert( ( MatchingRuleUse ) obj, schema, schemaManager );
079        }
080        else if ( obj instanceof DitStructureRule )
081        {
082            return convert( ( DitStructureRule ) obj, schema, schemaManager );
083        }
084        else if ( obj instanceof DitContentRule )
085        {
086            return convert( ( DitContentRule ) obj, schema, schemaManager );
087        }
088        else if ( obj instanceof NameForm )
089        {
090            return convert( ( NameForm ) obj, schema, schemaManager );
091        }
092
093        throw new IllegalArgumentException( I18n.err( I18n.ERR_13712_UNKNOWN_SCHEMA_OBJECT_TYPE, obj.getClass() ) );
094    }
095
096
097    /**
098     * Converts a Schema to an Entry
099     * 
100     * @param schema The Schema to convert
101     * @param schemaManager The SchemaManager
102     * @return An Entry containing the converted Schema
103     * @throws LdapException If the conversion failed
104     */
105    public Entry convert( Schema schema, SchemaManager schemaManager ) throws LdapException
106    {
107        Entry entry = new DefaultEntry( schemaManager );
108
109        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_SCHEMA_OC );
110        entry.put( SchemaConstants.CN_AT, schema.getSchemaName() );
111        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
112        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
113
114        if ( schema.isDisabled() )
115        {
116            entry.put( MetaSchemaConstants.M_DISABLED_AT, "TRUE" );
117        }
118
119        String[] dependencies = schema.getDependencies();
120
121        if ( dependencies != null && dependencies.length > 0 )
122        {
123            Attribute attr = new DefaultAttribute(
124                schemaManager.getAttributeType( MetaSchemaConstants.M_DEPENDENCIES_AT ) );
125
126            for ( String dependency : dependencies )
127            {
128                attr.add( dependency );
129            }
130
131            entry.put( attr );
132        }
133
134        return entry;
135    }
136
137
138    /**
139     * Convert a SyntaxChecker instance into an Entry
140     *
141     * @param syntaxChecker The SyntaxChecker to convert
142     * @param schema The schema containing this SyntaxChecker
143     * @param schemaManager The SchemaManager
144     * @return An Entry containing the converted SyntaxChecker
145     */
146    public Entry convert( SyntaxChecker syntaxChecker, Schema schema, SchemaManager schemaManager )
147    {
148        Entry entry = new DefaultEntry( schemaManager );
149
150        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_SYNTAX_CHECKER_OC );
151        entry.put( MetaSchemaConstants.M_OID_AT, syntaxChecker.getOid() );
152        entry.put( MetaSchemaConstants.M_FQCN_AT, syntaxChecker.getClass().getName() );
153        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
154        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
155
156        return entry;
157    }
158
159
160    /**
161     * Convert a Syntax instance into an Entry
162     *
163     * @param syntax The LdapSytax to convert
164     * @param schema The schema containing this Syntax
165     * @param schemaManager The SchemaManager
166     * @return And entry defining a LdapSyntax
167     * @throws LdapException If the conversion failed
168     */
169    public Entry convert( LdapSyntax syntax, Schema schema, SchemaManager schemaManager ) throws LdapException
170    {
171        Entry entry = new DefaultEntry( schemaManager );
172
173        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_SYNTAX_OC );
174        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
175        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
176        injectCommon( syntax, entry, schemaManager );
177
178        return entry;
179    }
180
181
182    /**
183     * Convert a Normalizer instance into an Entry
184     *
185     * @param oid The Normalizer's OID
186     * @param normalizer The Normalizer to convert
187     * @param schema The schema containing this Normalizer
188     * @param schemaManager The SchemaManager
189     * @return An Entry defining a Normalizer
190     */
191    public Entry convert( String oid, Normalizer normalizer, Schema schema, SchemaManager schemaManager )
192    {
193        Entry entry = new DefaultEntry( schemaManager );
194
195        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_NORMALIZER_OC );
196        entry.put( MetaSchemaConstants.M_OID_AT, oid );
197        entry.put( MetaSchemaConstants.M_FQCN_AT, normalizer.getClass().getName() );
198        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
199        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
200        
201        return entry;
202    }
203
204
205    /**
206     * Convert a LdapComparator instance into an Entry
207     *
208     * @param oid The LdapComparator's OID
209     * @param comparator The LdapComparator to convert
210     * @param schema The schema containing this Comparator
211     * @param schemaManager The SchemaManager
212     * @return An Entry defining a LdapComparator
213     */
214    public Entry convert( String oid, LdapComparator<? super Object> comparator, Schema schema, SchemaManager schemaManager )
215    {
216        Entry entry = new DefaultEntry( schemaManager );
217
218        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_COMPARATOR_OC );
219        entry.put( MetaSchemaConstants.M_OID_AT, oid );
220        entry.put( MetaSchemaConstants.M_FQCN_AT, comparator.getClass().getName() );
221        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
222        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
223        
224        return entry;
225    }
226
227
228    /**
229     * Converts a MatchingRule into an Entry
230     * 
231     * @param matchingRule The MatchingRule to convert
232     * @param schema The schema containing this ObjectClass
233     * @param schemaManager The SchemaManager
234     * @return The converted MatchingRule
235     * @throws LdapException If the conversion failed
236     */
237    public Entry convert( MatchingRule matchingRule, Schema schema, SchemaManager schemaManager )
238        throws LdapException
239    {
240        Entry entry = new DefaultEntry( schemaManager );
241
242        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_MATCHING_RULE_OC );
243        entry.put( MetaSchemaConstants.M_SYNTAX_AT, matchingRule.getSyntaxOid() );
244        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
245        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
246        injectCommon( matchingRule, entry, schemaManager );
247        
248        return entry;
249    }
250
251
252    /**
253     * Converts a MatchingRuleUse into an Entry
254     *
255     * @param matchingRuleUse The MatchingRuleUse to convert
256     * @param schema The schema containing this MatchingRuleUse
257     * @param schemaManager The SchemaManager
258     * @return The converted MatchingRuleUse
259     */
260    public Entry convert( MatchingRuleUse matchingRuleUse, Schema schema, SchemaManager schemaManager )
261    {
262        Entry entry = new DefaultEntry( schemaManager );
263
264        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, "" );
265        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
266        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
267        
268        return entry;
269    }
270
271
272    /**
273     * Converts a DitStructureRule into an Entry
274     *
275     * @param ditStructureRule The DitStructureRule to convert
276     * @param schema The schema containing this DitStructureRule
277     * @param schemaManager The SchemaManager
278     * @return The converted DitStructureRule
279     */
280    public Entry convert( DitStructureRule ditStructureRule, Schema schema, SchemaManager schemaManager )
281    {
282        Entry entry = new DefaultEntry( schemaManager );
283
284        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, "" );
285        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
286        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
287        
288        return entry;
289    }
290
291
292    /**
293     * Converts a DitContentRule into an Entry
294     *
295     * @param dITContentRule The DitContentRule to convert
296     * @param schema The schema containing this DitContentRule
297     * @param schemaManager The SchemaManager
298     * @return The converted DitContentRule
299     */
300    public Entry convert( DitContentRule dITContentRule, Schema schema, SchemaManager schemaManager )
301    {
302        Entry entry = new DefaultEntry( schemaManager );
303
304        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, "" );
305        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
306        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
307        
308        return entry;
309    }
310
311
312    /**
313     * 
314     * Converts a NameForm into an Entry
315     *
316     * @param nameForm The NameForm to convert
317     * @param schema The schema containing this NameForm
318     * @param schemaManager The SchemaManager
319     * @return The converted NameForm
320     */
321    public Entry convert( NameForm nameForm, Schema schema, SchemaManager schemaManager )
322    {
323        Entry entry = new DefaultEntry( schemaManager );
324
325        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, "" );
326        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
327        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
328        
329        return entry;
330    }
331
332
333    /**
334     * <pre>
335     *    objectclass ( 1.3.6.1.4.1.18060.0.4.0.3.3
336     *       NAME 'metaAttributeType'
337     *       DESC 'meta definition of the AttributeType object'
338     *       SUP metaTop
339     *       STRUCTURAL
340     *       MUST ( m-name $ m-syntax )
341     *       MAY ( m-supAttributeType $ m-obsolete $ m-equality $ m-ordering $
342     *             m-substr $ m-singleValue $ m-collective $ m-noUserModification $
343     *             m-usage $ m-extensionAttributeType )
344     *    )
345     * </pre>
346     * 
347     * @param attributeType The AttributeType to convert
348     * @param schema The schema containing this AttributeType
349     * @param schemaManager The SchemaManager
350     * @return The converted AttributeType 
351     * @throws LdapException If the conversion failed
352     */
353    public Entry convert( AttributeType attributeType, Schema schema, SchemaManager schemaManager ) throws LdapException
354    {
355        Entry entry = new DefaultEntry( schemaManager );
356
357        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_ATTRIBUTE_TYPE_OC );
358        entry.put( MetaSchemaConstants.M_COLLECTIVE_AT, getBoolean( attributeType.isCollective() ) );
359        entry.put( MetaSchemaConstants.M_NO_USER_MODIFICATION_AT, getBoolean( !attributeType.isUserModifiable() ) );
360        entry.put( MetaSchemaConstants.M_SINGLE_VALUE_AT, getBoolean( attributeType.isSingleValued() ) );
361        entry.put( MetaSchemaConstants.M_USAGE_AT, attributeType.getUsage().toString() );
362        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
363        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
364
365        injectCommon( attributeType, entry, schemaManager );
366
367        String superiorOid = attributeType.getSuperiorOid();
368
369        if ( superiorOid != null )
370        {
371            entry.put( MetaSchemaConstants.M_SUP_ATTRIBUTE_TYPE_AT, superiorOid );
372        }
373
374        if ( attributeType.getEqualityOid() != null )
375        {
376            entry.put( MetaSchemaConstants.M_EQUALITY_AT, attributeType.getEqualityOid() );
377        }
378
379        if ( attributeType.getSubstringOid() != null )
380        {
381            entry.put( MetaSchemaConstants.M_SUBSTR_AT, attributeType.getSubstringOid() );
382        }
383
384        if ( attributeType.getOrderingOid() != null )
385        {
386            entry.put( MetaSchemaConstants.M_ORDERING_AT, attributeType.getOrderingOid() );
387        }
388
389        if ( attributeType.getSyntaxOid() != null )
390        {
391            entry.put( MetaSchemaConstants.M_SYNTAX_AT, attributeType.getSyntaxOid() );
392        }
393
394        return entry;
395    }
396
397
398    /**
399     * Creates the attributes of an entry representing an objectClass.
400     * 
401     * <pre>
402     *  objectclass ( 1.3.6.1.4.1.18060.0.4.0.3.2
403     *      NAME 'metaObjectClass'
404     *      DESC 'meta definition of the objectclass object'
405     *      SUP metaTop
406     *      STRUCTURAL
407     *      MUST m-oid
408     *      MAY ( m-name $ m-obsolete $ m-supObjectClass $ m-typeObjectClass $ m-must $
409     *            m-may $ m-extensionObjectClass )
410     *  )
411     * </pre>
412     * 
413     * @param objectClass the objectClass to produce a meta schema entry for
414     * @param schema The schema containing this ObjectClass
415     * @param schemaManager The SchemaManager
416     * @return the attributes of the metaSchema entry representing the objectClass
417     * @throws LdapException If the conversion failed
418     */
419    public Entry convert( ObjectClass objectClass, Schema schema, SchemaManager schemaManager )
420        throws LdapException
421    {
422        Entry entry = new DefaultEntry( schemaManager );
423
424        entry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, MetaSchemaConstants.META_OBJECT_CLASS_OC );
425        entry.put( MetaSchemaConstants.M_TYPE_OBJECT_CLASS_AT, objectClass.getType().toString() );
426        entry.put( SchemaConstants.CREATORS_NAME_AT, schema.getOwner() );
427        entry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime( timeProvider ) );
428
429        injectCommon( objectClass, entry, schemaManager );
430        Attribute attr;
431
432        // handle the superior objectClasses
433        if ( ( objectClass.getSuperiorOids() != null ) && !objectClass.getSuperiorOids().isEmpty() )
434        {
435            if ( schemaManager != null )
436            {
437                attr = new DefaultAttribute(
438                    schemaManager.getAttributeType( MetaSchemaConstants.M_SUP_OBJECT_CLASS_AT ) );
439            }
440            else
441            {
442                attr = new DefaultAttribute( MetaSchemaConstants.M_SUP_OBJECT_CLASS_AT );
443            }
444
445            for ( String superior : objectClass.getSuperiorOids() )
446            {
447                attr.add( superior );
448            }
449
450            entry.put( attr );
451        }
452
453        // add the must list
454        if ( ( objectClass.getMustAttributeTypeOids() != null ) && !objectClass.getMustAttributeTypeOids().isEmpty() )
455        {
456            if ( schemaManager != null )
457            {
458                attr = new DefaultAttribute( schemaManager.getAttributeType( MetaSchemaConstants.M_MUST_AT ) );
459            }
460            else
461            {
462                attr = new DefaultAttribute( MetaSchemaConstants.M_MUST_AT );
463            }
464
465            for ( String mustOid : objectClass.getMustAttributeTypeOids() )
466            {
467                attr.add( mustOid );
468            }
469
470            entry.put( attr );
471        }
472
473        // add the may list
474        if ( ( objectClass.getMayAttributeTypeOids() != null ) && !objectClass.getMayAttributeTypeOids().isEmpty() )
475        {
476            if ( schemaManager != null )
477            {
478                attr = new DefaultAttribute( schemaManager.getAttributeType( MetaSchemaConstants.M_MAY_AT ) );
479            }
480            else
481            {
482                attr = new DefaultAttribute( MetaSchemaConstants.M_MAY_AT );
483            }
484
485            for ( String mayOid : objectClass.getMayAttributeTypeOids() )
486            {
487                attr.add( mayOid );
488            }
489
490            entry.put( attr );
491        }
492
493        return entry;
494    }
495
496
497    private void injectCommon( SchemaObject object, Entry entry, SchemaManager schemaManager )
498        throws LdapException
499    {
500        injectNames( object.getNames(), entry, schemaManager );
501        entry.put( MetaSchemaConstants.M_OBSOLETE_AT, getBoolean( object.isObsolete() ) );
502        entry.put( MetaSchemaConstants.M_OID_AT, object.getOid() );
503
504        if ( object.getDescription() != null )
505        {
506            entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, object.getDescription() );
507        }
508
509        // The extensions
510        Map<String, List<String>> extensions = object.getExtensions();
511
512        if ( extensions != null )
513        {
514            for ( Map.Entry<String, List<String>> mapEntry : extensions.entrySet() )
515            {
516                String key = mapEntry.getKey();
517                List<String> values = mapEntry.getValue();
518
519                for ( String value : values )
520                {
521                    entry.add( key, value );
522                }
523            }
524        }
525    }
526
527
528    private void injectNames( List<String> names, Entry entry, SchemaManager schemaManager ) throws LdapException
529    {
530        if ( ( names == null ) || names.isEmpty() )
531        {
532            return;
533        }
534
535        Attribute attr;
536
537        if ( schemaManager != null )
538        {
539            attr = new DefaultAttribute( schemaManager.getAttributeType( MetaSchemaConstants.M_NAME_AT ) );
540        }
541        else
542        {
543            attr = new DefaultAttribute( MetaSchemaConstants.M_NAME_AT );
544        }
545
546        for ( String name : names )
547        {
548            attr.add( name );
549        }
550
551        entry.put( attr );
552    }
553
554
555    private String getBoolean( boolean value )
556    {
557        if ( value )
558        {
559            return "TRUE";
560        }
561        else
562        {
563            return "FALSE";
564        }
565    }
566}