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 javax.naming.NamingException;
024
025
026 /**
027 * Utility class used to generate schema object specifications. Some of the
028 * latest work coming out of the LDAPBIS working body adds optional extensions
029 * to these syntaxes. We have not yet added extension support to these functions
030 * or the schema interfaces in this package. 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="./MatchingRule.html">MatchingRule</a></li>
036 * <li><a href="./MatchingRuleUse.html">MatchingRuleUse</a></li>
037 * <li><a href="./NameForm.html">NameForm</a></li>
038 * <li><a href="./ObjectClass.html">ObjectClass</a></li>
039 * <li><a href="./DITStructureRule.html">DITStructureRule</a></li>
040 * <li><a href="./Syntax.html">Syntax</a></li>
041 * </ul>
042 *
043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
044 * @version $Rev: 664290 $
045 */
046 public class DescriptionUtils
047 {
048 /**
049 * Generates the description using the AttributeTypeDescription as defined
050 * by the syntax: 1.3.6.1.4.1.1466.115.121.1.3. Only the right hand side of
051 * the description starting at the openning parenthesis is generated: that
052 * is 'AttributeTypeDescription = ' is not generated.
053 *
054 * <pre>
055 * AttributeTypeDescription = "(" whsp
056 * numericoid whsp ; AttributeType identifier
057 * [ "NAME" qdescrs ] ; name used in AttributeType
058 * [ "DESC" qdstring ] ; description
059 * [ "OBSOLETE" whsp ]
060 * [ "SUP" woid ] ; derived from parent AttributeType
061 * [ "EQUALITY" woid ; Matching Rule name
062 * [ "ORDERING" woid ; Matching Rule name
063 * [ "SUBSTR" woid ] ; Matching Rule name
064 * [ "SYNTAX" whsp noidlen whsp ] ; see section 4.3 RFC 2252
065 * [ "SINGLE-VALUE" whsp ] ; default multi-valued
066 * [ "COLLECTIVE" whsp ] ; default not collective
067 * [ "NO-USER-MODIFICATION" whsp ]; default user modifiable
068 * [ "USAGE" whsp AttributeUsage ]; default userApplications
069 * whsp ")"
070 * </pre>
071 *
072 * @param attributeType
073 * the attributeType to generate a description for
074 * @return the AttributeTypeDescription Syntax for the attributeType in a
075 * pretty formated string
076 * @throws NamingException If an error is raised while accessing some of the attributeType
077 * data
078 */
079 public static String getDescription( AttributeType attributeType ) throws NamingException
080 {
081 StringBuffer buf = new StringBuffer( "( " );
082 buf.append( attributeType.getOid() );
083 buf.append( '\n' );
084
085 buf.append( "NAME " );
086 buf.append( attributeType.getName() );
087 buf.append( '\n' );
088
089 if ( attributeType.getDescription() != null )
090 {
091 buf.append( "DESC " );
092 buf.append( attributeType.getDescription() );
093 buf.append( '\n' );
094 }
095
096 if ( attributeType.isObsolete() )
097 {
098 buf.append( "OBSOLETE" );
099 buf.append( '\n' );
100 }
101
102 buf.append( attributeType.getSuperior().getOid() );
103
104 if ( attributeType.getEquality() != null )
105 {
106 buf.append( "EQUALITY " );
107 buf.append( attributeType.getEquality().getOid() );
108 buf.append( '\n' );
109 }
110
111 if ( attributeType.getOrdering() != null )
112 {
113 buf.append( "ORDERING " );
114 buf.append( attributeType.getOrdering().getOid() );
115 buf.append( '\n' );
116 }
117
118 if ( attributeType.getSubstr() != null )
119 {
120 buf.append( "SUBSTR " );
121 buf.append( attributeType.getSubstr().getOid() );
122 buf.append( '\n' );
123 }
124
125 buf.append( "SYNTAX " );
126 buf.append( attributeType.getSyntax().getOid() );
127 buf.append( '\n' );
128
129 if ( attributeType.isSingleValue() )
130 {
131 buf.append( "SINGLE-VALUE" );
132 buf.append( '\n' );
133 }
134
135 if ( attributeType.isCollective() )
136 {
137 buf.append( "COLLECTIVE" );
138 buf.append( '\n' );
139 }
140
141 if ( attributeType.isCanUserModify() )
142 {
143 buf.append( "NO-USER-MODIFICATION" );
144 buf.append( '\n' );
145 }
146
147 buf.append( "USAGE " );
148 buf.append( UsageEnum.render( attributeType.getUsage() ) );
149 buf.append( " ) " );
150
151 return buf.toString();
152 }
153
154
155 /**
156 * Generates the DITContentRuleDescription for a DITContentRule as defined
157 * by the syntax: 1.3.6.1.4.1.1466.115.121.1.16. Only the right hand side of
158 * the description starting at the openning parenthesis is generated: that
159 * is 'DITContentRuleDescription = ' is not generated.
160 *
161 * <pre>
162 * DITContentRuleDescription = "("
163 * numericoid ; Structural ObjectClass identifier
164 * [ "NAME" qdescrs ]
165 * [ "DESC" qdstring ]
166 * [ "OBSOLETE" ]
167 * [ "AUX" oids ] ; Auxiliary ObjectClasses
168 * [ "MUST" oids ] ; AttributeType identifiers
169 * [ "MAY" oids ] ; AttributeType identifiers
170 * [ "NOT" oids ] ; AttributeType identifiers
171 * ")"
172 * </pre>
173 *
174 * @param dITContentRule
175 * the DIT content rule specification
176 * @return the specification according to the DITContentRuleDescription
177 * syntax
178 * @throws NamingException If an error is raised while accessing some of the dITConentRule
179 * data
180 */
181 public static String getDescription( DITContentRule dITContentRule ) throws NamingException
182 {
183 StringBuffer buf = new StringBuffer( "( " );
184 buf.append( dITContentRule.getOid() );
185 buf.append( '\n' );
186
187 buf.append( "NAME " );
188 buf.append( dITContentRule.getName() );
189 buf.append( '\n' );
190
191 if ( dITContentRule.getDescription() != null )
192 {
193 buf.append( "DESC " );
194 buf.append( dITContentRule.getDescription() );
195 buf.append( '\n' );
196 }
197
198 if ( dITContentRule.isObsolete() )
199 {
200 buf.append( "OBSOLETE" );
201 buf.append( '\n' );
202 }
203
204 // print out all the auxiliary object class oids
205 ObjectClass[] aux = dITContentRule.getAuxObjectClasses();
206
207 if ( aux != null && aux.length > 0 )
208 {
209 buf.append( "AUX\n" );
210
211 for ( ObjectClass objectClass: aux )
212 {
213 buf.append( '\t' );
214 buf.append( objectClass.getOid() );
215 buf.append( '\n' );
216 }
217 }
218
219 AttributeType[] must = dITContentRule.getMustNames();
220
221 if ( must != null && must.length > 0 )
222 {
223 buf.append( "MUST\n" );
224
225 for ( AttributeType attributeType:must )
226 {
227 buf.append( '\t' );
228 buf.append( attributeType.getOid() );
229 buf.append( '\n' );
230 }
231 }
232
233 AttributeType[] may = dITContentRule.getMayNames();
234
235 if ( may != null && may.length > 0 )
236 {
237 buf.append( "MAY\n" );
238
239 for ( AttributeType attributeType:may )
240 {
241 buf.append( '\t' );
242 buf.append( attributeType.getOid() );
243 buf.append( '\n' );
244 }
245 }
246
247 AttributeType[] not = dITContentRule.getNotNames();
248
249 if ( not != null && not.length > 0 )
250 {
251 buf.append( "NOT\n" );
252
253 for ( AttributeType attributeType:not )
254 {
255 buf.append( '\t' );
256 buf.append( attributeType.getOid() );
257 buf.append( '\n' );
258 }
259 }
260
261 buf.append( " )" );
262 return buf.toString();
263 }
264
265
266 /**
267 * Generates the MatchingRuleDescription for a MatchingRule as defined by
268 * the syntax: 1.3.6.1.4.1.1466.115.121.1.30. Only the right hand side of
269 * the description starting at the openning parenthesis is generated: that
270 * is 'MatchingRuleDescription = ' is not generated.
271 *
272 * <pre>
273 * MatchingRuleDescription = "(" whsp
274 * numericoid whsp ; MatchingRule object identifier
275 * [ "NAME" qdescrs ]
276 * [ "DESC" qdstring ]
277 * [ "OBSOLETE" whsp ]
278 * "SYNTAX" numericoid
279 * whsp ")"
280 * </pre>
281 *
282 * @param matchingRule
283 * the MatchingRule to generate the description for
284 * @return the MatchingRuleDescription string
285 * @throws NamingException If an error is raised while accessing some of the matchingRule
286 * data
287 */
288 public static String getDescription( MatchingRule matchingRule ) throws NamingException
289 {
290 StringBuffer buf = new StringBuffer( "( " );
291 buf.append( matchingRule.getOid() );
292 buf.append( '\n' );
293
294 buf.append( "NAME " );
295 buf.append( matchingRule.getName() );
296 buf.append( '\n' );
297
298 if ( matchingRule.getDescription() != null )
299 {
300 buf.append( "DESC " );
301 buf.append( matchingRule.getDescription() );
302 buf.append( '\n' );
303 }
304
305 if ( matchingRule.isObsolete() )
306 {
307 buf.append( "OBSOLETE" );
308 buf.append( '\n' );
309 }
310
311 buf.append( "SYNTAX " );
312 buf.append( matchingRule.getSyntax().getOid() );
313 buf.append( " ) " );
314 return buf.toString();
315 }
316
317
318 /**
319 * Generates the MatchingRuleUseDescription for a MatchingRuleUse as defined
320 * by the syntax: 1.3.6.1.4.1.1466.115.121.1.31. Only the right hand side of
321 * the description starting at the openning parenthesis is generated: that
322 * is 'MatchingRuleUseDescription = ' is not generated.
323 *
324 * <pre>
325 * MatchingRuleUseDescription = LPAREN WSP
326 * numericoid ; object identifier
327 * [ SP "NAME" SP qdescrs ] ; short names (descriptors)
328 * [ SP "DESC" SP qdstring ] ; description
329 * [ SP "OBSOLETE" ] ; not active
330 * SP "APPLIES" SP oids ; attribute types
331 * extensions WSP RPAREN ; extensions
332 *
333 * where:
334 * [numericoid] is the object identifier of the matching rule
335 * associated with this matching rule use description;
336 * NAME [qdescrs] are short names (descriptors) identifying this
337 * matching rule use;
338 * DESC [qdstring] is a short descriptive string;
339 * OBSOLETE indicates this matching rule use is not active;
340 * APPLIES provides a list of attribute types the matching rule applies
341 * to; and
342 * [extensions] describe extensions.
343 * </pre>
344 *
345 * @param matchingRuleUse The matching rule from which we want to generate
346 * a MatchingRuleUseDescription.
347 * @return The generated MatchingRuleUseDescription
348 * @throws NamingException If an error is raised while accessing some of the matchingRuleUse
349 * data
350 */
351 public static String getDescription( MatchingRuleUse matchingRuleUse ) throws NamingException
352 {
353 StringBuffer buf = new StringBuffer( "( " );
354 buf.append( matchingRuleUse.getMatchingRule().getOid() );
355 buf.append( '\n' );
356
357 buf.append( "NAME " );
358 buf.append( matchingRuleUse.getName() );
359 buf.append( '\n' );
360
361 if ( matchingRuleUse.getDescription() != null )
362 {
363 buf.append( "DESC " );
364 buf.append( matchingRuleUse.getDescription() );
365 buf.append( '\n' );
366 }
367
368 if ( matchingRuleUse.isObsolete() )
369 {
370 buf.append( "OBSOLETE" );
371 buf.append( '\n' );
372 }
373
374 buf.append( "APPLIES " );
375 AttributeType[] attributeTypes = matchingRuleUse.getApplicableAttributes();
376 if ( attributeTypes.length == 1 )
377 {
378 buf.append( attributeTypes[0].getOid() );
379 }
380 else
381 // for list of oids we need a parenthesis
382 {
383 buf.append( "( " );
384 buf.append( attributeTypes[0] );
385 for ( int ii = 1; ii < attributeTypes.length; ii++ )
386 {
387 buf.append( " $ " );
388 buf.append( attributeTypes[ii] );
389 }
390 buf.append( " ) " );
391 }
392
393 buf.append( '\n' );
394 return buf.toString();
395 }
396
397
398 /**
399 * Generates the NameFormDescription for a NameForm as defined by the
400 * syntax: 1.3.6.1.4.1.1466.115.121.1.35. Only the right hand side of the
401 * description starting at the openning parenthesis is generated: that is
402 * 'NameFormDescription = ' is not generated.
403 *
404 * <pre>
405 * NameFormDescription = "(" whsp
406 * numericoid whsp ; NameForm identifier
407 * [ "NAME" qdescrs ]
408 * [ "DESC" qdstring ]
409 * [ "OBSOLETE" whsp ]
410 * "OC" woid ; Structural ObjectClass
411 * "MUST" oids ; AttributeTypes
412 * [ "MAY" oids ] ; AttributeTypes
413 * whsp ")"
414 * </pre>
415 *
416 * @param nameForm
417 * the NameForm to generate the description for
418 * @return the NameFormDescription string
419 * @throws NamingException If an error is raised while accessing some of the nameForm
420 * data
421 */
422 public static String getDescription( NameForm nameForm ) throws NamingException
423 {
424 StringBuffer buf = new StringBuffer( "( " );
425 buf.append( nameForm.getOid() );
426 buf.append( '\n' );
427
428 buf.append( "NAME " );
429 buf.append( nameForm.getName() );
430 buf.append( '\n' );
431
432 if ( nameForm.getDescription() != null )
433 {
434 buf.append( "DESC " );
435 buf.append( nameForm.getDescription() );
436 buf.append( '\n' );
437 }
438
439 if ( nameForm.isObsolete() )
440 {
441 buf.append( "OBSOLETE" );
442 buf.append( '\n' );
443 }
444
445 buf.append( "OC " );
446 buf.append( nameForm.getObjectClass().getOid() );
447 buf.append( '\n' );
448
449 buf.append( "MUST\n" );
450 AttributeType[] must = nameForm.getMustUse();
451
452 for ( AttributeType attributeType:must )
453 {
454 buf.append( '\t' );
455 buf.append( attributeType.getOid() );
456 buf.append( '\n' );
457 }
458
459 AttributeType[] may = nameForm.getMayUse();
460
461 if ( may != null && may.length > 0 )
462 {
463 buf.append( "MAY\n" );
464
465 for ( AttributeType attributeType:may )
466 {
467 buf.append( '\t' );
468 buf.append( attributeType.getOid() );
469 buf.append( '\n' );
470 }
471 }
472
473 buf.append( " )" );
474 return buf.toString();
475 }
476
477
478 /**
479 * Generates the ObjectClassDescription for an ObjectClass as defined by the
480 * syntax: 1.3.6.1.4.1.1466.115.121.1.37. Only the right hand side of the
481 * description starting at the openning parenthesis is generated: that is
482 * 'ObjectClassDescription = ' is not generated.
483 *
484 * <pre>
485 * ObjectClassDescription = "(" whsp
486 * numericoid whsp ; ObjectClass identifier
487 * [ "NAME" qdescrs ]
488 * [ "DESC" qdstring ]
489 * [ "OBSOLETE" whsp ]
490 * [ "SUP" oids ] ; Superior ObjectClasses
491 * [ ( "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" ) whsp ]
492 * ; default structural
493 * [ "MUST" oids ] ; AttributeTypes
494 * [ "MAY" oids ] ; AttributeTypes
495 * whsp ")"
496 * </pre>
497 *
498 * @param objectClass
499 * the ObjectClass to generate a description for
500 * @return the description in the ObjectClassDescription syntax
501 * @throws NamingException If an error is raised while accessing some of the objectClass
502 * data
503 */
504 public static String getDescription( ObjectClass objectClass ) throws NamingException
505 {
506 StringBuffer buf = new StringBuffer( "( " );
507 buf.append( objectClass.getOid() );
508 buf.append( '\n' );
509
510 buf.append( "NAME " );
511 buf.append( objectClass.getName() );
512 buf.append( '\n' );
513
514 if ( objectClass.getDescription() != null )
515 {
516 buf.append( "DESC " );
517 buf.append( objectClass.getDescription() );
518 buf.append( '\n' );
519 }
520
521 if ( objectClass.isObsolete() )
522 {
523 buf.append( "OBSOLETE" );
524 buf.append( '\n' );
525 }
526
527 ObjectClass[] sups = objectClass.getSuperClasses();
528
529 if ( sups != null && sups.length > 0 )
530 {
531 buf.append( "SUP\n" );
532
533 for ( ObjectClass sup:sups )
534 {
535 buf.append( '\t' );
536 buf.append( sup.getOid() );
537 buf.append( '\n' );
538 }
539 }
540
541 if ( objectClass.getType() != null )
542 {
543 buf.append( objectClass.getType() );
544 buf.append( '\n' );
545 }
546
547 AttributeType[] must = objectClass.getMustList();
548 if ( must != null && must.length > 0 )
549 {
550 buf.append( "MUST\n" );
551
552 for ( AttributeType attributeType:must )
553 {
554 buf.append( '\t' );
555 buf.append( attributeType.getOid() );
556 buf.append( '\n' );
557 }
558 }
559
560 AttributeType[] may = objectClass.getMayList();
561
562 if ( may != null && may.length > 0 )
563 {
564 buf.append( "MAY\n" );
565
566 for ( AttributeType attributeType:may )
567 {
568 buf.append( '\t' );
569 buf.append( attributeType.getOid() );
570 buf.append( '\n' );
571 }
572 }
573
574 buf.append( " )" );
575 return buf.toString();
576 }
577
578
579 /**
580 * Generates the DITStructureRuleDescription for a DITStructureRule as
581 * defined by the syntax: 1.3.6.1.4.1.1466.115.121.1.17. Only the right hand
582 * side of the description starting at the openning parenthesis is
583 * generated: that is 'DITStructureRuleDescription = ' is not generated.
584 *
585 * <pre>
586 * DITStructureRuleDescription = "(" whsp
587 * ruleidentifier whsp ; DITStructureRule identifier
588 * [ "NAME" qdescrs ]
589 * [ "DESC" qdstring ]
590 * [ "OBSOLETE" whsp ]
591 * "FORM" woid whsp ; NameForm
592 * [ "SUP" ruleidentifiers whsp ]; superior DITStructureRules
593 * ")"
594 * </pre>
595 *
596 * @param dITStructureRule
597 * the DITStructureRule to generate the description for
598 * @return the description in the DITStructureRuleDescription syntax
599 * @throws NamingException If an error is raised while accessing some of the dITStructureRule
600 * data
601 */
602 public static String getDescription( DITStructureRule dITStructureRule ) throws NamingException
603 {
604 StringBuffer buf = new StringBuffer( "( " );
605 buf.append( dITStructureRule.getOid() );
606 buf.append( '\n' );
607
608 buf.append( "NAME " );
609 buf.append( dITStructureRule.getName() );
610 buf.append( '\n' );
611
612 if ( dITStructureRule.getDescription() != null )
613 {
614 buf.append( "DESC " );
615 buf.append( dITStructureRule.getDescription() );
616 buf.append( '\n' );
617 }
618
619 if ( dITStructureRule.isObsolete() )
620 {
621 buf.append( "OBSOLETE" );
622 buf.append( '\n' );
623 }
624
625 buf.append( "FORM " );
626 buf.append( dITStructureRule.getNameForm().getOid() );
627 buf.append( '\n' );
628
629 DITStructureRule[] sups = dITStructureRule.getSuperClasses();
630 if ( sups != null && sups.length > 0 )
631 {
632 buf.append( "SUP\n" );
633
634 for ( DITStructureRule sup:sups )
635 {
636 buf.append( '\t' );
637 buf.append( sup.getOid() );
638 buf.append( '\n' );
639 }
640 }
641
642 buf.append( " )" );
643 return buf.toString();
644 }
645
646
647 /**
648 * Generates the SyntaxDescription for a Syntax as defined by the syntax:
649 * 1.3.6.1.4.1.1466.115.121.1.54. Only the right hand side of the
650 * description starting at the openning parenthesis is generated: that is
651 * 'SyntaxDescription = ' is not generated.
652 *
653 * <pre>
654 * SyntaxDescription = "(" whsp
655 * numericoid whsp
656 * [ "DESC" qdstring ]
657 * whsp ")"
658 * </pre>
659 *
660 * @param syntax
661 * the Syntax to generate a description for
662 * @return the description in the SyntaxDescription syntax
663 */
664 public static String getDescription( Syntax syntax )
665 {
666 StringBuffer buf = new StringBuffer( "( " );
667 buf.append( syntax.getOid() );
668 buf.append( '\n' );
669
670 if ( syntax.getDescription() != null )
671 {
672 buf.append( "DESC " );
673 buf.append( syntax.getDescription() );
674 buf.append( '\n' );
675 }
676
677 buf.append( " )" );
678 return buf.toString();
679 }
680 }