You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2006/12/17 20:51:57 UTC

svn commit: r488033 - in /directory/trunks/shared/ldap/src: main/antlr/ main/java/org/apache/directory/shared/ldap/schema/syntax/ test/java/org/apache/directory/shared/ldap/schema/syntax/

Author: ersiner
Date: Sun Dec 17 11:51:56 2006
New Revision: 488033

URL: http://svn.apache.org/viewvc?view=rev&rev=488033
Log:
Applied Stefan Seelmann latest patch for DIRSERVER-793.

Modified:
    directory/trunks/shared/ldap/src/main/antlr/schema-value.g
    directory/trunks/shared/ldap/src/main/antlr/schema.g
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java
    directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserAttributeTypeDescriptionTest.java
    directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserLdapSyntaxDescriptionTest.java
    directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleDescriptionTest.java
    directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleUseDescriptionTest.java
    directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserObjectClassDescriptionTest.java
    directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserTestUtils.java

Modified: directory/trunks/shared/ldap/src/main/antlr/schema-value.g
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/antlr/schema-value.g?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/main/antlr/schema-value.g (original)
+++ directory/trunks/shared/ldap/src/main/antlr/schema-value.g Sun Dec 17 11:51:56 2006
@@ -49,15 +49,20 @@
 protected LDIGIT : '1'..'9' ;
 protected DIGIT : '0'..'9' ; 
 protected NUMBER : DIGIT | ( LDIGIT (DIGIT)+ ) ;
+protected NUMERICOID : NUMBER ( '.' NUMBER )+ ;
 
 QUOTE : '\'' ;
 DOLLAR : '$' ;
 LCURLY : '{' ;
 RCURLY : '}' ;
-NUMERICOID : NUMBER ( '.' NUMBER )+ ;
 DESCR : ( 'a'..'z' | 'A'..'Z' ) ( 'a'..'z' | 'A'..'Z' | '0'..'9' | '-' )* ;
 LEN : LCURLY n:NUMBER RCURLY { setText(n.getText()); } ;
 
+NUMBER_OR_NUMERICOID :
+    ( NUMBER '.' ) => NUMERICOID { $setType( NUMERICOID ); }
+    |
+    ( NUMBER ) { $setType( NUMBER ); }
+    ;
 
 /**
  * An antlr generated schema parser. This is a sub-parser used to parse
@@ -194,3 +199,45 @@
     )
     ;
     
+    /**
+     * ruleid = number
+     * number  = DIGIT / ( LDIGIT 1*DIGIT )
+     *
+     */
+ruleid returns [Integer ruleid=null]
+    : 
+    (
+        (SP)? 
+        n:NUMBER { ruleid = Integer.parseInt(n.getText()); }
+    )
+    ;
+
+
+    /**
+     * ruleids = ruleid / ( LPAREN WSP ruleidlist WSP RPAREN )
+     * ruleidlist = ruleid *( SP ruleid )
+     */
+ruleids returns [List<Integer> ruleids]
+    {
+        ruleids = new ArrayList<Integer>();
+        Integer ruleid = null;
+    }
+    :
+    (
+        ( 
+        	ruleid=ruleid { ruleids.add(ruleid); } 
+    	)
+    |
+        ( 
+        	LPAR 
+        	ruleid=ruleid { ruleids.add(ruleid); } 
+        	( 
+        		SP
+        		ruleid=ruleid { ruleids.add(ruleid); } 
+        	)* 
+        	(SP)?
+        	RPAR 
+        )
+    )
+    ;
+    
\ No newline at end of file

Modified: directory/trunks/shared/ldap/src/main/antlr/schema.g
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/antlr/schema.g?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/main/antlr/schema.g (original)
+++ directory/trunks/shared/ldap/src/main/antlr/schema.g Sun Dec 17 11:51:56 2006
@@ -69,6 +69,10 @@
 SUP : ( "SUP" WHSP sup:VALUES ) { setText(sup.getText().trim()); } ;
 MUST : ( "MUST" WHSP must:VALUES ) { setText(must.getText().trim()); } ;
 MAY : ( "MAY" WHSP may:VALUES ) { setText(may.getText()); } ;
+AUX : ( "AUX" WHSP aux:VALUES ) { setText(aux.getText()); } ;
+NOT : ( "NOT" WHSP not:VALUES ) { setText(not.getText()); } ;
+FORM : ( "FORM" WHSP form:VALUES ) { setText(form.getText()); } ;
+OC : ( "OC" WHSP oc:VALUES ) { setText(oc.getText()); } ;
 EQUALITY : ( "EQUALITY" WHSP equality:VALUES ) { setText(equality.getText().trim()); } ;
 ORDERING : ( "ORDERING" WHSP ordering:VALUES ) { setText(ordering.getText().trim()); } ;
 SUBSTR : ( "SUBSTR" WHSP substr:VALUES ) { setText(substr.getText().trim()); } ;
@@ -116,6 +120,23 @@
 	    String noid = "";
 	    int len = 0;
 	}
+    static class ElementTracker
+	{
+	    Map<String, Integer> elementMap = new HashMap<String, Integer>();
+	    void track(String element, Token token) throws SemanticException 
+	    {
+	        if(elementMap.containsKey(element))
+	        {
+	            throw new SemanticException( element + " appears twice.", token.getFilename(), token.getLine() , token.getColumn() );
+	        }
+	        elementMap.put(element, new Integer(1));
+	    }
+	    boolean contains(String element) 
+	    {
+	        return elementMap.containsKey(element);
+	    }
+	}
+
 }
 
 
@@ -142,30 +163,34 @@
      * </pre>
     */
 objectClassDescription returns [ObjectClassDescription ocd = new ObjectClassDescription()]
+    {
+        ElementTracker et = new ElementTracker();
+    }
     :
     ( oid:STARTNUMERICOID { ocd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { ocd.setNames(qdescrs(name.getText())); } )
+	    ( name:NAME { et.track("NAME", name); ocd.setNames(qdescrs(name.getText())); } )
 	    |
-	    ( desc:DESC { ocd.setDescription(qdstring(desc.getText())); } )
+	    ( desc:DESC { et.track("DESC", desc); ocd.setDescription(qdstring(desc.getText())); } )
 	    |
-	    ( OBSOLETE { ocd.setObsolete( true ); } )
+	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); ocd.setObsolete( true ); } )
 	    |
-	    ( sup:SUP { ocd.setSuperiorObjectClasses(oids(sup.getText())); } )
+	    ( sup:SUP { et.track("SUP", sup); ocd.setSuperiorObjectClasses(oids(sup.getText())); } )
 	    |
-	    ( ABSTRACT { ocd.setKind( ObjectClassTypeEnum.ABSTRACT ); }
+	    ( kind1:ABSTRACT { et.track("KIND", kind1); ocd.setKind( ObjectClassTypeEnum.ABSTRACT ); }
 	      |
-	      STRUCTURAL { ocd.setKind( ObjectClassTypeEnum.STRUCTURAL ); }
+	      kind2:STRUCTURAL { et.track("KIND", kind2); ocd.setKind( ObjectClassTypeEnum.STRUCTURAL ); }
 	      |
-	      AUXILIARY { ocd.setKind( ObjectClassTypeEnum.AUXILIARY ); } 
+	      kind3:AUXILIARY { et.track("KIND", kind3); ocd.setKind( ObjectClassTypeEnum.AUXILIARY ); } 
 	    )
 	    |
-	    ( must:MUST { ocd.setMustAttributeTypes(oids(must.getText())); } )
+	    ( must:MUST { et.track("MUST", must); ocd.setMustAttributeTypes(oids(must.getText())); } )
 	    |
-	    ( may:MAY { ocd.setMayAttributeTypes(oids(may.getText())); } )
+	    ( may:MAY { et.track("MAY", may); ocd.setMayAttributeTypes(oids(may.getText())); } )
 	    |
 	    ( extension:EXTENSION { 
 	        Extension ex = extension(extension.getText());
+	        et.track(ex.key, extension); 
 	        ocd.addExtension(ex.key, ex.values); 
 	     } )
 	)*    
@@ -204,50 +229,74 @@
      * </pre>
     */
 attributeTypeDescription returns [AttributeTypeDescription atd = new AttributeTypeDescription()]
+    {
+        ElementTracker et = new ElementTracker();
+    }
     :
     ( oid:STARTNUMERICOID { atd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { atd.setNames(qdescrs(name.getText())); } )
+	    ( name:NAME { et.track("NAME", name); atd.setNames(qdescrs(name.getText())); } )
 	    |
-	    ( desc:DESC { atd.setDescription(qdstring(desc.getText())); } )
+	    ( desc:DESC { et.track("DESC", desc); atd.setDescription(qdstring(desc.getText())); } )
 	    |
-	    ( OBSOLETE { atd.setObsolete( true ); } )
+	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); atd.setObsolete( true ); } )
 	    |
-	    ( sup:SUP { atd.setSuperType(oid(sup.getText())); } )
+	    ( sup:SUP { et.track("SUP", sup); atd.setSuperType(oid(sup.getText())); } )
 	    |
-        ( equality:EQUALITY { atd.setEqualityMatchingRule(oid(equality.getText())); } )
+        ( equality:EQUALITY { et.track("EQUALITY", equality); atd.setEqualityMatchingRule(oid(equality.getText())); } )
         |
-        ( ordering:ORDERING { atd.setOrderingMatchingRule(oid(ordering.getText())); } )
+        ( ordering:ORDERING { et.track("ORDERING", ordering); atd.setOrderingMatchingRule(oid(ordering.getText())); } )
         |
-        ( substr:SUBSTR { atd.setSubstringsMatchingRule(oid(substr.getText())); } )
+        ( substr:SUBSTR { et.track("SUBSTR", substr); atd.setSubstringsMatchingRule(oid(substr.getText())); } )
         |
         ( syntax:SYNTAX { 
+           et.track("SYNTAX", syntax); 
             NoidLen noidlen = noidlen(syntax.getText());
             atd.setSyntax(noidlen.noid); 
             atd.setSyntaxLength(noidlen.len);
           } )
         |
-        ( SINGLE_VALUE { atd.setSingleValued( true ); } )
+        ( singleValue:SINGLE_VALUE { et.track("SINGLE_VALUE", singleValue); atd.setSingleValued( true ); } )
         |
-        ( COLLECTIVE { atd.setCollective( true ); } )
+        ( collective:COLLECTIVE { et.track("COLLECTIVE", collective); atd.setCollective( true ); } )
         |
-        ( NO_USER_MODIFICATION { atd.setUserModifiable( false ); } )
+        ( noUserModification:NO_USER_MODIFICATION { et.track("NO_USER_MODIFICATION", noUserModification); atd.setUserModifiable( false ); } )
         |
-	    ( USAGE (WHSP)* USER_APPLICATIONS { atd.setUsage( UsageEnum.USER_APPLICATIONS ); }
+	    ( usage1:USAGE (WHSP)* USER_APPLICATIONS { et.track("USAGE", usage1); atd.setUsage( UsageEnum.USER_APPLICATIONS ); }
 	      |
-	      USAGE DIRECTORY_OPERATION { atd.setUsage( UsageEnum.DIRECTORY_OPERATION ); }
+	      usage2:USAGE DIRECTORY_OPERATION { et.track("USAGE", usage2); atd.setUsage( UsageEnum.DIRECTORY_OPERATION ); }
 	      |
-	      USAGE DISTRIBUTED_OPERATION { atd.setUsage( UsageEnum.DISTRIBUTED_OPERATION ); } 
+	      usage3:USAGE DISTRIBUTED_OPERATION { et.track("USAGE", usage3); atd.setUsage( UsageEnum.DISTRIBUTED_OPERATION ); } 
 	      |
-	      USAGE DSA_OPERATION { atd.setUsage( UsageEnum.DSA_OPERATION ); } 
+	      usage4:USAGE DSA_OPERATION { et.track("USAGE", usage4); atd.setUsage( UsageEnum.DSA_OPERATION ); } 
 	    )
 	    |
 	    ( extension:EXTENSION { 
 	        Extension ex = extension(extension.getText());
+	        et.track(ex.key, extension); 
 	        atd.addExtension(ex.key, ex.values); 
 	     } )
 	)*    
     RPAR
+    {
+        // semantic check: required elements
+        if( !et.contains("SYNTAX") && !et.contains("SUP") ) 
+        {
+            throw new SemanticException( "One of SYNTAX or SUP is required", null, 0, 0 );
+        }
+        
+        // COLLECTIVE requires USAGE userApplications
+        if ( atd.isCollective() && ( atd.getUsage() != UsageEnum.USER_APPLICATIONS ) )
+        {
+            throw new SemanticException( "COLLECTIVE requires USAGE userApplications", null, 0, 0 );
+        }
+        
+        // NO-USER-MODIFICATION requires an operational USAGE.
+        if ( !atd.isUserModifiable() && ( atd.getUsage() == UsageEnum.USER_APPLICATIONS ) )
+        {
+            throw new SemanticException( "NO-USER-MODIFICATION requires an operational USAGE", null, 0, 0 );
+        }
+    }
     ;
 
 
@@ -263,13 +312,17 @@
      * </pre>
     */
 ldapSyntaxDescription returns [LdapSyntaxDescription lsd = new LdapSyntaxDescription()]
-     :
+    {
+        ElementTracker et = new ElementTracker();
+    }
+    :
     ( oid:STARTNUMERICOID { lsd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( desc:DESC { lsd.setDescription(qdstring(desc.getText())); } )
+	    ( desc:DESC { et.track("DESC", desc); lsd.setDescription(qdstring(desc.getText())); } )
 	    |
 	    ( extension:EXTENSION { 
 	        Extension ex = extension(extension.getText());
+	        et.track(ex.key, extension); 
 	        lsd.addExtension(ex.key, ex.values); 
 	     } )
     )*
@@ -293,23 +346,33 @@
      * </pre>
     */
 matchingRuleDescription returns [MatchingRuleDescription mrd = new MatchingRuleDescription()]
-     :
+    {
+        ElementTracker et = new ElementTracker();
+    }
+    :
     ( oid:STARTNUMERICOID { mrd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { mrd.setNames(qdescrs(name.getText())); } )
+	    ( name:NAME { et.track("NAME", name); mrd.setNames(qdescrs(name.getText())); } )
 	    |
-	    ( desc:DESC { mrd.setDescription(qdstring(desc.getText())); } )
+	    ( desc:DESC { et.track("DESC", desc); mrd.setDescription(qdstring(desc.getText())); } )
 	    |
-	    ( OBSOLETE { mrd.setObsolete( true ); } )
+	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); mrd.setObsolete( true ); } )
 	    |
-        ( syntax:SYNTAX { mrd.setSyntax(numericoid(syntax.getText())); } )
+        ( syntax:SYNTAX { et.track("SYNTAX", syntax); mrd.setSyntax(numericoid(syntax.getText())); } )
 	    |
 	    ( extension:EXTENSION { 
 	        Extension ex = extension(extension.getText());
+	        et.track(ex.key, extension); 
 	        mrd.addExtension(ex.key, ex.values); 
 	     } )
     )*
     RPAR
+    {
+        // semantic check: required elements
+        if( !et.contains("SYNTAX") ) {
+            throw new SemanticException( "SYNTAX is required", null, 0, 0 );
+        }
+    }
     ;
 
 
@@ -328,26 +391,198 @@
      * </pre>
     */
 matchingRuleUseDescription returns [MatchingRuleUseDescription mrud = new MatchingRuleUseDescription()]
-     :
+    {
+        ElementTracker et = new ElementTracker();
+    }
+    :
     ( oid:STARTNUMERICOID { mrud.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { mrud.setNames(qdescrs(name.getText())); } )
+	    ( name:NAME { et.track("NAME", name); mrud.setNames(qdescrs(name.getText())); } )
 	    |
-	    ( desc:DESC { mrud.setDescription(qdstring(desc.getText())); } )
+	    ( desc:DESC { et.track("DESC", desc); mrud.setDescription(qdstring(desc.getText())); } )
 	    |
-	    ( OBSOLETE { mrud.setObsolete( true ); } )
+	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); mrud.setObsolete( true ); } )
 	    |
-        ( applies:APPLIES { mrud.setApplicableAttributes(oids(applies.getText())); } )
+        ( applies:APPLIES { et.track("APPLIES", applies); mrud.setApplicableAttributes(oids(applies.getText())); } )
 	    |
 	    ( extension:EXTENSION { 
 	        Extension ex = extension(extension.getText());
+	        et.track(ex.key, extension); 
 	        mrud.addExtension(ex.key, ex.values); 
 	     } )
     )*
     RPAR
+    {
+        // semantic check: required elements
+        if( !et.contains("APPLIES") ) {
+            throw new SemanticException( "APPLIES is required", null, 0, 0 );
+        }
+    }
+    ;
+
+
+    /**
+     * Production for DIT content rule descriptions. It is fault-tolerant
+     * against element ordering.
+     *
+     * <pre>
+     * DITContentRuleDescription = LPAREN WSP
+     *    numericoid                 ; object identifier
+     *    [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
+     *    [ SP "DESC" SP qdstring ]  ; description
+     *    [ SP "OBSOLETE" ]          ; not active
+     *    [ SP "AUX" SP oids ]       ; auxiliary object classes
+     *    [ SP "MUST" SP oids ]      ; attribute types
+     *    [ SP "MAY" SP oids ]       ; attribute types
+     *    [ SP "NOT" SP oids ]       ; attribute types
+     *    extensions WSP RPAREN      ; extensions
+     * </pre>
+    */
+ditContentRuleDescription returns [DITContentRuleDescription dcrd = new DITContentRuleDescription()]
+    {
+        ElementTracker et = new ElementTracker();
+    }
+    :
+    ( oid:STARTNUMERICOID { dcrd.setNumericOid(numericoid(oid.getText())); } )
+    (
+	    ( name:NAME { et.track("NAME", name); dcrd.setNames(qdescrs(name.getText())); } )
+	    |
+	    ( desc:DESC { et.track("DESC", desc); dcrd.setDescription(qdstring(desc.getText())); } )
+	    |
+	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); dcrd.setObsolete( true ); } )
+	    |
+	    ( aux:AUX { et.track("AUX", aux); dcrd.setAuxiliaryObjectClasses(oids(aux.getText())); } )
+	    |
+	    ( must:MUST { et.track("MUST", must); dcrd.setMustAttributeTypes(oids(must.getText())); } )
+	    |
+	    ( may:MAY { et.track("MAY", may); dcrd.setMayAttributeTypes(oids(may.getText())); } )
+	    |
+	    ( not:NOT { et.track("NOT", not); dcrd.setNotAttributeTypes(oids(not.getText())); } )
+	    |
+	    ( extension:EXTENSION { 
+	        Extension ex = extension(extension.getText());
+	        et.track(ex.key, extension); 
+	        dcrd.addExtension(ex.key, ex.values); 
+	     } )
+    )*
+    RPAR
+    ;
+
+
+    /**
+     * Production for DIT structure rules descriptions. It is fault-tolerant
+     * against element ordering.
+     *
+     * <pre>
+     * DITStructureRuleDescription = LPAREN WSP
+     *   ruleid                     ; rule identifier
+     *   [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
+     *   [ SP "DESC" SP qdstring ]  ; description
+     *   [ SP "OBSOLETE" ]          ; not active
+     *   SP "FORM" SP oid           ; NameForm
+     *   [ SP "SUP" ruleids ]       ; superior rules
+     *   extensions WSP RPAREN      ; extensions
+     *
+     * ruleids = ruleid / ( LPAREN WSP ruleidlist WSP RPAREN )
+     * ruleidlist = ruleid *( SP ruleid )
+     * ruleid = number
+     * </pre>
+    */
+ditStructureRuleDescription returns [DITStructureRuleDescription dsrd = new DITStructureRuleDescription()]
+    {
+        ElementTracker et = new ElementTracker();
+    }
+    :
+    ( ruleid:STARTNUMERICOID { dsrd.setRuleId(ruleid(ruleid.getText())); } )
+    (
+	    ( name:NAME { et.track("NAME", name); dsrd.setNames(qdescrs(name.getText())); } )
+	    |
+	    ( desc:DESC { et.track("DESC", desc); dsrd.setDescription(qdstring(desc.getText())); } )
+	    |
+	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); dsrd.setObsolete( true ); } )
+	    |
+	    ( form:FORM { et.track("FORM", form); dsrd.setForm(oid(form.getText())); } )
+	    |
+	    ( sup:SUP { et.track("SUP", sup); dsrd.setSuperRules(ruleids(sup.getText())); } )
+	    |
+	    ( extension:EXTENSION { 
+	        Extension ex = extension(extension.getText());
+	        et.track(ex.key, extension); 
+	        dsrd.addExtension(ex.key, ex.values); 
+	     } )
+    )*
+    RPAR
+    {
+        // semantic check: required elements
+        if( !et.contains("FORM") ) {
+            throw new SemanticException( "FORM is required", null, 0, 0 );
+        }
+    }
     ;
 
 
+    /**
+     * Production for name form descriptions. It is fault-tolerant
+     * against element ordering.
+     *
+     * <pre>
+     * NameFormDescription = LPAREN WSP
+     *    numericoid                 ; object identifier
+     *    [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
+     *    [ SP "DESC" SP qdstring ]  ; description
+     *    [ SP "OBSOLETE" ]          ; not active
+     *    SP "OC" SP oid             ; structural object class
+     *    SP "MUST" SP oids          ; attribute types
+     *    [ SP "MAY" SP oids ]       ; attribute types
+     *    extensions WSP RPAREN      ; extensions
+     * </pre>
+    */
+nameFormDescription returns [NameFormDescription nfd = new NameFormDescription()]
+    {
+        ElementTracker et = new ElementTracker();
+    }
+    :
+    ( oid:STARTNUMERICOID { nfd.setNumericOid(numericoid(oid.getText())); } )
+    (
+	    ( name:NAME { et.track("NAME", name); nfd.setNames(qdescrs(name.getText())); } )
+	    |
+	    ( desc:DESC { et.track("DESC", desc); nfd.setDescription(qdstring(desc.getText())); } )
+	    |
+	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); nfd.setObsolete( true ); } )
+	    |
+	    ( oc:OC { et.track("OC", oc); nfd.setStructuralObjectClass(oid(oc.getText())); } )
+	    |
+	    ( must:MUST { et.track("MUST", must); nfd.setMustAttributeTypes(oids(must.getText())); } )
+	    |
+	    ( may:MAY { et.track("MAY", may); nfd.setMayAttributeTypes(oids(may.getText())); } )
+	    |
+	    ( extension:EXTENSION { 
+	        Extension ex = extension(extension.getText());
+	        et.track(ex.key, extension); 
+	        nfd.addExtension(ex.key, ex.values); 
+	     } )
+    )*
+    RPAR
+    {
+        // semantic check: required elements
+        if( !et.contains("MUST") ) {
+            throw new SemanticException( "MUST is required", null, 0, 0 );
+        }
+        if( !et.contains("OC") ) {
+            throw new SemanticException( "OC is required", null, 0, 0 );
+        }
+        
+        // semantic check: MUST and MAY must be disjoint
+        //List<String> aList = new ArrayList<String>( nfd.getMustAttributeTypes() );
+        //aList.retainAll( nfd.getMayAttributeTypes() );
+        //if( !aList.isEmpty() ) 
+        //{
+        //    throw new SemanticException( "MUST and MAY must be disjoint, "+aList.get( 0 )+" appears in both", null, 0, 0 );
+        //}
+    }
+    ;
+    
+
 
 
 noidlen [String s] returns [NoidLen noidlen]
@@ -435,6 +670,23 @@
     :
     ;
 
-    
+ruleid [String s] returns [Integer ruleid]
+    {
+    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
+        AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
+        ruleid = parser.ruleid();
+    }
+    :
+    ;
+
+ruleids [String s] returns [List<Integer> ruleids]
+    {
+    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
+        AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
+        ruleids = parser.ruleids();
+    }
+    :
+    ;
+
 
     

Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java Sun Dec 17 11:51:56 2006
@@ -26,7 +26,6 @@
 
 import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
-import org.apache.directory.shared.ldap.schema.UsageEnum;
 import org.apache.directory.shared.ldap.schema.syntax.parser.AttributeTypeDescriptionSchemaParser;
 import org.apache.directory.shared.ldap.util.StringTools;
 
@@ -141,26 +140,7 @@
 
         try
         {
-            AttributeTypeDescription atd = schemaParser.parseAttributeTypeDescription( strValue );
-            
-            // SYNTAX or SUP must be contained
-            if ( ( atd.getSyntax() == null ) && ( atd.getSuperType() == null ) ) 
-            {
-                return false;
-            }
-            
-            // COLLECTIVE requires usage userApplications
-            if ( atd.isCollective() && ( atd.getUsage() != UsageEnum.USER_APPLICATIONS ) )
-            {
-                return false;
-            }
-            
-            // NO-USER-MODIFICATION requires an operational usage.
-            if ( !atd.isUserModifiable() && ( atd.getUsage() == UsageEnum.USER_APPLICATIONS ) ) 
-            {
-                return false;
-            }
-                
+            schemaParser.parseAttributeTypeDescription( strValue );
             return true;
         }
         catch ( ParseException pe )

Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java Sun Dec 17 11:51:56 2006
@@ -119,14 +119,7 @@
 
         try
         {
-            MatchingRuleDescription mrd = schemaParser.parseMatchingRuleDescription( strValue );
-            
-            // SYNTAX must be present
-            if ( ( mrd.getSyntax() == null ) ) 
-            {
-                return false;
-            }
-            
+            schemaParser.parseMatchingRuleDescription( strValue );
             return true;
         }
         catch ( ParseException pe )

Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java Sun Dec 17 11:51:56 2006
@@ -116,14 +116,7 @@
 
         try
         {
-            MatchingRuleUseDescription mrud = schemaParser.parseMatchingRuleUseDescription( strValue );
-            
-            // APPLIES must be present
-            if ( ( mrud.getApplicableAttributes()== null ) || ( mrud.getApplicableAttributes().isEmpty() ) ) 
-            {
-                return false;
-            }
-                
+            schemaParser.parseMatchingRuleUseDescription( strValue );
             return true;
         }
         catch ( ParseException pe )

Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java Sun Dec 17 11:51:56 2006
@@ -32,7 +32,7 @@
 
 /**
  * A SyntaxChecker which verifies that a value follows the
- * object class descripton syntax according to RFC 4512, par 4.4.1:
+ * object class descripton syntax according to RFC 4512, par 4.2.1:
  * 
  * <pre>
  * ObjectClassDescription = LPAREN WSP
@@ -124,7 +124,6 @@
         try
         {
             schemaParser.parseObjectClassDescription( strValue );
-                
             return true;
         }
         catch ( ParseException pe )

Modified: directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserAttributeTypeDescriptionTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserAttributeTypeDescriptionTest.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserAttributeTypeDescriptionTest.java (original)
+++ directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserAttributeTypeDescriptionTest.java Sun Dec 17 11:51:56 2006
@@ -58,7 +58,7 @@
      */
     public void testNumericOid() throws ParseException
     {
-        SchemaParserTestUtils.testNumericOid( parser );
+        SchemaParserTestUtils.testNumericOid( parser, "SYNTAX 1.1" );
     }
 
 
@@ -69,7 +69,7 @@
      */
     public void testNames() throws ParseException
     {
-        SchemaParserTestUtils.testNames( parser );
+        SchemaParserTestUtils.testNames( parser, "1.1", "SYNTAX 1.1" );
     }
 
 
@@ -80,7 +80,7 @@
      */
     public void testDescription() throws ParseException
     {
-        SchemaParserTestUtils.testDescription( parser );
+        SchemaParserTestUtils.testDescription( parser, "1.1", "SYNTAX 1.1" );
     }
 
 
@@ -91,7 +91,7 @@
      */
     public void testObsolete() throws ParseException
     {
-        SchemaParserTestUtils.testObsolete( parser );
+        SchemaParserTestUtils.testObsolete( parser, "1.1", "SYNTAX 1.1" );
     }
 
 
@@ -106,22 +106,22 @@
         AttributeTypeDescription atd = null;
 
         // no SUP
-        value = "( 1.1 )";
+        value = "( 1.1 SYNTAX 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNull( atd.getSuperType() );
 
         // SUP numericoid
-        value = "( 1.1 SUP 1.2.3.4.5.6.7.8.9.0 )";
+        value = "( 1.1 SYNTAX 1.1 SUP 1.2.3.4.5.6.7.8.9.0 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4.5.6.7.8.9.0", atd.getSuperType() );
 
         // SUP descr
-        value = "( 1.1 SUP abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
+        value = "( 1.1 SYNTAX 1.1 SUP abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getSuperType() );
 
         // no quote allowed
-        value = "( 1.1 SUP 'name' )";
+        value = "( 1.1 SYNTAX 1.1 SUP 'name' )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -133,7 +133,7 @@
         }
 
         // no quote allowed
-        value = "( 1.1 SUP '1.2.3.4' )";
+        value = "( 1.1 SYNTAX 1.1 SUP '1.2.3.4' )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -145,7 +145,7 @@
         }
 
         // invalid character
-        value = "( 1.1 SUP 1.2.3.4.A )";
+        value = "( 1.1 SYNTAX 1.1 SUP 1.2.3.4.A )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -157,7 +157,7 @@
         }
 
         // only single SUP allowed
-        value = "( 1.1 SUP ( name1 $ name2 ) )";
+        value = "( 1.1 SYNTAX 1.1 SUP ( name1 $ name2 ) )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -169,7 +169,7 @@
         }
 
         // empty sup
-        value = "( 1.1 SUP )";
+        value = "( 1.1 SYNTAX 1.1 SUP )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -194,22 +194,22 @@
         AttributeTypeDescription atd = null;
 
         // no EQUALITY
-        value = "( 1.1 )";
+        value = "( 1.1 SYNTAX 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNull( atd.getEqualityMatchingRule() );
 
         // EQUALITY numericoid
-        value = "( 1.1 EQUALITY 1.2.3.4567.8.9.0 )";
+        value = "( 1.1 SYNTAX 1.1 EQUALITY 1.2.3.4567.8.9.0 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4567.8.9.0", atd.getEqualityMatchingRule() );
 
         // EQUALITY descr
-        value = "( 1.1 EQUALITY abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
+        value = "( 1.1 SYNTAX 1.1 EQUALITY abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getEqualityMatchingRule() );
 
         // no quote allowed
-        value = "( 1.1 EQUALITY 'caseExcactMatch' )";
+        value = "( 1.1 SYNTAX 1.1 EQUALITY 'caseExcactMatch' )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -234,22 +234,22 @@
         AttributeTypeDescription atd = null;
 
         // no EQUALITY
-        value = "( 1.1 )";
+        value = "( 1.1 SYNTAX 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNull( atd.getOrderingMatchingRule() );
 
         // EQUALITY numericoid
-        value = "( 1.1 ORDERING 1.2.3.4567.8.9.0 )";
+        value = "( 1.1 SYNTAX 1.1 ORDERING 1.2.3.4567.8.9.0 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4567.8.9.0", atd.getOrderingMatchingRule() );
 
         // EQUALITY descr
-        value = "( 1.1 ORDERING abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
+        value = "( 1.1 SYNTAX 1.1 ORDERING abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getOrderingMatchingRule() );
 
         // no quote allowed
-        value = "( 1.1 ORDERING 'generalizedTimeOrderingMatch' )";
+        value = "( 1.1 SYNTAX 1.1 ORDERING 'generalizedTimeOrderingMatch' )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -274,23 +274,23 @@
         AttributeTypeDescription atd = null;
 
         // no EQUALITY
-        value = "( 1.1 )";
+        value = "( 1.1 SYNTAX 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNull( atd.getSubstringsMatchingRule() );
 
         // EQUALITY numericoid
-        value = "( 1.1 SUBSTR 1.2.3.4567.8.9.0 )";
+        value = "( 1.1 SYNTAX 1.1 SUBSTR 1.2.3.4567.8.9.0 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4567.8.9.0", atd.getSubstringsMatchingRule() );
 
         // EQUALITY descr
-        value = "( 1.1 SUBSTR abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
+        value = "( 1.1 SYNTAX 1.1 SUBSTR abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd
             .getSubstringsMatchingRule() );
 
         // no quote allowed
-        value = "( 1.1 SUBSTR 'caseIgnoreSubstringsMatch' )";
+        value = "( 1.1 SYNTAX 1.1 SUBSTR 'caseIgnoreSubstringsMatch' )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -314,7 +314,7 @@
         AttributeTypeDescription atd = null;
 
         // no SYNTAX
-        value = "( 1.1 )";
+        value = "( 1.1 SUP 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNull( atd.getSyntax() );
         assertEquals( 0, atd.getSyntaxLength() );
@@ -423,22 +423,22 @@
         AttributeTypeDescription atd = null;
 
         // not single-value
-        value = "( 1.1 NAME 'test' DESC 'Descripton' )";
+        value = "( 1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' )";
         atd = parser.parseAttributeTypeDescription( value );
         assertFalse( atd.isSingleValued() );
 
         // single-value
-        value = "(1.1 NAME 'test' DESC 'Descripton' SINGLE-VALUE)";
+        value = "(1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' SINGLE-VALUE)";
         atd = parser.parseAttributeTypeDescription( value );
         assertTrue( atd.isSingleValued() );
 
         // single-value 
-        value = "(1.1 SINGLE-VALUE)";
+        value = "(1.1 SYNTAX 1.1 SINGLE-VALUE)";
         atd = parser.parseAttributeTypeDescription( value );
         assertTrue( atd.isSingleValued() );
 
         // ivalid
-        value = "(1.1 NAME 'test' DESC 'Descripton' SINGLE-VALU )";
+        value = "(1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' SINGLE-VALU )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -462,22 +462,22 @@
         AttributeTypeDescription atd = null;
 
         // not collective
-        value = "( 1.1 NAME 'test' DESC 'Descripton' )";
+        value = "( 1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' )";
         atd = parser.parseAttributeTypeDescription( value );
         assertFalse( atd.isCollective() );
 
         // single-value
-        value = "(1.1 NAME 'test' DESC 'Descripton' COLLECTIVE )";
+        value = "(1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' COLLECTIVE )";
         atd = parser.parseAttributeTypeDescription( value );
         assertTrue( atd.isCollective() );
 
         // single-value 
-        value = "(1.1 COLLECTIVE)";
+        value = "(1.1 SYNTAX 1.1 COLLECTIVE)";
         atd = parser.parseAttributeTypeDescription( value );
         assertTrue( atd.isCollective() );
 
         // ivalid
-        value = "(1.1 NAME 'test' DESC 'Descripton' COLLECTIV )";
+        value = "(1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' COLLECTIV )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -501,26 +501,26 @@
         AttributeTypeDescription atd = null;
 
         // not NO-USER-MODIFICATION
-        value = "( 1.1 NAME 'test' DESC 'Descripton' )";
+        value = "( 1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' )";
         atd = parser.parseAttributeTypeDescription( value );
         assertTrue( atd.isUserModifiable() );
 
         // NO-USER-MODIFICATION
-        value = "(1.1 NAME 'test' DESC 'Descripton' NO-USER-MODIFICATION )";
+        value = "(1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' NO-USER-MODIFICATION USAGE directoryOperation )";
         atd = parser.parseAttributeTypeDescription( value );
         assertFalse( atd.isUserModifiable() );
 
         // NO-USER-MODIFICATION 
-        value = "(1.1 NO-USER-MODIFICATION)";
+        value = "(1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE directoryOperation )";
         atd = parser.parseAttributeTypeDescription( value );
         assertFalse( atd.isUserModifiable() );
 
         // ivalid
-        value = "(1.1 NAME 'test' DESC 'Descripton' NO-USER-MODIFICATIO )";
+        value = "(1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' NO-USER-MODIFICATIO USAGE directoryOperation )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, invalid COLLECTIVE value" );
+            fail( "Exception expected, invalid NO-USER-MODIFICATION value" );
         }
         catch ( ParseException pe )
         {
@@ -540,34 +540,34 @@
         AttributeTypeDescription atd = null;
 
         // DEFAULT is userApplications
-        value = "( 1.1 )";
+        value = "( 1.1 SYNTAX 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( UsageEnum.USER_APPLICATIONS, atd.getUsage() );
 
         // userApplications
-        value = "( 1.1 USAGE userApplications )";
+        value = "( 1.1 SYNTAX 1.1 USAGE userApplications )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( UsageEnum.USER_APPLICATIONS, atd.getUsage() );
 
         // directoryOperation
-        value = "( 1.1 USAGE directoryOperation )";
+        value = "( 1.1 SYNTAX 1.1 USAGE directoryOperation )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( UsageEnum.DIRECTORY_OPERATION, atd.getUsage() );
 
         // AUXILIARY
-        value = "( 1.1 USAGE distributedOperation )";
+        value = "( 1.1 SYNTAX 1.1 USAGE distributedOperation )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( UsageEnum.DISTRIBUTED_OPERATION, atd.getUsage() );
 
         // STRUCTURAL
-        value = "( 1.1 USAGE dSAOperation )";
+        value = "( 1.1 SYNTAX 1.1 USAGE dSAOperation )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( UsageEnum.DSA_OPERATION, atd.getUsage() );
 
         // TODO: case insensitive?
 
         // ivalid
-        value = "( 1.1 USAGE abc )";
+        value = "( 1.1 SYNTAX 1.1 USAGE abc )";
         try
         {
             atd = parser.parseAttributeTypeDescription( value );
@@ -587,7 +587,7 @@
      */
     public void testExtensions() throws ParseException
     {
-        SchemaParserTestUtils.testExtensions( parser );
+        SchemaParserTestUtils.testExtensions( parser, "1.1", "SYNTAX 1.1" );
     }
 
 
@@ -601,7 +601,7 @@
         String value = null;
         AttributeTypeDescription atd = null;
 
-        value = "( 1.2.3.4.5.6.7.8.9.0 NAME ( 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' 'test' ) DESC 'Descripton äöüß 部長' OBSOLETE SUP abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 EQUALITY 2.3.4.5.6.7.8.9.0.1 ORDERING 3.4.5.6.7.8.9.0.1.2 SUBSTR 4.5.6.7.8.9.0.1.2.3 SYNTAX 5.6.7.8.9.0.1.2.3.4{1234567890} SINGLE-VALUE COLLECTIVE NO-USER-MODIFICATION USAGE dSAOperation X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2') )";
+        value = "( 1.2.3.4.5.6.7.8.9.0 NAME ( 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' 'test' ) DESC 'Descripton äöüß 部長' OBSOLETE SUP abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 EQUALITY 2.3.4.5.6.7.8.9.0.1 ORDERING 3.4.5.6.7.8.9.0.1.2 SUBSTR 4.5.6.7.8.9.0.1.2.3 SYNTAX 5.6.7.8.9.0.1.2.3.4{1234567890} SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2') )";
         atd = parser.parseAttributeTypeDescription( value );
 
         assertEquals( "1.2.3.4.5.6.7.8.9.0", atd.getNumericOid() );
@@ -618,7 +618,7 @@
         assertEquals( 1234567890, atd.getSyntaxLength() );
 
         assertTrue( atd.isSingleValued() );
-        assertTrue( atd.isCollective() );
+        assertFalse( atd.isCollective() );
         assertFalse( atd.isUserModifiable() );
         assertEquals( UsageEnum.DSA_OPERATION, atd.getUsage() );
 
@@ -633,7 +633,179 @@
         assertEquals( "test2-2", atd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
     }
 
+    
+    /**
+     * Test unique elements.
+     * 
+     * @throws ParseException
+     */
+    public void testUniqueElements() throws ParseException
+    {
+        String[] testValues = new String[]
+            { 
+                "( 1.1 SYNTAX 1.1 NAME 'test1' NAME 'test2' )", 
+                "( 1.1 SYNTAX 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1.1 SYNTAX 1.1 OBSOLETE OBSOLETE )", 
+                "( 1.1 SYNTAX 1.1 SUP test1 SUP test2 )",
+                "( 1.1 SYNTAX 1.1 EQUALITY test1 EQUALITY test2 )",
+                "( 1.1 SYNTAX 1.1 ORDERING test1 ORDERING test2 )",
+                "( 1.1 SYNTAX 1.1 SUBSTR test1 SUBSTR test2 )",
+                "( 1.1 SYNTAX 1.1 SYNTAX 2.2 SYNTAX 3.3 )",
+                "( 1.1 SYNTAX 1.1 SINGLE-VALUE SINGLE-VALUE )",
+                "( 1.1 SYNTAX 1.1 COLLECTIVE COLLECTIVE )", 
+                "( 1.1 SYNTAX 1.1 USAGE directoryOperation NO-USER-MODIFICATION NO-USER-MODIFICATION )", 
+                "( 1.1 SYNTAX 1.1 USAGE directoryOperation USAGE userApplications )", 
+                "( 1.1 SYNTAX 1.1 X-TEST 'test1' X-TEST 'test2' )" 
+            };
+        SchemaParserTestUtils.testUnique( parser, testValues );
+    }
+    
+    
+    /**
+     * Test required elements.
+     * 
+     * @throws ParseException
+     */
+    public void testRequiredElements() throws ParseException
+    {
+        String value = null;
+        AttributeTypeDescription atd = null;
+
+        value = "( 1.2.3.4.5.6.7.8.9.0 SYNTAX 1.1 SUP 1.1 )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertNotNull( atd.getSyntax() );
+        assertNotNull( atd.getSuperType() );
+        
+        value = "( 1.2.3.4.5.6.7.8.9.0 SYNTAX 1.1 )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertNotNull( atd.getSyntax() );
+        assertNull( atd.getSuperType() );
+        
+        value = "( 1.2.3.4.5.6.7.8.9.0 SUP 1.1 )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertNull( atd.getSyntax() );
+        assertNotNull( atd.getSuperType() );
+
+        value = "( 1.2.3.4.5.6.7.8.9.0 )";
+        try
+        {
+            parser.parseAttributeTypeDescription( value );
+            fail( "Exception expected, SYNTAX or SUP is required" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
 
+    }
+    
+    /**
+     * Test collective constraint:
+     * COLLECTIVE requires USAGE userApplications
+     * 
+     * @throws ParseException
+     */
+    public void testCollecitveConstraint() throws ParseException
+    {
+        String value = null;
+        AttributeTypeDescription atd = null;
+
+        value = "( 1.1 SYNTAX 1.1 COLLECTIVE )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertTrue( atd.isCollective() );
+        assertEquals( UsageEnum.USER_APPLICATIONS , atd.getUsage() );
+        
+        value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE userApplications )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertTrue( atd.isCollective() );
+        assertEquals( UsageEnum.USER_APPLICATIONS , atd.getUsage() );
+        
+        value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE directoryOperation )";
+        try
+        {
+            parser.parseAttributeTypeDescription( value );
+            fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        
+        value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE dSAOperation )";
+        try
+        {
+            parser.parseAttributeTypeDescription( value );
+            fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        
+        value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE distributedOperation )";
+        try
+        {
+            parser.parseAttributeTypeDescription( value );
+            fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        
+    }
+    
+    
+    /**
+     * Test no-user-modification constraint:
+     * NO-USER-MODIFICATION requires an operational USAGE
+     * 
+     * @throws ParseException
+     */
+    public void testNoUserModificatonConstraint() throws ParseException
+    {
+        String value = null;
+        AttributeTypeDescription atd = null;
+        
+        value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE directoryOperation )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertFalse( atd.isUserModifiable() );
+        assertEquals( UsageEnum.DIRECTORY_OPERATION , atd.getUsage() );
+        
+        value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE dSAOperation )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertFalse( atd.isUserModifiable() );
+        assertEquals( UsageEnum.DSA_OPERATION , atd.getUsage() );
+        
+        value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE distributedOperation )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertFalse( atd.isUserModifiable() );
+        assertEquals( UsageEnum.DISTRIBUTED_OPERATION , atd.getUsage() );
+        
+        value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE userApplications )";
+        try
+        {
+            parser.parseAttributeTypeDescription( value );
+            fail( "Exception expected, NO-USER-MODIFICATION requires an operational USAGE" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        
+        value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION )";
+        try
+        {
+            parser.parseAttributeTypeDescription( value );
+            fail( "Exception expected, NO-USER-MODIFICATION requires an operational USAGE" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+    }
+    
+    
     /**
      * Ensure that element order is ignored
      * 
@@ -697,12 +869,11 @@
     {
         String[] testValues = new String[]
             {
-                "( 1.1 )",
+                "( 1.1 SYNTAX 1.1 )",
                 "( 2.5.4.41 NAME 'name' DESC 'RFC2256: common supertype of name attributes'  EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} USAGE userApplications )",
                 "( 2.5.4.3 NAME ( 'cn' 'commonName' ) DESC 'RFC2256: common name(s) for which the entity is known by'  SUP name EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE userApplications )",
-                "( 1.2.3.4.5.6.7.8.9.0 NAME ( 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' 'test' ) DESC 'Descripton äöüß 部長' OBSOLETE SUP abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 EQUALITY 2.3.4.5.6.7.8.9.0.1 ORDERING 3.4.5.6.7.8.9.0.1.2 SUBSTR 4.5.6.7.8.9.0.1.2.3 SYNTAX 5.6.7.8.9.0.1.2.3.4{1234567890} SINGLE-VALUE COLLECTIVE NO-USER-MODIFICATION USAGE dSAOperation X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2') )" };
+                "( 1.2.3.4.5.6.7.8.9.0 NAME ( 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' 'test' ) DESC 'Descripton äöüß 部長' OBSOLETE SUP abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 EQUALITY 2.3.4.5.6.7.8.9.0.1 ORDERING 3.4.5.6.7.8.9.0.1.2 SUBSTR 4.5.6.7.8.9.0.1.2.3 SYNTAX 5.6.7.8.9.0.1.2.3.4{1234567890} SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2') )" };
         SchemaParserTestUtils.testMultiThreaded( parser, testValues );
-
     }
 
 }

Modified: directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserLdapSyntaxDescriptionTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserLdapSyntaxDescriptionTest.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserLdapSyntaxDescriptionTest.java (original)
+++ directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserLdapSyntaxDescriptionTest.java Sun Dec 17 11:51:56 2006
@@ -57,7 +57,7 @@
      */
     public void testNumericOid() throws ParseException
     {
-        SchemaParserTestUtils.testNumericOid( parser );
+        SchemaParserTestUtils.testNumericOid( parser, "" );
     }
 
 
@@ -68,7 +68,7 @@
      */
     public void testDescription() throws ParseException
     {
-        SchemaParserTestUtils.testDescription( parser );
+        SchemaParserTestUtils.testDescription( parser, "1.1", "" );
     }
 
 
@@ -79,7 +79,7 @@
      */
     public void testExtensions() throws ParseException
     {
-        SchemaParserTestUtils.testExtensions( parser );
+        SchemaParserTestUtils.testExtensions( parser, "1.1", "" );
     }
 
 
@@ -110,6 +110,22 @@
 
     }
 
+
+    /**
+     * Test unique elements.
+     * 
+     * @throws ParseException
+     */
+    public void testUniqueElements() throws ParseException
+    {
+        String[] testValues = new String[]
+            { 
+                "( 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1.1 X-TEST 'test1' X-TEST 'test2' )" 
+            };
+        SchemaParserTestUtils.testUnique( parser, testValues );
+    }
+    
 
     ////////////////////////////////////////////////////////////////
     //         Some real-world attribute type definitions         //

Modified: directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleDescriptionTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleDescriptionTest.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleDescriptionTest.java (original)
+++ directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleDescriptionTest.java Sun Dec 17 11:51:56 2006
@@ -51,25 +51,25 @@
 
     public void testNumericOid() throws Exception
     {
-        SchemaParserTestUtils.testNumericOid( parser );
+        SchemaParserTestUtils.testNumericOid( parser, "SYNTAX 1.1" );
     }
 
 
     public void testNames() throws Exception
     {
-        SchemaParserTestUtils.testNames( parser );
+        SchemaParserTestUtils.testNames( parser, "1.1", "SYNTAX 1.1" );
     }
 
 
     public void testDescription() throws ParseException
     {
-        SchemaParserTestUtils.testDescription( parser );
+        SchemaParserTestUtils.testDescription( parser, "1.1", "SYNTAX 1.1" );
     }
 
 
     public void testObsolete() throws ParseException
     {
-        SchemaParserTestUtils.testObsolete( parser );
+        SchemaParserTestUtils.testObsolete( parser, "1.1", "SYNTAX 1.1" );
     }
 
 
@@ -106,12 +106,36 @@
             // expected
         }
 
+        // SYNTAX is required
+        value = "( 1.1 )";
+        try
+        {
+            mrd = parser.parseMatchingRuleDescription( value );
+            fail( "Exception expected, SYNTAX is required" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // OC must only appear once
+        value = "( 1.1 SYNTAX 2.2 SYNTAX 3.3 )";
+        try
+        {
+            mrd = parser.parseMatchingRuleDescription( value );
+            fail( "Exception expected, SYNTAX appears twice" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        
     }
 
 
     public void testExtensions() throws ParseException
     {
-        SchemaParserTestUtils.testExtensions( parser );
+        SchemaParserTestUtils.testExtensions( parser, "1.1", "SYNTAX 1.1" );
     }
 
 
@@ -140,8 +164,55 @@
         assertEquals( "test2-1", mrd.getExtensions().get( "X-TEST-b" ).get( 0 ) );
         assertEquals( "test2-2", mrd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
     }
+    
+    
+    /**
+     * Test unique elements.
+     * 
+     * @throws ParseException
+     */
+    public void testUniqueElements() throws ParseException
+    {
+        String[] testValues = new String[]
+            { 
+                "( 1.1 SYNTAX 1.1 NAME 'test1' NAME 'test2' )", 
+                "( 1.1 SYNTAX 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1.1 SYNTAX 1.1 OBSOLETE OBSOLETE )", 
+                "( 1.1 SYNTAX 1.1 SYNTAX 2.2 SYNTAX 3.3 )",
+                "( 1.1 SYNTAX 1.1 X-TEST 'test1' X-TEST 'test2' )" 
+            };
+        SchemaParserTestUtils.testUnique( parser, testValues );
+    }
+
+
+    /**
+     * Test required elements.
+     * 
+     * @throws ParseException
+     */
+    public void testRequiredElements() throws ParseException
+    {
+        String value = null;
+        MatchingRuleDescription mrd = null;
+
+        value = "( 1.2.3.4.5.6.7.8.9.0 SYNTAX 1.1 )";
+        mrd = parser.parseMatchingRuleDescription( value );
+        assertNotNull( mrd.getSyntax() );
 
+        value = "( 1.2.3.4.5.6.7.8.9.0 )";
+        try
+        {
+            mrd = parser.parseMatchingRuleDescription( value );
+            fail( "Exception expected, SYNTAX is required" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
 
+    }
+    
+    
     ////////////////////////////////////////////////////////////////
     //         Some real-world matching rule descriptons          //
     ////////////////////////////////////////////////////////////////
@@ -203,7 +274,7 @@
     {
         String[] testValues = new String[]
             {
-                "( 1.1 )",
+                "( 1.1 SYNTAX 1.1 )",
                 "( 2.5.13.5 NAME 'caseExactMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
                 "( 2.5.13.5 NAME 'caseExactMatch' DESC 'Case Exact Matching on Directory String [defined in X.520]' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
                 "( 1.2.3.4.5.6.7.8.9.0 NAME ( 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' 'test' ) DESC 'Descripton äöüß 部長' OBSOLETE SYNTAX 0.1.2.3.4.5.6.7.8.9 X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2') )" };

Modified: directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleUseDescriptionTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleUseDescriptionTest.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleUseDescriptionTest.java (original)
+++ directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserMatchingRuleUseDescriptionTest.java Sun Dec 17 11:51:56 2006
@@ -52,25 +52,25 @@
 
     public void testNumericOid() throws Exception
     {
-        SchemaParserTestUtils.testNumericOid( parser );
+        SchemaParserTestUtils.testNumericOid( parser, "APPLIES 1.1" );
     }
 
 
     public void testNames() throws Exception
     {
-        SchemaParserTestUtils.testNames( parser );
+        SchemaParserTestUtils.testNames( parser, "1.1", "APPLIES 1.1" );
     }
 
 
     public void testDescription() throws ParseException
     {
-        SchemaParserTestUtils.testDescription( parser );
+        SchemaParserTestUtils.testDescription( parser, "1.1", "APPLIES 1.1" );
     }
 
 
     public void testObsolete() throws ParseException
     {
-        SchemaParserTestUtils.testObsolete( parser );
+        SchemaParserTestUtils.testObsolete( parser, "1.1", "APPLIES 1.1" );
     }
 
 
@@ -80,11 +80,6 @@
         String value = null;
         MatchingRuleUseDescription mrud = null;
 
-        // no APPLIES
-        value = "( 1.1 )";
-        mrud = parser.parseMatchingRuleUseDescription( value );
-        assertEquals( 0, mrud.getApplicableAttributes().size() );
-
         // APPLIES simple numericoid
         value = "( 1.1 APPLIES 1.2.3.4.5.6.7.8.9.0 )";
         mrud = parser.parseMatchingRuleUseDescription( value );
@@ -220,12 +215,36 @@
         {
             // expected
         }
+        
+        // APPLIES is required
+        value = "( 1.1 )";
+        try
+        {
+            mrud = parser.parseMatchingRuleUseDescription( value );
+            fail( "Exception expected, APPLIES is required" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // APPLIES must only appear once
+        value = "( 1.1 APPLIES test1 APPLIES test2 )";
+        try
+        {
+            mrud = parser.parseMatchingRuleUseDescription( value );
+            fail( "Exception expected, APPLIES appears twice" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
     }
 
 
     public void testExtensions() throws ParseException
     {
-        SchemaParserTestUtils.testExtensions( parser );
+        SchemaParserTestUtils.testExtensions( parser, "1.1", "APPLIES 1.1" );
     }
 
 
@@ -259,6 +278,53 @@
     }
 
 
+    /**
+     * Test unique elements.
+     * 
+     * @throws ParseException
+     */
+    public void testUniqueElements() throws ParseException
+    {
+        String[] testValues = new String[]
+            { 
+                "( 1.1 APPLIES 1.1 NAME 'test1' NAME 'test2' )",
+                "( 1.1 APPLIES 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1.1 APPLIES 1.1 OBSOLETE OBSOLETE )", 
+                "( 1.1 APPLIES 1.1 APPLIES test1 APPLIES test2 )",
+                "( 1.1 APPLIES 1.1 X-TEST 'test1' X-TEST 'test2' )" 
+            };
+        SchemaParserTestUtils.testUnique( parser, testValues );
+    }    
+    
+    
+    /**
+     * Test required elements.
+     * 
+     * @throws ParseException
+     */
+    public void testRequiredElements() throws ParseException
+    {
+        String value = null;
+        MatchingRuleUseDescription mrud = null;
+
+        value = "( 1.2.3.4.5.6.7.8.9.0 APPLIES a )";
+        mrud = parser.parseMatchingRuleUseDescription( value );
+        assertEquals( 1, mrud.getApplicableAttributes().size() );
+
+        value = "( 1.2.3.4.5.6.7.8.9.0 )";
+        try
+        {
+            mrud = parser.parseMatchingRuleUseDescription( value );
+            fail( "Exception expected, APPLIES is required" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+    }
+    
+    
     ////////////////////////////////////////////////////////////////
     //       Some real-world matching rule use descriptons        //
     ////////////////////////////////////////////////////////////////
@@ -287,7 +353,7 @@
     {
         String[] testValues = new String[]
             {
-                "( 1.1 )",
+                "( 1.1 APPLIES 1.1 )",
                 "( 2.5.13.17 NAME 'octetStringMatch' APPLIES ( javaSerializedData $ userPassword ) )",
                 "( 2.5.13.1 NAME 'distinguishedNameMatch' APPLIES ( memberOf $ dITRedirect $ associatedName $ secretary $ documentAuthor $ manager $ seeAlso $ roleOccupant $ owner $ member $ distinguishedName $ aliasedObjectName $ namingContexts $ subschemaSubentry $ modifiersName $ creatorsName ) )",
                 "( 1.2.3.4.5.6.7.8.9.0 NAME ( 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' 'test' ) DESC 'Descripton äöüß 部長' OBSOLETE APPLIES ( 0.1.2.3.4.5.6.7.8.9 $ abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 ) X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2') )" };

Modified: directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserObjectClassDescriptionTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserObjectClassDescriptionTest.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserObjectClassDescriptionTest.java (original)
+++ directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserObjectClassDescriptionTest.java Sun Dec 17 11:51:56 2006
@@ -58,7 +58,7 @@
      */
     public void testNumericOid() throws ParseException
     {
-        SchemaParserTestUtils.testNumericOid( parser );
+        SchemaParserTestUtils.testNumericOid( parser, "" );
     }
 
 
@@ -69,7 +69,7 @@
      */
     public void testNames() throws ParseException
     {
-        SchemaParserTestUtils.testNames( parser );
+        SchemaParserTestUtils.testNames( parser, "1.1", "" );
     }
 
 
@@ -80,7 +80,7 @@
      */
     public void testDescription() throws ParseException
     {
-        SchemaParserTestUtils.testDescription( parser );
+        SchemaParserTestUtils.testDescription( parser, "1.1", "" );
     }
 
 
@@ -91,7 +91,7 @@
      */
     public void testObsolete() throws ParseException
     {
-        SchemaParserTestUtils.testObsolete( parser );
+        SchemaParserTestUtils.testObsolete( parser, "1.1", "" );
     }
 
 
@@ -399,7 +399,7 @@
      */
     public void testExtensions() throws ParseException
     {
-        SchemaParserTestUtils.testExtensions( parser );
+        SchemaParserTestUtils.testExtensions( parser, "1.1", "" );
 
     }
 
@@ -448,6 +448,31 @@
     }
 
 
+    /**
+     * Test unique elements.
+     * 
+     * @throws ParseException
+     */
+    public void testUniqueElements() throws ParseException
+    {
+        String[] testValues = new String[]
+            { 
+                "( 1.1 NAME 'test1' NAME 'test2' )", 
+                "( 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1.1 OBSOLETE OBSOLETE )", 
+                "( 1.1 SUP test1 SUP test2 )",
+                "( 1.1 STRUCTURAL STRUCTURAL )",
+                "( 1.1 ABSTRACT ABSTRACT )",
+                "( 1.1 AUXILIARY AUXILIARY )",
+                "( 1.1 STRUCTURAL AUXILIARY AUXILIARY )",
+                "( 1.1 MUST test1 MUST test2 )",
+                "( 1.1 MAY test1 MAY test2 )",
+                "( 1.1 X-TEST 'test1' X-TEST 'test2' )" 
+            };
+        SchemaParserTestUtils.testUnique( parser, testValues );
+    }
+    
+    
     /**
      * Ensure that element order is ignored
      * 

Modified: directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserTestUtils.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserTestUtils.java?view=diff&rev=488033&r1=488032&r2=488033
==============================================================================
--- directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserTestUtils.java (original)
+++ directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SchemaParserTestUtils.java Sun Dec 17 11:51:56 2006
@@ -18,7 +18,7 @@
      * 
      * @throws ParseException
      */
-    public static void testNumericOid( AbstractSchemaParser parser ) throws ParseException
+    public static void testNumericOid( AbstractSchemaParser parser, String required ) throws ParseException
     {
         String value = null;
         AbstractSchemaDescription asd = null;
@@ -48,22 +48,22 @@
         }
 
         // simple
-        value = "( 0.1.2.3.4.5.6.7.8.9 )";
+        value = "( 0.1.2.3.4.5.6.7.8.9 "+required+" )";
         asd = parser.parse( value );
         TestCase.assertEquals( "0.1.2.3.4.5.6.7.8.9", asd.getNumericOid() );
 
         // simple
-        value = "( 123.4567.890 )";
+        value = "( 123.4567.890 "+required+")";
         asd = parser.parse( value );
         TestCase.assertEquals( "123.4567.890", asd.getNumericOid() );
         
         // simple with spaces
-        value = "(          0.1.2.3.4.5.6.7.8.9          )";
+        value = "(          0.1.2.3.4.5.6.7.8.9         "+required+" )";
         asd = parser.parse( value );
         TestCase.assertEquals( "0.1.2.3.4.5.6.7.8.9", asd.getNumericOid() );
 
         // non-numeric not allowed
-        value = "( test )";
+        value = "( test "+required+" )";
         try
         {
             parser.parse( value );
@@ -75,7 +75,7 @@
         }
 
         // to short
-        value = "( 1 )";
+        value = "( 1 "+required+" )";
         try
         {
             parser.parse( value );
@@ -87,7 +87,7 @@
         }
 
         // dot only
-        value = "( . )";
+        value = "( . "+required+" )";
         try
         {
             parser.parse( value );
@@ -99,7 +99,7 @@
         }
 
         // ends with dot
-        value = "( 1.1. )";
+        value = "( 1.1. "+required+" )";
         try
         {
             parser.parse( value );
@@ -111,7 +111,7 @@
         }
 
         // quotes not allowed
-        value = "( '1.1' )";
+        value = "( '1.1' "+required+" )";
         try
         {
             parser.parse( value );
@@ -123,7 +123,7 @@
         }
 
         // leading 0 not allowed
-        value = "( 01.1 )";
+        value = "( 01.1 "+required+" )";
         try
         {
             parser.parse( value );
@@ -135,7 +135,7 @@
         }
 
         // alpha not allowed
-        value = "( 1.2.a.4 )";
+        value = "( 1.2.a.4 "+required+" )";
         try
         {
             parser.parse( value );
@@ -153,44 +153,44 @@
      * 
      * @throws ParseException
      */
-    public static void testNames( AbstractSchemaParser parser ) throws ParseException
+    public static void testNames( AbstractSchemaParser parser, String oid, String required ) throws ParseException
     {
         String value = null;
         AbstractSchemaDescription asd = null;
 
         // alpha
-        value = "( 1.1 NAME 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' )";
+        value = "( "+oid+" "+required+" NAME 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' )";
         asd = parser.parse( value );
         TestCase.assertEquals( 1, asd.getNames().size() );
         TestCase.assertEquals( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", asd.getNames().get( 0 ) );
 
         // alpha-num-hypen
-        value = "( 1.1 NAME 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' )";
+        value = "( "+oid+" "+required+" NAME 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' )";
         asd = parser.parse( value );
         TestCase.assertEquals( 1, asd.getNames().size() );
         TestCase.assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", asd.getNames().get( 0 ) );
 
         // with parentheses
-        value = "( 1.1 NAME ( 'a-z-0-9' ) )";
+        value = "( "+oid+" "+required+" NAME ( 'a-z-0-9' ) )";
         asd = parser.parse( value );
         TestCase.assertEquals( 1, asd.getNames().size() );
         TestCase.assertEquals( "a-z-0-9", asd.getNames().get( 0 ) );
 
         // with parentheses, without space
-        value = "( 1.1 NAME ('a-z-0-9') )";
+        value = "( "+oid+" "+required+" NAME ('a-z-0-9') )";
         asd = parser.parse( value );
         TestCase.assertEquals( 1, asd.getNames().size() );
         TestCase.assertEquals( "a-z-0-9", asd.getNames().get( 0 ) );
 
         // multi with space
-        value = "( 1.1 NAME ( 'test1' 'test2' ) )";
+        value = "( "+oid+" "+required+" NAME ( 'test1' 'test2' ) )";
         asd = parser.parse( value );
         TestCase.assertEquals( 2, asd.getNames().size() );
         TestCase.assertEquals( "test1", asd.getNames().get( 0 ) );
         TestCase.assertEquals( "test2", asd.getNames().get( 1 ) );
 
         // multi without space
-        value = "( 1.1 NAME ('test1' 'test2' 'test3') )";
+        value = "( "+oid+" "+required+" NAME ('test1' 'test2' 'test3') )";
         asd = parser.parse( value );
         TestCase.assertEquals( 3, asd.getNames().size() );
         TestCase.assertEquals( "test1", asd.getNames().get( 0 ) );
@@ -198,7 +198,7 @@
         TestCase.assertEquals( "test3", asd.getNames().get( 2 ) );
 
         // multi with many spaces
-        value = "(          1.1          NAME          (          'test1'          'test2'          'test3'          )          )";
+        value = "(          "+oid+" "+required+"          NAME          (          'test1'          'test2'          'test3'          )          )";
         asd = parser.parse( value );
         TestCase.assertEquals( 3, asd.getNames().size() );
         TestCase.assertEquals( "test1", asd.getNames().get( 0 ) );
@@ -206,7 +206,7 @@
         TestCase.assertEquals( "test3", asd.getNames().get( 2 ) );
 
         // lowercase
-        value = "( 1.1 name 'test' )";
+        value = "( "+oid+" "+required+" name 'test' )";
         try
         {
             parser.parse( value );
@@ -218,7 +218,7 @@
         }
 
         // unquoted
-        value = "( 1.1 NAME test )";
+        value = "( "+oid+" "+required+" NAME test )";
         try
         {
             parser.parse( value );
@@ -230,7 +230,7 @@
         }
 
         // start with number
-        value = "( 1.1 NAME '1test' )";
+        value = "( "+oid+" "+required+" NAME '1test' )";
         try
         {
             parser.parse( value );
@@ -242,7 +242,7 @@
         }
 
         // start with hypen
-        value = "( 1.1 NAME '-test' )";
+        value = "( "+oid+" "+required+" NAME '-test' )";
         try
         {
             parser.parse( value );
@@ -254,7 +254,7 @@
         }
 
         // invalid character
-        value = "( 1.1 NAME 'te_st' )";
+        value = "( "+oid+" "+required+" NAME 'te_st' )";
         try
         {
             parser.parse( value );
@@ -266,7 +266,7 @@
         }
 
         // NAM unknown
-        value = "( 1.1 NAM 'test' )";
+        value = "( "+oid+" "+required+" NAM 'test' )";
         try
         {
             parser.parse( value );
@@ -278,7 +278,7 @@
         }
 
         // one valid, one invalid
-        value = "( 1.1 NAME ( 'test' 'te_st' ) )";
+        value = "( "+oid+" "+required+" NAME ( 'test' 'te_st' ) )";
         try
         {
             parser.parse( value );
@@ -290,7 +290,7 @@
         }
 
         // no space between values
-        value = "( 1.1 NAME ( 'test1''test2' ) )";
+        value = "( "+oid+" "+required+" NAME ( 'test1''test2' ) )";
         try
         {
             asd = parser.parse( value );
@@ -308,23 +308,23 @@
      * 
      * @throws ParseException
      */
-    public static void testDescription( AbstractSchemaParser parser ) throws ParseException
+    public static void testDescription( AbstractSchemaParser parser, String oid, String required ) throws ParseException
     {
         String value = null;
         AbstractSchemaDescription asd = null;
 
         // simple
-        value = "(1.1 DESC 'Descripton')";
+        value = "("+oid+" "+required+" DESC 'Descripton')";
         asd = parser.parse( value );
         TestCase.assertEquals( "Descripton", asd.getDescription() );
 
         // unicode
-        value = "( 1.1 DESC 'Descripton äöüß 部長' )";
+        value = "( "+oid+" "+required+" DESC 'Descripton äöüß 部長' )";
         asd = parser.parse( value );
         TestCase.assertEquals( "Descripton äöüß 部長", asd.getDescription() );
 
         // lowercase
-        value = "( 1.1 desc 'Descripton' )";
+        value = "( "+oid+" "+required+" desc 'Descripton' )";
         try
         {
             parser.parse( value );
@@ -343,18 +343,18 @@
      * 
      * @throws ParseException
      */
-    public static void testExtensions( AbstractSchemaParser parser ) throws ParseException
+    public static void testExtensions( AbstractSchemaParser parser, String oid, String required ) throws ParseException
     {
         String value = null;
         AbstractSchemaDescription asd = null;
 
         // no extension
-        value = "( 1.1 )";
+        value = "( "+oid+" "+required+" )";
         asd = parser.parse( value );
         TestCase.assertEquals( 0, asd.getExtensions().size() );
 
         // single extension with one value
-        value = "( 1.1 X-TEST 'test' )";
+        value = "( "+oid+" "+required+" X-TEST 'test' )";
         asd = parser.parse( value );
         TestCase.assertEquals( 1, asd.getExtensions().size() );
         TestCase.assertNotNull( asd.getExtensions().get( "X-TEST" ) );
@@ -362,7 +362,7 @@
         TestCase.assertEquals( "test", asd.getExtensions().get( "X-TEST" ).get( 0 ) );
 
         // single extension with multiple values
-        value = "( 1.1 X-TEST-ABC ('test1' 'test äöüß'       'test 部長' ) )";
+        value = "( "+oid+" "+required+" X-TEST-ABC ('test1' 'test äöüß'       'test 部長' ) )";
         asd = parser.parse( value );
         TestCase.assertEquals( 1, asd.getExtensions().size() );
         TestCase.assertNotNull( asd.getExtensions().get( "X-TEST-ABC" ) );
@@ -372,7 +372,7 @@
         TestCase.assertEquals( "test 部長", asd.getExtensions().get( "X-TEST-ABC" ).get( 2 ) );
 
         // multiple extensions
-        value = "(1.1 X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2'))";
+        value = "("+oid+" "+required+" X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2'))";
         asd = parser.parse( value );
         TestCase.assertEquals( 2, asd.getExtensions().size() );
         TestCase.assertNotNull( asd.getExtensions().get( "X-TEST-a" ) );
@@ -385,7 +385,7 @@
         TestCase.assertEquals( "test2-2", asd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
 
         // invalid extension, no number allowed
-        value = "( 1.1 X-TEST1 'test' )";
+        value = "( "+oid+" "+required+" X-TEST1 'test' )";
         try
         {
             asd = parser.parse( value );
@@ -404,33 +404,33 @@
      * 
      * @throws ParseException
      */
-    public static void testObsolete( AbstractSchemaParser parser ) throws ParseException
+    public static void testObsolete( AbstractSchemaParser parser, String oid, String required ) throws ParseException
     {
         String value = null;
         AbstractSchemaDescription asd = null;
 
         // not obsolete
-        value = "( 1.1 )";
+        value = "( "+oid+" "+required+" )";
         asd = parser.parse( value );
         TestCase.assertFalse( asd.isObsolete() );
 
         // not obsolete
-        value = "( 1.1 NAME 'test' DESC 'Descripton' )";
+        value = "( "+oid+" "+required+" NAME 'test' DESC 'Descripton' )";
         asd = parser.parse( value );
         TestCase.assertFalse( asd.isObsolete() );
         
         // obsolete
-        value = "(1.1 NAME 'test' DESC 'Descripton' OBSOLETE)";
+        value = "("+oid+" "+required+" NAME 'test' DESC 'Descripton' OBSOLETE)";
         asd = parser.parse( value );
         TestCase.assertTrue( asd.isObsolete() );
 
         // obsolete 
-        value = "(1.1 OBSOLETE)";
+        value = "("+oid+" "+required+" OBSOLETE)";
         asd = parser.parse( value );
         TestCase.assertTrue( asd.isObsolete() );
 
         // ivalid
-        value = "(1.1 NAME 'test' DESC 'Descripton' OBSOLET )";
+        value = "("+oid+" "+required+" NAME 'test' DESC 'Descripton' OBSOLET )";
         try
         {
             asd = parser.parse( value );
@@ -442,7 +442,7 @@
         }
         
         // trailing value not allowed
-        value = "(1.1 NAME 'test' DESC 'Descripton' OBSOLETE 'true' )";
+        value = "("+oid+" "+required+" NAME 'test' DESC 'Descripton' OBSOLETE 'true' )";
         try
         {
             asd = parser.parse( value );
@@ -455,6 +455,30 @@
         
     }
     
+    
+    
+    /**
+     * Test extensions.
+     * 
+     * @throws ParseException
+     */
+    public static void testUnique( AbstractSchemaParser parser, String[] testValues ) throws ParseException
+    {
+        for ( int i = 0; i < testValues.length; i++ )
+        {
+            String testValue = testValues[i];
+            try
+            {
+                parser.parse( testValue );
+                TestCase.fail( "Exception expected, element appears twice in "+testValue );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
+        
+    }
     
     
     /**