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.server.core.api.schema;
021
022
023import java.text.ParseException;
024
025import org.apache.directory.api.ldap.model.constants.SchemaConstants;
026import org.apache.directory.api.ldap.model.entry.Attribute;
027import org.apache.directory.api.ldap.model.entry.Value;
028import org.apache.directory.api.ldap.model.exception.LdapException;
029import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
030import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
031import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
032import org.apache.directory.api.ldap.model.schema.AttributeType;
033import org.apache.directory.api.ldap.model.schema.DitContentRule;
034import org.apache.directory.api.ldap.model.schema.DitStructureRule;
035import org.apache.directory.api.ldap.model.schema.LdapSyntax;
036import org.apache.directory.api.ldap.model.schema.MatchingRule;
037import org.apache.directory.api.ldap.model.schema.MatchingRuleUse;
038import org.apache.directory.api.ldap.model.schema.NameForm;
039import org.apache.directory.api.ldap.model.schema.ObjectClass;
040import org.apache.directory.api.ldap.model.schema.SchemaManager;
041import org.apache.directory.api.ldap.model.schema.parsers.AttributeTypeDescriptionSchemaParser;
042import org.apache.directory.api.ldap.model.schema.parsers.DitContentRuleDescriptionSchemaParser;
043import org.apache.directory.api.ldap.model.schema.parsers.DitStructureRuleDescriptionSchemaParser;
044import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescription;
045import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescriptionSchemaParser;
046import org.apache.directory.api.ldap.model.schema.parsers.LdapSyntaxDescriptionSchemaParser;
047import org.apache.directory.api.ldap.model.schema.parsers.MatchingRuleDescriptionSchemaParser;
048import org.apache.directory.api.ldap.model.schema.parsers.MatchingRuleUseDescriptionSchemaParser;
049import org.apache.directory.api.ldap.model.schema.parsers.NameFormDescriptionSchemaParser;
050import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescription;
051import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescriptionSchemaParser;
052import org.apache.directory.api.ldap.model.schema.parsers.ObjectClassDescriptionSchemaParser;
053import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescription;
054import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescriptionSchemaParser;
055import org.apache.directory.server.i18n.I18n;
056
057
058/**
059 * TODO: move to apacheds-core?
060 * 
061 * Parses descriptions using a number of different parsers for schema descriptions.
062 * Also checks to make sure some things are valid as it's parsing paramters of
063 * certain entity types.
064 *
065 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
066 */
067public class DescriptionParsers
068{
069    /** Empty arrays of SchemaObjects */
070    private static final LdapComparatorDescription[] EMPTY_COMPARATORS = new LdapComparatorDescription[0];
071    private static final NormalizerDescription[] EMPTY_NORMALIZERS = new NormalizerDescription[0];
072    private static final SyntaxCheckerDescription[] EMPTY_SYNTAX_CHECKERS = new SyntaxCheckerDescription[0];
073    private static final LdapSyntax[] EMPTY_SYNTAXES = new LdapSyntax[0];
074    private static final MatchingRule[] EMPTY_MATCHING_RULES = new MatchingRule[0];
075    private static final AttributeType[] EMPTY_ATTRIBUTE_TYPES = new AttributeType[0];
076    private static final ObjectClass[] EMPTY_OBJECT_CLASSES = new ObjectClass[0];
077    private static final MatchingRuleUse[] EMPTY_MATCHING_RULE_USES = new MatchingRuleUse[0];
078    private static final DitStructureRule[] EMPTY_DIT_STRUCTURE_RULES = new DitStructureRule[0];
079    private static final DitContentRule[] EMPTY_DIT_CONTENT_RULES = new DitContentRule[0];
080    private static final NameForm[] EMPTY_NAME_FORMS = new NameForm[0];
081
082    /** The SchemaObject description's parsers */
083    private final LdapComparatorDescriptionSchemaParser comparatorParser = new LdapComparatorDescriptionSchemaParser();
084    private final NormalizerDescriptionSchemaParser normalizerParser = new NormalizerDescriptionSchemaParser();
085    private final SyntaxCheckerDescriptionSchemaParser syntaxCheckerParser = new SyntaxCheckerDescriptionSchemaParser();
086    private final LdapSyntaxDescriptionSchemaParser syntaxParser = new LdapSyntaxDescriptionSchemaParser();
087    private final MatchingRuleDescriptionSchemaParser matchingRuleParser = new MatchingRuleDescriptionSchemaParser();
088    private final AttributeTypeDescriptionSchemaParser attributeTypeParser = new AttributeTypeDescriptionSchemaParser();
089    private final ObjectClassDescriptionSchemaParser objectClassParser = new ObjectClassDescriptionSchemaParser();
090    private final MatchingRuleUseDescriptionSchemaParser matchingRuleUseParser = new MatchingRuleUseDescriptionSchemaParser();
091    private final DitStructureRuleDescriptionSchemaParser ditStructureRuleParser = new DitStructureRuleDescriptionSchemaParser();
092    private final DitContentRuleDescriptionSchemaParser ditContentRuleParser = new DitContentRuleDescriptionSchemaParser();
093    private final NameFormDescriptionSchemaParser nameFormParser = new NameFormDescriptionSchemaParser();
094
095    /** The SchemaManager instance */
096    private final SchemaManager schemaManager;
097
098
099    /**
100     * Creates a description parser.
101     * 
102     * @param schemaManager The server schemaManager to use while creating new schema entities
103     */
104    public DescriptionParsers( SchemaManager schemaManager )
105    {
106        this.schemaManager = schemaManager;
107    }
108
109
110    /**
111     * Parse the SyntaxCheckers description
112     *
113     * @param attr The attribute containing the SC description
114     * @return The array of SyntaxCheckerDescription instances
115     * @throws LdapInvalidAttributeValueException If something went wrong
116     */
117    public SyntaxCheckerDescription[] parseSyntaxCheckers( Attribute attr ) throws LdapInvalidAttributeValueException
118    {
119        if ( ( attr == null ) || ( attr.size() == 0 ) )
120        {
121            return EMPTY_SYNTAX_CHECKERS;
122        }
123
124        SyntaxCheckerDescription[] syntaxCheckerDescriptions = new SyntaxCheckerDescription[attr.size()];
125
126        int pos = 0;
127
128        for ( Value value : attr )
129        {
130            try
131            {
132                syntaxCheckerDescriptions[pos++] = syntaxCheckerParser
133                    .parse( value.getString() );
134            }
135            catch ( ParseException e )
136            {
137                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
138                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_405,
139                        value ) );
140                iave.initCause( e );
141                throw iave;
142            }
143        }
144
145        return syntaxCheckerDescriptions;
146    }
147
148
149    public NormalizerDescription[] parseNormalizers( Attribute attr ) throws LdapInvalidAttributeValueException
150    {
151        if ( attr == null || attr.size() == 0 )
152        {
153            return EMPTY_NORMALIZERS;
154        }
155
156        NormalizerDescription[] normalizerDescriptions = new NormalizerDescription[attr.size()];
157
158        int pos = 0;
159
160        for ( Value value : attr )
161        {
162            try
163            {
164                normalizerDescriptions[pos++] = normalizerParser.parse( value.getString() );
165            }
166            catch ( ParseException e )
167            {
168                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
169                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_406,
170                        value.getString() ) );
171                iave.initCause( e );
172                throw iave;
173            }
174        }
175
176        return normalizerDescriptions;
177    }
178
179
180    public LdapComparatorDescription[] parseComparators( Attribute attr ) throws LdapInvalidAttributeValueException
181    {
182        if ( attr == null || attr.size() == 0 )
183        {
184            return EMPTY_COMPARATORS;
185        }
186
187        LdapComparatorDescription[] comparatorDescriptions = new LdapComparatorDescription[attr.size()];
188
189        int pos = 0;
190
191        for ( Value value : attr )
192        {
193            try
194            {
195                comparatorDescriptions[pos++] = comparatorParser.parse( value.getString() );
196            }
197            catch ( ParseException e )
198            {
199                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
200                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_407,
201                        value.getString() ) );
202                iave.initCause( e );
203                throw iave;
204            }
205        }
206
207        return comparatorDescriptions;
208    }
209
210
211    /**
212     * Parses a set of attributeTypeDescriptions held within an attribute into
213     * schema entities.
214     * 
215     * @param attr the attribute containing attributeTypeDescriptions
216     * @return the set of attributeType objects for the descriptions
217     * @throws LdapException if there are problems parsing the descriptions
218     */
219    public AttributeType[] parseAttributeTypes( Attribute attr ) throws LdapException
220    {
221        if ( ( attr == null ) || ( attr.size() == 0 ) )
222        {
223            return EMPTY_ATTRIBUTE_TYPES;
224        }
225
226        AttributeType[] attributeTypes = new AttributeType[attr.size()];
227
228        int pos = 0;
229
230        for ( Value value : attr )
231        {
232            AttributeType attributeType = null;
233
234            try
235            {
236                attributeType = attributeTypeParser.parse( value.getString() );
237            }
238            catch ( ParseException e )
239            {
240                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
241                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_408,
242                        value.getString() ) );
243                iave.initCause( e );
244                throw iave;
245            }
246
247            // if the supertype is provided make sure it exists in some schema
248            if ( ( attributeType.getSuperiorOid() != null )
249                && !schemaManager.getAttributeTypeRegistry().contains( attributeType.getSuperiorOid() ) )
250            {
251                throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
252                    I18n.err( I18n.ERR_409, attributeType.getSuperiorOid() ) );
253            }
254
255            // if the syntax is provided by the description make sure it exists in some schema
256            if ( ( attributeType.getSyntaxOid() != null )
257                && !schemaManager.getLdapSyntaxRegistry().contains( attributeType.getSyntaxOid() ) )
258            {
259                throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
260                    I18n.err( I18n.ERR_410, attributeType.getSyntaxOid() ) );
261            }
262
263            // if the matchingRule is provided make sure it exists in some schema
264            if ( ( attributeType.getEqualityOid() != null )
265                && !schemaManager.getMatchingRuleRegistry().contains( attributeType.getEqualityOid() ) )
266            {
267                throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
268                    I18n.err( I18n.ERR_411, attributeType.getEqualityOid() ) );
269            }
270
271            // if the matchingRule is provided make sure it exists in some schema
272            if ( ( attributeType.getOrderingOid() != null )
273                && !schemaManager.getMatchingRuleRegistry().contains( attributeType.getOrderingOid() ) )
274            {
275                throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
276                    I18n.err( I18n.ERR_412, attributeType.getOrderingOid() ) );
277            }
278
279            // if the matchingRule is provided make sure it exists in some schema
280            if ( ( attributeType.getSubstringOid() != null )
281                && !schemaManager.getMatchingRuleRegistry().contains( attributeType.getSubstringOid() ) )
282            {
283                throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
284                    I18n.err( I18n.ERR_413, attributeType.getSubstringOid() ) );
285            }
286
287            attributeTypes[pos++] = attributeType;
288        }
289
290        return attributeTypes;
291    }
292
293
294    /**
295     * Parses a set of objectClassDescriptions held within an attribute into
296     * schema entities.
297     * 
298     * @param attr the attribute containing objectClassDescriptions
299     * @return the set of objectClass objects for the descriptions
300     * @throws LdapException if there are problems parsing the descriptions
301     */
302    public ObjectClass[] parseObjectClasses( Attribute attr ) throws LdapException
303    {
304        if ( attr == null || attr.size() == 0 )
305        {
306            return EMPTY_OBJECT_CLASSES;
307        }
308
309        ObjectClass[] objectClasses = new ObjectClass[attr.size()];
310
311        int pos = 0;
312
313        for ( Value value : attr )
314        {
315            ObjectClass objectClass = null;
316
317            try
318            {
319                objectClass = objectClassParser.parse( value.getString() );
320            }
321            catch ( ParseException e )
322            {
323                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
324                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_417,
325                        value.getString() ) );
326                iave.initCause( e );
327                throw iave;
328            }
329
330            // if the super objectClasses are provided make sure it exists in some schema
331            if ( objectClass.getSuperiorOids() != null && !objectClass.getSuperiorOids().isEmpty() )
332            {
333                for ( String superiorOid : objectClass.getSuperiorOids() )
334                {
335                    if ( superiorOid.equals( SchemaConstants.TOP_OC_OID )
336                        || superiorOid.equalsIgnoreCase( SchemaConstants.TOP_OC ) )
337                    {
338                        continue;
339                    }
340
341                    if ( !schemaManager.getObjectClassRegistry().contains( superiorOid ) )
342                    {
343                        throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
344                            I18n.err( I18n.ERR_418, superiorOid ) );
345                    }
346                }
347            }
348
349            // if the may list is provided make sure attributes exists in some schema
350            if ( objectClass.getMayAttributeTypeOids() != null && !objectClass.getMayAttributeTypeOids().isEmpty() )
351            {
352                for ( String mayAttrOid : objectClass.getMayAttributeTypeOids() )
353                {
354                    if ( !schemaManager.getAttributeTypeRegistry().contains( mayAttrOid ) )
355                    {
356                        throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
357                            I18n.err( I18n.ERR_419, mayAttrOid ) );
358                    }
359                }
360            }
361
362            // if the must list is provided make sure attributes exists in some schema
363            if ( objectClass.getMustAttributeTypeOids() != null && !objectClass.getMustAttributeTypeOids().isEmpty() )
364            {
365                for ( String mustAttrOid : objectClass.getMustAttributeTypeOids() )
366                {
367                    if ( !schemaManager.getAttributeTypeRegistry().contains( mustAttrOid ) )
368                    {
369                        throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
370                            I18n.err( I18n.ERR_420, mustAttrOid ) );
371                    }
372                }
373            }
374
375            objectClasses[pos++] = objectClass;
376        }
377
378        return objectClasses;
379    }
380
381
382    /**
383     * Parses a set of matchingRuleUseDescriptions held within an attribute into
384     * schema entities.
385     * 
386     * @param attr the attribute containing matchingRuleUseDescriptions
387     * @return the set of matchingRuleUse objects for the descriptions
388     * @throws org.apache.directory.api.ldap.model.exception.LdapException if there are problems parsing the descriptions
389     */
390    public MatchingRuleUse[] parseMatchingRuleUses( Attribute attr ) throws LdapException
391    {
392        if ( attr == null || attr.size() == 0 )
393        {
394            return EMPTY_MATCHING_RULE_USES;
395        }
396
397        MatchingRuleUse[] matchingRuleUses = new MatchingRuleUse[attr.size()];
398
399        int pos = 0;
400
401        for ( Value value : attr )
402        {
403            MatchingRuleUse matchingRuleUse = null;
404
405            try
406            {
407                matchingRuleUse = matchingRuleUseParser.parse( value.getString() );
408                matchingRuleUse.setSpecification( value.getString() );
409            }
410            catch ( ParseException e )
411            {
412                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
413                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_421,
414                        value.getString() ) );
415                iave.initCause( e );
416                throw iave;
417            }
418
419            matchingRuleUses[pos++] = matchingRuleUse;
420        }
421
422        return matchingRuleUses;
423    }
424
425
426    /**
427     * Parses a set of ldapSyntaxes held within an attribute into
428     * schema entities.
429     * 
430     * @param attr the attribute containing ldapSyntaxes
431     * @return the set of Syntax objects for the descriptions
432     * @throws org.apache.directory.api.ldap.model.exception.LdapException if there are problems parsing the descriptions
433     */
434    public LdapSyntax[] parseLdapSyntaxes( Attribute attr ) throws LdapException
435    {
436        if ( attr == null || attr.size() == 0 )
437        {
438            return EMPTY_SYNTAXES;
439        }
440
441        LdapSyntax[] syntaxes = new LdapSyntax[attr.size()];
442
443        int pos = 0;
444
445        for ( Value value : attr )
446        {
447            LdapSyntax ldapSyntax = null;
448
449            try
450            {
451                ldapSyntax = syntaxParser.parse( value.getString() );
452                ldapSyntax.setSpecification( value.getString() );
453            }
454            catch ( ParseException e )
455            {
456                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
457                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_422,
458                        value.getString() ) );
459                iave.initCause( e );
460                throw iave;
461            }
462
463            if ( !schemaManager.getSyntaxCheckerRegistry().contains( ldapSyntax.getOid() ) )
464            {
465                throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, I18n.err( I18n.ERR_423 ) );
466            }
467
468            // Call this method once to initialize the flags
469            ldapSyntax.isHumanReadable();
470            
471            syntaxes[pos++] = ldapSyntax;
472        }
473
474        return syntaxes;
475    }
476
477
478    /**
479     * Parses a set of matchingRuleDescriptions held within an attribute into
480     * schema entities.
481     * 
482     * @param attr the attribute containing matchingRuleDescriptions
483     * @return the set of matchingRule objects for the descriptions
484     * @throws LdapException if there are problems parsing the descriptions
485     */
486    public MatchingRule[] parseMatchingRules( Attribute attr ) throws LdapException
487    {
488        if ( attr == null || attr.size() == 0 )
489        {
490            return EMPTY_MATCHING_RULES;
491        }
492
493        MatchingRule[] matchingRules = new MatchingRule[attr.size()];
494
495        int pos = 0;
496
497        for ( Value value : attr )
498        {
499            MatchingRule matchingRule = null;
500
501            try
502            {
503                matchingRule = matchingRuleParser.parse( value.getString() );
504                matchingRule.setSpecification( value.getString() );
505            }
506            catch ( ParseException e )
507            {
508                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
509                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_424,
510                        value.getString() ) );
511                iave.initCause( e );
512                throw iave;
513            }
514
515            if ( !schemaManager.getLdapSyntaxRegistry().contains( matchingRule.getSyntaxOid() ) )
516            {
517                throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
518                    I18n.err( I18n.ERR_425, matchingRule.getSyntaxOid() ) );
519            }
520
521            matchingRules[pos++] = matchingRule;
522        }
523
524        return matchingRules;
525    }
526
527
528    /**
529     * Parses a set of dITStructureRuleDescriptions held within an attribute into
530     * schema entities.
531     * 
532     * @param attr the attribute containing dITStructureRuleDescriptions
533     * @return the set of DitStructureRule objects for the descriptions
534     * @throws LdapException if there are problems parsing the descriptions
535     */
536    public DitStructureRule[] parseDitStructureRules( Attribute attr ) throws LdapException
537    {
538        if ( attr == null || attr.size() == 0 )
539        {
540            return EMPTY_DIT_STRUCTURE_RULES;
541        }
542
543        DitStructureRule[] ditStructureRules = new DitStructureRule[attr.size()];
544
545        int pos = 0;
546
547        for ( Value value : attr )
548        {
549            DitStructureRule ditStructureRule = null;
550
551            try
552            {
553                ditStructureRule = ditStructureRuleParser.parse( value.getString() );
554                ditStructureRule.setSpecification( value.getString() );
555            }
556            catch ( ParseException e )
557            {
558                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
559                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_426,
560                        value.getString() ) );
561                iave.initCause( e );
562                throw iave;
563            }
564
565            ditStructureRules[pos++] = ditStructureRule;
566        }
567
568        return ditStructureRules;
569    }
570
571
572    /**
573     * Parses a set of dITContentRuleDescriptions held within an attribute into
574     * schema entities.
575     * 
576     * @param attr the attribute containing dITContentRuleDescriptions
577     * @return the set of DitContentRule objects for the descriptions
578     * @throws LdapException if there are problems parsing the descriptions
579     */
580    public DitContentRule[] parseDitContentRules( Attribute attr ) throws LdapException
581    {
582        if ( attr == null || attr.size() == 0 )
583        {
584            return EMPTY_DIT_CONTENT_RULES;
585        }
586
587        DitContentRule[] ditContentRules = new DitContentRule[attr.size()];
588
589        int pos = 0;
590
591        for ( Value value : attr )
592        {
593            DitContentRule ditContentRule = null;
594
595            try
596            {
597                ditContentRule = ditContentRuleParser.parse( value.getString() );
598                ditContentRule.setSpecification( value.getString() );
599            }
600            catch ( ParseException e )
601            {
602                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
603                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_427,
604                        value.getString() ) );
605                iave.initCause( e );
606                throw iave;
607            }
608
609            ditContentRules[pos++] = ditContentRule;
610        }
611
612        return ditContentRules;
613    }
614
615
616    /**
617     * Parses a set of nameFormDescriptions held within an attribute into
618     * schema entities.
619     * 
620     * @param attr the attribute containing nameFormDescriptions
621     * @return the set of NameFormRule objects for the descriptions
622     * @throws LdapException if there are problems parsing the descriptions
623     */
624    public NameForm[] parseNameForms( Attribute attr ) throws LdapException
625    {
626        if ( attr == null || attr.size() == 0 )
627        {
628            return EMPTY_NAME_FORMS;
629        }
630
631        NameForm[] nameForms = new NameForm[attr.size()];
632
633        int pos = 0;
634
635        for ( Value value : attr )
636        {
637            NameForm nameForm = null;
638
639            try
640            {
641                nameForm = nameFormParser.parse( value.getString() );
642                nameForm.setSpecification( value.getString() );
643            }
644            catch ( ParseException e )
645            {
646                LdapInvalidAttributeValueException iave = new LdapInvalidAttributeValueException(
647                    ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_428,
648                        value.getString() ) );
649                iave.initCause( e );
650                throw iave;
651            }
652
653            nameForms[pos++] = nameForm;
654        }
655
656        return nameForms;
657    }
658}