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.util.List;
024 import 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 * @version $Rev: 896579 $
048 */
049 public class DescriptionUtils
050 {
051 /**
052 * Generates the description using the AttributeTypeDescription as defined
053 * by the syntax: 1.3.6.1.4.1.1466.115.121.1.3. Only the right hand side of
054 * the description starting at the opening parenthesis is generated: that
055 * is 'AttributeTypeDescription = ' is not generated.
056 *
057 * <pre>
058 * AttributeTypeDescription = "(" whsp
059 * numericoid whsp ; AttributeType identifier
060 * [ "NAME" qdescrs ] ; name used in AttributeType
061 * [ "DESC" qdstring ] ; description
062 * [ "OBSOLETE" whsp ]
063 * [ "SUP" woid ] ; derived from parent AttributeType
064 * [ "EQUALITY" woid ; Matching Rule name
065 * [ "ORDERING" woid ; Matching Rule name
066 * [ "SUBSTR" woid ] ; Matching Rule name
067 * [ "SYNTAX" whsp noidlen whsp ] ; see section 4.3 RFC 2252
068 * [ "SINGLE-VALUE" whsp ] ; default multi-valued
069 * [ "COLLECTIVE" whsp ] ; default not collective
070 * [ "NO-USER-MODIFICATION" whsp ]; default user modifiable
071 * [ "USAGE" whsp AttributeUsage ]; default userApplications
072 * whsp ")"
073 * </pre>
074 *
075 * @param attributeType
076 * the attributeType to generate a description for
077 * @return the AttributeTypeDescription Syntax for the attributeType in a
078 * pretty formated string
079 */
080 public static String getDescription( AttributeType attributeType )
081 {
082 StringBuilder buf = new StringBuilder( "( " );
083 buf.append( attributeType.getOid() );
084 buf.append( '\n' );
085
086 if ( attributeType.getNames().size() != 0 )
087 {
088 buf.append( " NAME " );
089 getQDescrs( buf, attributeType.getNames() );
090 }
091
092 if ( attributeType.getDescription() != null )
093 {
094 buf.append( " DESC " );
095 buf.append( attributeType.getDescription() );
096 buf.append( '\n' );
097 }
098
099 if ( attributeType.isObsolete() )
100 {
101 buf.append( " OBSOLETE\n" );
102 }
103
104 if ( attributeType.getSuperior() != null )
105 {
106 buf.append( " SUP " );
107 buf.append( attributeType.getSuperiorName() );
108 buf.append( '\n' );
109 }
110
111 if ( attributeType.getEquality() != null )
112 {
113 buf.append( " EQUALITY " );
114 buf.append( attributeType.getEqualityName() );
115 buf.append( '\n' );
116 }
117
118 if ( attributeType.getOrdering() != null )
119 {
120 buf.append( " ORDERING " );
121 buf.append( attributeType.getOrderingName() );
122 buf.append( '\n' );
123 }
124
125 if ( attributeType.getSubstring() != null )
126 {
127 buf.append( " SUBSTR " );
128 buf.append( attributeType.getSubstringName() );
129 buf.append( '\n' );
130 }
131
132 if ( attributeType.getSyntax() != null )
133 {
134 buf.append( " SYNTAX " );
135
136 buf.append( attributeType.getSyntaxName() );
137
138 if ( attributeType.getSyntaxLength() > 0 )
139 {
140 buf.append( '{' ).append( attributeType.getSyntaxLength() ).append( '}' );
141 }
142
143 buf.append( '\n' );
144 }
145
146 if ( attributeType.isSingleValued() )
147 {
148 buf.append( " SINGLE-VALUE\n" );
149 }
150
151 if ( attributeType.isCollective() )
152 {
153 buf.append( " COLLECTIVE\n" );
154 }
155
156 if ( !attributeType.isUserModifiable() )
157 {
158 buf.append( " NO-USER-MODIFICATION\n" );
159 }
160
161 buf.append( " USAGE " );
162 buf.append( UsageEnum.render( attributeType.getUsage() ) );
163 buf.append( '\n' );
164
165 if ( attributeType.getExtensions() != null )
166 {
167 getExtensions( buf, attributeType.getExtensions() );
168 }
169
170 buf.append( " )\n" );
171
172 return buf.toString();
173 }
174
175
176 /**
177 * Generates the ComparatorDescription for a LdapComparator. Only the right
178 * hand side of the description starting at the opening parenthesis is
179 * generated: that is 'ComparatorDescription = ' is not generated.
180 *
181 * <pre>
182 * ComparatorDescription = "("
183 * numericoid
184 * ["DESC" qdstring ]
185 * "FQCN" whsp fqcn
186 * ["BYTECODE" whsp base64 ]
187 * extensions
188 * ")"
189 * </pre>
190 *
191 * @param comparator
192 * the Comparator to generate the description for
193 * @return the ComparatorDescription string
194 */
195 public static String getDescription( LdapComparator<?> comparator )
196 {
197 return getLoadableDescription( comparator );
198 }
199
200
201 /**
202 * Generates the DITContentRuleDescription for a DITContentRule as defined
203 * by the syntax: 1.3.6.1.4.1.1466.115.121.1.16. Only the right hand side of
204 * the description starting at the opening parenthesis is generated: that
205 * is 'DITContentRuleDescription = ' is not generated.
206 *
207 * <pre>
208 * DITContentRuleDescription = "("
209 * numericoid ; Structural ObjectClass identifier
210 * [ "NAME" qdescrs ]
211 * [ "DESC" qdstring ]
212 * [ "OBSOLETE" ]
213 * [ "AUX" oids ] ; Auxiliary ObjectClasses
214 * [ "MUST" oids ] ; AttributeType identifiers
215 * [ "MAY" oids ] ; AttributeType identifiers
216 * [ "NOT" oids ] ; AttributeType identifiers
217 * ")"
218 * </pre>
219 *
220 * @param dITContentRule
221 * the DIT content rule specification
222 * @return the specification according to the DITContentRuleDescription
223 * syntax
224 */
225 public static String getDescription( DITContentRule dITContentRule )
226 {
227 StringBuilder buf = new StringBuilder( "( " );
228 buf.append( dITContentRule.getOid() );
229 buf.append( '\n' );
230
231 if ( dITContentRule.getNames() != null )
232 {
233 buf.append( " NAME " );
234 getQDescrs( buf, dITContentRule.getNames() );
235 buf.append( '\n' );
236 }
237
238 if ( dITContentRule.getDescription() != null )
239 {
240 buf.append( " DESC " );
241 buf.append( dITContentRule.getDescription() );
242 buf.append( '\n' );
243 }
244
245 if ( dITContentRule.isObsolete() )
246 {
247 buf.append( " OBSOLETE\n" );
248 }
249
250 // print out all the auxiliary object class oids
251 List<ObjectClass> aux = dITContentRule.getAuxObjectClasses();
252
253 if ( ( aux != null ) && ( aux.size() > 0 ) )
254 {
255 buf.append( " AUX " );
256 getQDStrings( buf, aux );
257 }
258
259 List<AttributeType> must = dITContentRule.getMustAttributeTypes();
260
261 if ( ( must != null ) && ( must.size() > 0 ) )
262 {
263 buf.append( " MUST " );
264 getQDStrings( buf, must );
265 }
266
267 List<AttributeType> may = dITContentRule.getMayAttributeTypes();
268
269 if ( ( may != null ) && ( may.size() > 0 ) )
270 {
271 buf.append( " MAY " );
272 getQDStrings( buf, may );
273 }
274
275 List<AttributeType> not = dITContentRule.getNotAttributeTypes();
276
277 if ( ( not != null ) && ( not.size() > 0 ) )
278 {
279 buf.append( " NOT " );
280 getQDStrings( buf, not );
281 }
282
283 if ( dITContentRule.getExtensions() != null )
284 {
285 getExtensions( buf, dITContentRule.getExtensions() );
286 }
287
288 buf.append( " )\n" );
289 return buf.toString();
290 }
291
292
293 /**
294 * Generates the DITStructureRuleDescription for a DITStructureRule as
295 * defined by the syntax: 1.3.6.1.4.1.1466.115.121.1.17. Only the right hand
296 * side of the description starting at the opening parenthesis is
297 * generated: that is 'DITStructureRuleDescription = ' is not generated.
298 *
299 * <pre>
300 * DITStructureRuleDescription = "(" whsp
301 * ruleid ; rule identifier
302 * [ SP "NAME" SP qdescrs ] ; short names (descriptors)
303 * [ SP "DESC" SP qdstring ] ; description
304 * [ SP "OBSOLETE" ] ; not active
305 * SP "FORM" SP oid ; NameForm
306 * [ SP "SUP" ruleids ] ; superior rules
307 * extensions WSP ; extensions
308 * ")"
309 * </pre>
310 *
311 * @param dITStructureRule
312 * the DITStructureRule to generate the description for
313 * @return the description in the DITStructureRuleDescription syntax
314 */
315 public static String getDescription( DITStructureRule dITStructureRule )
316 {
317 StringBuilder buf = new StringBuilder( "( " );
318 buf.append( dITStructureRule.getOid() );
319 buf.append( '\n' );
320
321 if ( dITStructureRule.getNames() != null )
322 {
323 buf.append( " NAME " );
324 getQDescrs( buf, dITStructureRule.getNames() );
325 }
326
327 if ( dITStructureRule.getDescription() != null )
328 {
329 buf.append( " DESC " );
330 buf.append( dITStructureRule.getDescription() );
331 buf.append( '\n' );
332 }
333
334 if ( dITStructureRule.isObsolete() )
335 {
336 buf.append( " OBSOLETE\n" );
337 }
338
339 buf.append( " FORM " );
340 buf.append( dITStructureRule.getForm() );
341 buf.append( '\n' );
342
343 // TODO : Shouldn't we get the ruleId OID ?
344 List<Integer> sups = dITStructureRule.getSuperRules();
345
346 if ( ( sups != null ) && ( sups.size() > 0 ) )
347 {
348 buf.append( " SUP\n" );
349
350 if ( sups.size() == 1 )
351 {
352 buf.append( sups.get( 0 ) );
353 }
354 else
355 {
356 boolean isFirst = true;
357 buf.append( "( " );
358
359 for ( int sup : sups )
360 {
361 if ( isFirst )
362 {
363 isFirst = false;
364 }
365 else
366 {
367 buf.append( " " );
368 }
369
370 buf.append( sup );
371 }
372
373 buf.append( " )" );
374 }
375
376 buf.append( '\n' );
377 }
378
379 buf.append( " )\n" );
380
381 return buf.toString();
382 }
383
384
385 /**
386 * Generates the MatchingRuleDescription for a MatchingRule as defined by
387 * the syntax: 1.3.6.1.4.1.1466.115.121.1.30. Only the right hand side of
388 * the description starting at the opening parenthesis is generated: that
389 * is 'MatchingRuleDescription = ' is not generated.
390 *
391 * <pre>
392 * MatchingRuleDescription = "(" whsp
393 * numericoid whsp ; MatchingRule object identifier
394 * [ "NAME" qdescrs ]
395 * [ "DESC" qdstring ]
396 * [ "OBSOLETE" whsp ]
397 * "SYNTAX" numericoid
398 * whsp ")"
399 * </pre>
400 *
401 * @param matchingRule
402 * the MatchingRule to generate the description for
403 * @return the MatchingRuleDescription string
404 */
405 public static String getDescription( MatchingRule matchingRule )
406 {
407 StringBuilder buf = new StringBuilder( "( " );
408 buf.append( matchingRule.getOid() );
409 buf.append( '\n' );
410
411 if ( matchingRule.getNames() != null )
412 {
413 buf.append( " NAME " );
414 getQDescrs( buf, matchingRule.getNames() );
415 }
416
417 if ( matchingRule.getDescription() != null )
418 {
419 buf.append( " DESC " );
420 buf.append( matchingRule.getDescription() );
421 buf.append( '\n' );
422 }
423
424 if ( matchingRule.isObsolete() )
425 {
426 buf.append( " OBSOLETE\n" );
427 }
428
429 buf.append( " SYNTAX " );
430 buf.append( matchingRule.getSyntaxOid() );
431 buf.append( '\n' );
432
433 if ( matchingRule.getExtensions() != null )
434 {
435 getExtensions( buf, matchingRule.getExtensions() );
436 }
437
438 buf.append( " ) " );
439 return buf.toString();
440 }
441
442
443 /**
444 * Generates the MatchingRuleUseDescription for a MatchingRuleUse as defined
445 * by the syntax: 1.3.6.1.4.1.1466.115.121.1.31. Only the right hand side of
446 * the description starting at the opening parenthesis is generated: that
447 * is 'MatchingRuleUseDescription = ' is not generated.
448 *
449 * <pre>
450 * MatchingRuleUseDescription = LPAREN WSP
451 * numericoid ; object identifier
452 * [ SP "NAME" SP qdescrs ] ; short names (descriptors)
453 * [ SP "DESC" SP qdstring ] ; description
454 * [ SP "OBSOLETE" ] ; not active
455 * SP "APPLIES" SP oids ; attribute types
456 * extensions WSP RPAREN ; extensions
457 *
458 * where:
459 * [numericoid] is the object identifier of the matching rule
460 * associated with this matching rule use description;
461 * NAME [qdescrs] are short names (descriptors) identifying this
462 * matching rule use;
463 * DESC [qdstring] is a short descriptive string;
464 * OBSOLETE indicates this matching rule use is not active;
465 * APPLIES provides a list of attribute types the matching rule applies
466 * to; and
467 * [extensions] describe extensions.
468 * </pre>
469 *
470 * @param matchingRuleUse The matching rule from which we want to generate
471 * a MatchingRuleUseDescription.
472 * @return The generated MatchingRuleUseDescription
473 */
474 public static String getDescription( MatchingRuleUse matchingRuleUse )
475 {
476 StringBuilder buf = new StringBuilder( "( " );
477 buf.append( matchingRuleUse.getOid() );
478 buf.append( '\n' );
479
480 buf.append( " NAME " );
481 getQDescrs( buf, matchingRuleUse.getNames() );
482
483 if ( matchingRuleUse.getDescription() != null )
484 {
485 buf.append( " DESC " );
486 buf.append( matchingRuleUse.getDescription() );
487 buf.append( '\n' );
488 }
489
490 if ( matchingRuleUse.isObsolete() )
491 {
492 buf.append( " OBSOLETE\n" );
493 }
494
495 buf.append( " APPLIES " );
496 List<AttributeType> attributeTypes = matchingRuleUse.getApplicableAttributes();
497
498 if ( attributeTypes.size() == 1 )
499 {
500 buf.append( attributeTypes.get( 0 ).getOid() );
501 }
502 else
503 // for list of oids we need a parenthesis
504 {
505 buf.append( "( " );
506
507 boolean isFirst = true;
508
509 for ( AttributeType attributeType : attributeTypes )
510 {
511 if ( isFirst )
512 {
513 isFirst = false;
514 }
515 else
516 {
517 buf.append( " $ " );
518 }
519
520 buf.append( attributeType );
521 }
522
523 buf.append( " ) " );
524 }
525
526 if ( matchingRuleUse.getExtensions() != null )
527 {
528 getExtensions( buf, matchingRuleUse.getExtensions() );
529 }
530
531 buf.append( " )\n" );
532
533 return buf.toString();
534 }
535
536
537 /**
538 * Generates the NameFormDescription for a NameForm as defined by the
539 * syntax: 1.3.6.1.4.1.1466.115.121.1.35. Only the right hand side of the
540 * description starting at the opening parenthesis is generated: that is
541 * 'NameFormDescription = ' is not generated.
542 *
543 * <pre>
544 * NameFormDescription = "(" whsp
545 * numericoid whsp ; NameForm identifier
546 * [ "NAME" qdescrs ]
547 * [ "DESC" qdstring ]
548 * [ "OBSOLETE" whsp ]
549 * "OC" woid ; Structural ObjectClass
550 * "MUST" oids ; AttributeTypes
551 * [ "MAY" oids ] ; AttributeTypes
552 * whsp ")"
553 * </pre>
554 *
555 * @param nameForm
556 * the NameForm to generate the description for
557 * @return the NameFormDescription string
558 */
559 public static String getDescription( NameForm nameForm )
560 {
561 StringBuilder buf = new StringBuilder( "( " );
562 buf.append( nameForm.getOid() );
563 buf.append( '\n' );
564
565 if ( nameForm.getNames() != null )
566 {
567 buf.append( " NAME " );
568 getQDescrs( buf, nameForm.getNames() );
569 }
570
571 if ( nameForm.getDescription() != null )
572 {
573 buf.append( " DESC " );
574 buf.append( nameForm.getDescription() );
575 buf.append( '\n' );
576 }
577
578 if ( nameForm.isObsolete() )
579 {
580 buf.append( " OBSOLETE\n" );
581 }
582
583 buf.append( " OC " );
584 buf.append( nameForm.getStructuralObjectClassOid() );
585 buf.append( '\n' );
586
587 buf.append( " MUST\n" );
588 List<AttributeType> must = nameForm.getMustAttributeTypes();
589
590 getQDStrings( buf, must );
591
592 List<AttributeType> may = nameForm.getMayAttributeTypes();
593
594 if ( ( may != null ) && ( may.size() > 0 ) )
595 {
596 buf.append( " MAY\n" );
597 getQDStrings( buf, may );
598 }
599
600 if ( nameForm.getExtensions() != null )
601 {
602 getExtensions( buf, nameForm.getExtensions() );
603 }
604
605 buf.append( " )\n" );
606 return buf.toString();
607 }
608
609
610 /**
611 * Generates the NormalizerDescription for a Normalizer. Only the right
612 * hand side of the description starting at the opening parenthesis is
613 * generated: that is 'NormalizerDescription = ' is not generated.
614 *
615 * <pre>
616 * NormalizerDescription = "("
617 * numericoid
618 * ["DESC" qdstring ]
619 * "FQCN" whsp fqcn
620 * ["BYTECODE" whsp base64 ]
621 * extensions
622 * ")"
623 * </pre>
624 *
625 * @param normalizer
626 * the Normalizer to generate the description for
627 * @return the NormalizerDescription string
628 */
629 public static String getDescription( Normalizer normalizer )
630 {
631 return getLoadableDescription( normalizer );
632 }
633
634
635 /**
636 * Generates the ObjectClassDescription for an ObjectClass as defined by the
637 * syntax: 1.3.6.1.4.1.1466.115.121.1.37. Only the right hand side of the
638 * description starting at the opening parenthesis is generated: that is
639 * 'ObjectClassDescription = ' is not generated.
640 *
641 * <pre>
642 * ObjectClassDescription = "(" whsp
643 * numericoid whsp ; ObjectClass identifier
644 * [ "NAME" qdescrs ]
645 * [ "DESC" qdstring ]
646 * [ "OBSOLETE" whsp ]
647 * [ "SUP" oids ] ; Superior ObjectClasses
648 * [ ( "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" ) whsp ]
649 * ; default structural
650 * [ "MUST" oids ] ; AttributeTypes
651 * [ "MAY" oids ] ; AttributeTypes
652 * whsp ")"
653 * </pre>
654 *
655 * @param objectClass
656 * the ObjectClass to generate a description for
657 * @return the description in the ObjectClassDescription syntax
658 */
659 public static String getDescription( ObjectClass objectClass )
660 {
661 StringBuilder buf = new StringBuilder( "( " );
662 buf.append( objectClass.getOid() );
663 buf.append( '\n' );
664
665 if ( ( objectClass.getNames() != null ) && ( objectClass.getNames().size() != 0 ) )
666 {
667 buf.append( " NAME " );
668 getQDescrs( buf, objectClass.getNames() );
669 }
670
671 if ( objectClass.getDescription() != null )
672 {
673 buf.append( " DESC " );
674 buf.append( objectClass.getDescription() );
675 buf.append( '\n' );
676 }
677
678 if ( objectClass.isObsolete() )
679 {
680 buf.append( " OBSOLETE\n" );
681 }
682
683 List<ObjectClass> sups = objectClass.getSuperiors();
684
685 if ( ( sups != null ) && ( sups.size() > 0 ) )
686 {
687 buf.append( " SUP " );
688 getQDStrings( buf, sups );
689 }
690
691 if ( objectClass.getType() != null )
692 {
693 buf.append( ' ' );
694 buf.append( objectClass.getType() );
695 buf.append( '\n' );
696 }
697
698 List<AttributeType> must = objectClass.getMustAttributeTypes();
699
700 if ( ( must != null ) && ( must.size() > 0 ) )
701 {
702 buf.append( " MUST " );
703 getQDStrings( buf, must );
704 }
705
706 List<AttributeType> may = objectClass.getMayAttributeTypes();
707
708 if ( ( may != null ) && ( may.size() > 0 ) )
709 {
710 buf.append( " MAY " );
711 getQDStrings( buf, may );
712 }
713
714 if ( objectClass.getExtensions() != null )
715 {
716 getExtensions( buf, objectClass.getExtensions() );
717 }
718
719 buf.append( " )\n" );
720
721 return buf.toString();
722 }
723
724
725 /**
726 * Generates the SyntaxDescription for a Syntax as defined by the syntax:
727 * 1.3.6.1.4.1.1466.115.121.1.54. Only the right hand side of the
728 * description starting at the opening parenthesis is generated: that is
729 * 'SyntaxDescription = ' is not generated.
730 *
731 * <pre>
732 * SyntaxDescription = "(" whsp
733 * numericoid whsp
734 * [ "DESC" qdstring ]
735 * [ extensions ]
736 * whsp ")"
737 * </pre>
738 *
739 * @param syntax
740 * the Syntax to generate a description for
741 * @return the description in the SyntaxDescription syntax
742 */
743 public static String getDescription( LdapSyntax syntax )
744 {
745 StringBuilder buf = new StringBuilder( "( " );
746 buf.append( syntax.getOid() );
747 buf.append( '\n' );
748
749 if ( syntax.getDescription() != null )
750 {
751 buf.append( " DESC " );
752 buf.append( syntax.getDescription() );
753 buf.append( '\n' );
754 }
755
756 if ( syntax.getExtensions() != null )
757 {
758 getExtensions( buf, syntax.getExtensions() );
759 }
760
761 buf.append( " )" );
762 return buf.toString();
763 }
764
765
766 /**
767 * Generates the SyntaxCheckerDescription for a SyntaxChecker. Only the right
768 * hand side of the description starting at the opening parenthesis is
769 * generated: that is 'SyntaxCheckerDescription = ' is not generated.
770 *
771 * <pre>
772 * SyntaxCheckerDescription = "("
773 * numericoid
774 * ["DESC" qdstring ]
775 * "FQCN" whsp fqcn
776 * ["BYTECODE" whsp base64 ]
777 * extensions
778 * ")"
779 * </pre>
780 *
781 * @param syntaxChecker
782 * the SyntaxChecker to generate the description for
783 * @return the SyntaxCheckerDescription string
784 */
785 public static String getDescription( SyntaxChecker syntaxChecker )
786 {
787 return getLoadableDescription( syntaxChecker );
788 }
789
790
791 private static void getExtensions( StringBuilder sb, Map<String, List<String>> extensions )
792 {
793 for ( String key : extensions.keySet() )
794 {
795 sb.append( key ).append( " " );
796
797 List<String> values = extensions.get( key );
798
799 if ( ( values != null ) && ( values.size() != 0 ) )
800 {
801 if ( values.size() == 1 )
802 {
803 sb.append( values.get( 0 ) );
804 }
805 else
806 {
807 boolean isFirst = true;
808 sb.append( "( " );
809
810 for ( String value : values )
811 {
812 if ( isFirst )
813 {
814 isFirst = false;
815 }
816 else
817 {
818 sb.append( " " );
819 }
820
821 sb.append( value );
822 }
823
824 sb.append( " )" );
825 }
826 }
827
828 sb.append( '\n' );
829 }
830 }
831
832
833 private static void getQDStrings( StringBuilder sb, List<? extends SchemaObject> schemaObjects )
834 {
835 if ( ( schemaObjects != null ) && ( schemaObjects.size() != 0 ) )
836 {
837 if ( schemaObjects.size() == 1 )
838 {
839 sb.append( '\'' ).append( schemaObjects.get( 0 ).getName() ).append( '\'' );
840 }
841 else
842 {
843 boolean isFirst = true;
844 sb.append( "( " );
845
846 for ( SchemaObject schemaObject : schemaObjects )
847 {
848 if ( isFirst )
849 {
850 isFirst = false;
851 }
852 else
853 {
854 sb.append( " " );
855 }
856
857 sb.append( '\'' ).append( schemaObject.getName() ).append( '\'' );
858 }
859
860 sb.append( " )" );
861 }
862 }
863
864 sb.append( '\n' );
865 }
866
867
868 private static void getQDescrs( StringBuilder sb, List<String> names )
869 {
870 if ( ( names != null ) && ( names.size() != 0 ) )
871 {
872 if ( names.size() == 1 )
873 {
874 sb.append( '\'' ).append( names.get( 0 ) ).append( '\'' );
875 }
876 else
877 {
878 boolean isFirst = true;
879 sb.append( "( " );
880
881 for ( String name : names )
882 {
883 if ( isFirst )
884 {
885 isFirst = false;
886 }
887 else
888 {
889 sb.append( " " );
890 }
891
892 sb.append( '\'' ).append( name ).append( '\'' );
893 }
894
895 sb.append( " )" );
896 }
897 }
898
899 sb.append( '\n' );
900 }
901
902
903 /**
904 * Generate the description for Comparators, Normalizers and SyntaxCheckers.
905 */
906 private static String getLoadableDescription( LoadableSchemaObject schemaObject )
907 {
908 StringBuilder buf = new StringBuilder( "( " );
909 buf.append( schemaObject.getOid() );
910 buf.append( '\n' );
911
912 if ( schemaObject.getDescription() != null )
913 {
914 buf.append( " DESC " );
915 buf.append( schemaObject.getDescription() );
916 buf.append( '\n' );
917 }
918
919 if ( schemaObject.getFqcn() != null )
920 {
921 buf.append( " FQCN " );
922 buf.append( schemaObject.getFqcn() );
923 buf.append( '\n' );
924 }
925
926 if ( schemaObject.getBytecode() != null )
927 {
928 buf.append( " BYTECODE " );
929
930 // We will dump only the 16 first bytes
931 if ( schemaObject.getBytecode().length() > 16 )
932 {
933 buf.append( schemaObject.getBytecode().substring( 0, 16 ) );
934 }
935 else
936 {
937 buf.append( schemaObject.getBytecode() );
938 }
939
940 buf.append( '\n' );
941 }
942
943 if ( schemaObject.getExtensions() != null )
944 {
945 getExtensions( buf, schemaObject.getExtensions() );
946 }
947
948 buf.append( " ) " );
949
950 return buf.toString();
951 }
952 }