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.List;
024import java.util.Map;
025
026
027/**
028 * Utility class used to generate schema object specifications. Some of the
029 * latest work coming out of the LDAPBIS working body adds optional extensions
030 * to these syntaxes. Descriptions can be generated for
031 * the following objects:
032 * <ul>
033 * <li><a href="./AttributeType.html">AttributeType</a></li>
034 * <li><a href="./DitContentRule.html">DitContentRule</a></li>
035 * <li><a href="./DitContentRule.html">DitStructureRule</a></li>
036 * <li><a href="./LdapComparator.html">Syntax</a></li>
037 * <li><a href="./MatchingRule.html">MatchingRule</a></li>
038 * <li><a href="./MatchingRuleUse.html">MatchingRuleUse</a></li>
039 * <li><a href="./NameForm.html">NameForm</a></li>
040 * <li><a href="./Normalizer.html">Syntax</a></li>
041 * <li><a href="./ObjectClass.html">ObjectClass</a></li>
042 * <li><a href="./LdapSyntax.html">Syntax</a></li>
043 * <li><a href="./SyntaxChecker.html">Syntax</a></li>
044 * </ul>
045 * 
046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
047 */
048public final class DescriptionUtils
049{
050    /**
051     * Private constructor.
052     */
053    private DescriptionUtils()
054    {
055    }
056
057
058    /**
059     * Generates the ComparatorDescription for a LdapComparator. Only the right 
060     * hand side of the description starting at the opening parenthesis is 
061     * generated: that is 'ComparatorDescription = ' is not generated.
062     * 
063     * <pre>
064     * ComparatorDescription = &quot;(&quot;
065     *     numericoid                          
066     *     [&quot;DESC&quot; qdstring ]
067     *     &quot;FQCN&quot; whsp fqcn
068     *     [&quot;BYTECODE&quot; whsp base64  ]
069     *     extensions 
070     *     &quot;)&quot;
071     * </pre>
072     * 
073     * @param comparator
074     *            the Comparator to generate the description for
075     * @return the ComparatorDescription string
076     */
077    public static String getDescription( LdapComparator<?> comparator )
078    {
079        return getLoadableDescription( comparator );
080    }
081
082
083    /**
084     * Generates the NormalizerDescription for a Normalizer. Only the right 
085     * hand side of the description starting at the opening parenthesis is 
086     * generated: that is 'NormalizerDescription = ' is not generated.
087     * 
088     * <pre>
089     * NormalizerDescription = &quot;(&quot;
090     *     numericoid                          
091     *     [&quot;DESC&quot; qdstring ]
092     *     &quot;FQCN&quot; whsp fqcn
093     *     [&quot;BYTECODE&quot; whsp base64  ]
094     *     extensions 
095     *     &quot;)&quot;
096     * </pre>
097     * 
098     * @param normalizer
099     *            the Normalizer to generate the description for
100     * @return the NormalizerDescription string
101     */
102    public static String getDescription( Normalizer normalizer )
103    {
104        return getLoadableDescription( normalizer );
105    }
106
107
108    /**
109     * Generates the SyntaxCheckerDescription for a SyntaxChecker. Only the right 
110     * hand side of the description starting at the opening parenthesis is 
111     * generated: that is 'SyntaxCheckerDescription = ' is not generated.
112     * 
113     * <pre>
114     * SyntaxCheckerDescription = &quot;(&quot;
115     *     numericoid                          
116     *     [&quot;DESC&quot; qdstring ]
117     *     &quot;FQCN&quot; whsp fqcn
118     *     [&quot;BYTECODE&quot; whsp base64  ]
119     *     extensions 
120     *     &quot;)&quot;
121     * </pre>
122     * 
123     * @param syntaxChecker
124     *            the SyntaxChecker to generate the description for
125     * @return the SyntaxCheckerDescription string
126     */
127    public static String getDescription( SyntaxChecker syntaxChecker )
128    {
129        return getLoadableDescription( syntaxChecker );
130    }
131
132
133    private static void getExtensions( StringBuilder sb, Map<String, List<String>> extensions )
134    {
135        for ( Map.Entry<String, List<String>> extension : extensions.entrySet() )
136        {
137            sb.append( ' ' ).append( extension.getKey() ).append( ' ' );
138
139            List<String> values = extension.getValue();
140
141            if ( ( values != null ) && !values.isEmpty() )
142            {
143                if ( values.size() == 1 )
144                {
145                    sb.append( values.get( 0 ) );
146                }
147                else
148                {
149                    boolean isFirst = true;
150                    sb.append( "( " );
151
152                    for ( String value : values )
153                    {
154                        if ( isFirst )
155                        {
156                            isFirst = false;
157                        }
158                        else
159                        {
160                            sb.append( ' ' );
161                        }
162
163                        sb.append( value );
164                    }
165
166                    sb.append( " )" );
167                }
168            }
169
170            sb.append( '\n' );
171        }
172    }
173
174
175    /**
176     * Generate the description for Comparators, Normalizers and SyntaxCheckers.
177     */
178    private static String getLoadableDescription( LoadableSchemaObject schemaObject )
179    {
180        StringBuilder buf = new StringBuilder( "( " );
181        buf.append( schemaObject.getOid() );
182        buf.append( '\n' );
183
184        if ( schemaObject.getDescription() != null )
185        {
186            buf.append( " DESC " );
187            buf.append( schemaObject.getDescription() );
188            buf.append( '\n' );
189        }
190
191        if ( schemaObject.getFqcn() != null )
192        {
193            buf.append( " FQCN " );
194            buf.append( schemaObject.getFqcn() );
195            buf.append( '\n' );
196        }
197
198        if ( schemaObject.getBytecode() != null )
199        {
200            buf.append( " BYTECODE " );
201
202            // We will dump only the 16 first bytes
203            if ( schemaObject.getBytecode().length() > 16 )
204            {
205                buf.append( schemaObject.getBytecode().substring( 0, 16 ) );
206            }
207            else
208            {
209                buf.append( schemaObject.getBytecode() );
210            }
211
212            buf.append( '\n' );
213        }
214
215        if ( schemaObject.getExtensions() != null )
216        {
217            getExtensions( buf, schemaObject.getExtensions() );
218        }
219
220        buf.append( " ) " );
221
222        return buf.toString();
223    }
224}