You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2010/07/15 12:04:08 UTC

svn commit: r964361 [3/5] - in /directory/shared/trunk: ldap-schema-manager-tests/ ldap-schema-manager-tests/src/test/java/org/apache/directory/shared/ldap/aci/ ldap-schema-manager-tests/src/test/java/org/apache/directory/shared/ldap/schema/syntaxCheck...

Added: directory/shared/trunk/ldap/src/main/antlr/ACIItemChecker.g
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/antlr/ACIItemChecker.g?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/antlr/ACIItemChecker.g (added)
+++ directory/shared/trunk/ldap/src/main/antlr/ACIItemChecker.g Thu Jul 15 10:04:06 2010
@@ -0,0 +1,780 @@
+header
+{
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+
+package org.apache.directory.shared.ldap.aci;
+
+
+import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser class definition
+// ----------------------------------------------------------------------------
+
+/**
+ * The antlr generated ACIItem checker.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+class AntlrACIItemChecker extends Parser;
+
+
+// ----------------------------------------------------------------------------
+// parser options
+// ----------------------------------------------------------------------------
+
+options
+{
+    k = 1; // ;-)
+    defaultErrorHandler = false;
+}
+
+
+// ----------------------------------------------------------------------------
+// imaginary tokens
+// ----------------------------------------------------------------------------
+
+tokens
+{
+    ATTRIBUTE_VALUE_CANDIDATE;
+    RANGE_OF_VALUES_CANDIDATE;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser initialization
+// ----------------------------------------------------------------------------
+
+{
+    NameComponentNormalizer normalizer;
+    
+    /**
+     * Creates a (normalizing) subordinate DnParser for parsing Names.
+     * This method MUST be called for each instance while we cannot do
+     * constructor overloading for this class.
+     *
+     * @return the DnParser to be used for parsing Names
+     */
+    public void init()
+    {
+    }
+
+    /**
+     * Sets the NameComponentNormalizer for this parser's dnParser.
+     */
+    public void setNormalizer(NameComponentNormalizer normalizer)
+    {
+        this.normalizer = normalizer;
+    }
+}
+
+
+// ----------------------------------------------------------------------------
+// parser productions
+// ----------------------------------------------------------------------------
+
+wrapperEntryPoint
+    :
+    ( SP )* theACIItem ( SP )* EOF
+    ;
+
+theACIItem
+    :
+    OPEN_CURLY
+        ( SP )* mainACIItemComponent ( SP )*
+            ( SEP ( SP )* mainACIItemComponent ( SP )* )*
+    CLOSE_CURLY
+    ;
+    
+mainACIItemComponent
+    :
+    aci_identificationTag
+    | aci_precedence
+    | aci_authenticationLevel
+    | aci_itemOrUserFirst
+    ;
+    
+aci_identificationTag
+    :
+    ID_identificationTag ( SP )+ SAFEUTF8STRING
+    ;
+
+aci_precedence
+    :
+    precedence
+    ;
+
+precedence
+    :
+    ID_precedence ( SP )+ INTEGER
+    ;
+
+aci_authenticationLevel
+    :
+    ID_authenticationLevel ( SP )+ authenticationLevel
+    ;
+
+authenticationLevel
+    :
+    ID_none
+    |
+    ID_simple
+    |
+    ID_strong
+    ;
+
+aci_itemOrUserFirst
+    :
+    ID_itemOrUserFirst ( SP )+ itemOrUserFirst
+    ;
+
+itemOrUserFirst
+    :
+    itemFirst | userFirst
+    ;
+
+itemFirst
+    :
+    ID_itemFirst ( SP )* COLON ( SP )*
+        OPEN_CURLY ( SP )*
+            ( 
+              protectedItems ( SP )*
+                SEP ( SP )* itemPermissions
+            | // relaxing
+              itemPermissions ( SP )*
+                SEP ( SP )* protectedItems
+            )
+        ( SP )* CLOSE_CURLY
+    ;
+
+userFirst
+    :
+    ID_userFirst ( SP )* COLON ( SP )*
+        OPEN_CURLY ( SP )*
+            (
+              userClasses ( SP )*
+                SEP ( SP )* userPermissions
+            | // relaxing
+              userPermissions ( SP )*
+                SEP ( SP )* userClasses
+            )
+        ( SP )* CLOSE_CURLY
+    ;
+
+protectedItems
+    :
+    ID_protectedItems ( SP )*
+        OPEN_CURLY ( SP )*
+            (
+                protectedItem ( SP )*
+                    ( SEP ( SP )* protectedItem ( SP )* )*
+            )?
+        CLOSE_CURLY
+    ;
+
+protectedItem
+    :
+    entry
+    | allUserAttributeTypes
+    | attributeType
+    | allAttributeValues 
+    | allUserAttributeTypesAndValues
+    | attributeValue
+    | selfValue
+    | rangeOfValues
+    | maxValueCount
+    | maxImmSub
+    | restrictedBy
+    | classes
+    ;
+
+entry
+    :
+    ID_entry
+    ;
+
+allUserAttributeTypes
+    :
+    ID_allUserAttributeTypes
+    ;
+
+attributeType
+    :
+    ID_attributeType ( SP )+ attributeTypeSet
+    ;
+
+allAttributeValues
+    :
+    ID_allAttributeValues ( SP )+ attributeTypeSet
+    ;
+
+allUserAttributeTypesAndValues
+    :
+    ID_allUserAttributeTypesAndValues
+    ;
+
+attributeValue
+    :
+    ATTRIBUTE_VALUE_CANDIDATE // ate the identifier for subordinate dn parser workaround
+    ;
+
+selfValue
+    :
+    ID_selfValue ( SP )+ attributeTypeSet
+    ;
+
+rangeOfValues
+    :
+    RANGE_OF_VALUES_CANDIDATE
+    ;
+
+maxValueCount
+    :
+    ID_maxValueCount ( SP )+
+    OPEN_CURLY ( SP )*
+        aMaxValueCount ( SP )*
+            ( SEP ( SP )* aMaxValueCount ( SP )*
+            )*
+    CLOSE_CURLY
+    ;
+
+aMaxValueCount
+    :
+    OPEN_CURLY ( SP )*
+        (
+          ID_type ( SP )+ oid ( SP )* SEP ( SP )*
+          ID_maxCount ( SP )+ INTEGER
+        | // relaxing
+          ID_maxCount ( SP )+ INTEGER ( SP )* SEP ( SP )*
+          ID_type ( SP )+ oid
+        )
+    ( SP )* CLOSE_CURLY
+    ;
+
+maxImmSub
+    :
+    ID_maxImmSub ( SP )+ INTEGER
+    ;
+
+restrictedBy
+    :
+    ID_restrictedBy ( SP )+
+        OPEN_CURLY ( SP )*
+            restrictedValue ( SP )*
+                    ( SEP ( SP )* restrictedValue ( SP )*
+                    )*
+        CLOSE_CURLY
+    ;
+
+restrictedValue
+    :
+    OPEN_CURLY ( SP )*
+        (
+          ID_type ( SP )+ oid ( SP )* SEP ( SP )*
+          ID_valuesIn ( SP )+ oid
+        | // relaxing
+          ID_valuesIn ( SP )+ oid ( SP )* SEP ( SP )*
+          ID_type ( SP )+ oid
+        )
+    ( SP )* CLOSE_CURLY
+    ;
+
+attributeTypeSet 
+    :
+    OPEN_CURLY ( SP )*
+        oid ( SP )*
+            ( SEP ( SP )* oid ( SP )*
+            )*
+    CLOSE_CURLY
+    ;
+
+classes
+    :
+    ID_classes ( SP )+ refinement
+    ;
+
+itemPermissions
+    :
+    ID_itemPermissions ( SP )+
+        OPEN_CURLY ( SP )*
+            ( itemPermission ( SP )*
+                ( SEP ( SP )* itemPermission ( SP )*
+                )*
+            )?
+        CLOSE_CURLY
+    ;
+
+itemPermission
+    :
+    OPEN_CURLY ( SP )*
+        anyItemPermission ( SP )*
+            ( SEP ( SP )* anyItemPermission ( SP )* )*
+    CLOSE_CURLY
+    ;
+
+anyItemPermission
+    :
+    precedence
+    | userClasses
+    | grantsAndDenials
+    ;
+
+grantsAndDenials
+    :
+    ID_grantsAndDenials ( SP )+
+    OPEN_CURLY ( SP )*
+        ( grantAndDenial ( SP )*
+            ( SEP ( SP )* grantAndDenial ( SP )*
+            )*
+        )?
+    CLOSE_CURLY
+    ;
+
+grantAndDenial
+    :
+    ID_grantAdd 
+    | ID_denyAdd
+    | ID_grantDiscloseOnError
+    | ID_denyDiscloseOnError 
+    | ID_grantRead
+    | ID_denyRead
+    | ID_grantRemove
+    | ID_denyRemove 
+    //-- permissions that may be used only in conjunction
+    //-- with the entry component
+    | ID_grantBrowse
+    | ID_denyBrowse
+    | ID_grantExport
+    | ID_denyExport
+    | ID_grantImport
+    | ID_denyImport
+    | ID_grantModify
+    | ID_denyModify
+    | ID_grantRename
+    | ID_denyRename
+    | ID_grantReturnDN
+    | ID_denyReturnDN
+    //-- permissions that may be used in conjunction
+    //-- with any component, except entry, of ProtectedItems
+    | ID_grantCompare
+    | ID_denyCompare
+    | ID_grantFilterMatch
+    | ID_denyFilterMatch
+    | ID_grantInvoke
+    | ID_denyInvoke
+    ;
+
+userClasses
+    :
+    ID_userClasses ( SP )+
+    OPEN_CURLY ( SP )*
+        (
+            userClass ( SP )*
+                ( SEP ( SP )* userClass ( SP )* )*
+        )?
+    CLOSE_CURLY
+    ;
+
+userClass
+    :
+    allUsers
+    | thisEntry
+    | parentOfEntry
+    | name
+    | userGroup
+    | subtree
+    ;
+
+allUsers
+    :
+    ID_allUsers
+    ;
+
+thisEntry
+    :
+    ID_thisEntry
+    ;
+
+parentOfEntry
+    :
+    ID_parentOfEntry
+    ;
+
+name
+    :
+    ID_name ( SP )+ 
+        OPEN_CURLY ( SP )*
+            distinguishedName ( SP )*
+                ( SEP ( SP )* distinguishedName ( SP )*
+            )*
+        CLOSE_CURLY
+    ;
+
+userGroup
+    :
+    ID_userGroup ( SP )+ 
+        OPEN_CURLY ( SP )*
+            distinguishedName ( SP )*
+                ( SEP ( SP )* distinguishedName ( SP )* )*
+        CLOSE_CURLY
+    ;
+
+subtree
+    :
+    ID_subtree ( SP )+
+        OPEN_CURLY ( SP )*
+            subtreeSpecification ( SP )*
+                ( SEP ( SP )* subtreeSpecification ( SP )* )*
+        CLOSE_CURLY
+    ;
+
+userPermissions
+    :
+    ID_userPermissions ( SP )+
+        OPEN_CURLY ( SP )*
+            ( userPermission ( SP )*
+                ( SEP ( SP )* userPermission ( SP )* )*
+            )?
+        CLOSE_CURLY
+    ;
+
+userPermission
+     :
+     OPEN_CURLY ( SP )*
+         anyUserPermission ( SP )*
+             ( SEP ( SP )* anyUserPermission ( SP )* )*
+     CLOSE_CURLY
+     ;
+
+anyUserPermission
+    :
+    precedence
+    | protectedItems
+    | grantsAndDenials
+    ;
+
+subtreeSpecification
+    :
+    OPEN_CURLY ( SP )*
+        ( subtreeSpecificationComponent ( SP )*
+            ( SEP ( SP )* subtreeSpecificationComponent ( SP )* )* )?
+    CLOSE_CURLY
+    ;
+
+subtreeSpecificationComponent
+    :
+    ss_base
+    | ss_specificExclusions
+    | ss_minimum
+    | ss_maximum
+    ;
+
+ss_base
+    :
+    ID_base ( SP )+ distinguishedName
+    ;
+
+ss_specificExclusions
+    :
+    ID_specificExclusions ( SP )+ specificExclusions
+    ;
+
+specificExclusions
+    :
+    OPEN_CURLY ( SP )*
+        ( specificExclusion ( SP )*
+            ( SEP ( SP )* specificExclusion ( SP )* )*
+        )?
+    CLOSE_CURLY
+    ;
+
+specificExclusion
+    :
+    chopBefore | chopAfter
+    ;
+
+chopBefore
+    :
+    ID_chopBefore ( SP )* COLON ( SP )* distinguishedName
+    ;
+
+chopAfter
+    :
+    ID_chopAfter ( SP )* COLON ( SP )* distinguishedName
+    ;
+
+ss_minimum
+    :
+    ID_minimum ( SP )+ baseDistance
+    ;
+
+ss_maximum
+    :
+    ID_maximum ( SP )+ baseDistance
+    ;
+
+distinguishedName
+    :
+    SAFEUTF8STRING
+    ;
+
+baseDistance
+    :
+    INTEGER
+    ;
+
+oid
+    :
+    ( DESCR | NUMERICOID )
+    ;
+
+refinement
+    :
+    item | and | or | not
+    ;
+
+item
+    :
+    ID_item ( SP )* COLON ( SP )* oid
+    ;
+
+and
+    :
+    ID_and ( SP )* COLON ( SP )* refinements
+    ;
+
+or
+    :
+    ID_or ( SP )* COLON ( SP )* refinements
+    ;
+
+not
+    :
+    ID_not ( SP )* COLON ( SP )* refinements
+    ;
+
+refinements
+    :
+    OPEN_CURLY ( SP )*
+    (
+        refinement ( SP )*
+        ( SEP ( SP )* refinement ( SP )* )*
+    )? CLOSE_CURLY
+    ;
+
+    
+//  ----------------------------------------------------------------------------
+//  lexer class definition
+//  ----------------------------------------------------------------------------
+
+/**
+  * The parser's primary lexer.
+  *
+  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+   */
+class AntlrACIItemCheckerLexer extends Lexer;
+
+
+//  ----------------------------------------------------------------------------
+//  lexer options
+//  ----------------------------------------------------------------------------
+
+options
+{
+    k = 2;
+    charVocabulary = '\3'..'\377';
+}
+
+
+//----------------------------------------------------------------------------
+// tokens
+//----------------------------------------------------------------------------
+
+tokens
+{
+    ID_identificationTag = "identificationTag";
+    ID_precedence = "precedence";
+    ID_FALSE = "FALSE";
+    ID_TRUE = "TRUE";
+    ID_none = "none";
+    ID_simple = "simple";
+    ID_strong = "strong";
+    ID_level = "level";
+    ID_basicLevels = "basicLevels";
+    ID_localQualifier = "localQualifier";
+    ID_signed = "signed";
+    ID_authenticationLevel = "authenticationLevel";
+    ID_itemOrUserFirst = "itemOrUserFirst";
+    ID_itemFirst = "itemFirst";
+    ID_userFirst = "userFirst";
+    ID_protectedItems = "protectedItems";
+    ID_classes = "classes";
+    ID_entry = "entry";
+    ID_allUserAttributeTypes = "allUserAttributeTypes";
+    ID_attributeType = "attributeType";
+    ID_allAttributeValues = "allAttributeValues";
+    ID_allUserAttributeTypesAndValues = "allUserAttributeTypesAndValues";
+    ID_selfValue = "selfValue";
+    ID_item = "item";
+    ID_and = "and";
+    ID_or = "or";
+    ID_not = "not";
+    ID_rangeOfValues = "rangeOfValues";
+    ID_maxValueCount = "maxValueCount";
+    ID_type = "type";
+    ID_maxCount = "maxCount";
+    ID_maxImmSub = "maxImmSub";
+    ID_restrictedBy = "restrictedBy";
+    ID_valuesIn = "valuesIn";
+    ID_userClasses = "userClasses";
+    ID_base = "base";
+    ID_specificExclusions = "specificExclusions";
+    ID_chopBefore = "chopBefore";
+    ID_chopAfter = "chopAfter";
+    ID_minimum = "minimum";
+    ID_maximum = "maximum";
+    ID_specificationFilter = "specificationFilter";
+    ID_grantsAndDenials = "grantsAndDenials";
+    ID_itemPermissions = "itemPermissions";
+    ID_userPermissions = "userPermissions";
+    ID_allUsers = "allUsers";
+    ID_thisEntry = "thisEntry";
+    ID_parentOfEntry = "parentOfEntry";
+    ID_subtree = "subtree";
+    ID_name = "name";
+    ID_userGroup = "userGroup";
+
+    ID_grantAdd = "grantAdd"; // (0),
+    ID_denyAdd = "denyAdd";  // (1),
+    ID_grantDiscloseOnError = "grantDiscloseOnError";  // (2),
+    ID_denyDiscloseOnError = "denyDiscloseOnError";  // (3),
+    ID_grantRead = "grantRead";  // (4),
+    ID_denyRead = "denyRead";  // (5),
+    ID_grantRemove = "grantRemove";  // (6),
+    ID_denyRemove = "denyRemove";  // (7),
+    //-- permissions that may be used only in conjunction
+    //-- with the entry component
+    ID_grantBrowse = "grantBrowse";  // (8),
+    ID_denyBrowse = "denyBrowse";  // (9),
+    ID_grantExport = "grantExport";  // (10),
+    ID_denyExport = "denyExport";  // (11),
+    ID_grantImport = "grantImport";  // (12),
+    ID_denyImport = "denyImport";  // (13),
+    ID_grantModify = "grantModify";  // (14),
+    ID_denyModify = "denyModify";  // (15),
+    ID_grantRename = "grantRename";  // (16),
+    ID_denyRename = "denyRename";  // (17),
+    ID_grantReturnDN = "grantReturnDN";  // (18),
+    ID_denyReturnDN = "denyReturnDN";  // (19),
+    //-- permissions that may be used in conjunction
+    //-- with any component, except entry, of ProtectedItems
+    ID_grantCompare = "grantCompare";  // (20),
+    ID_denyCompare = "denyCompare";  // (21),
+    ID_grantFilterMatch = "grantFilterMatch";  // (22),
+    ID_denyFilterMatch = "denyFilterMatch";  // (23),
+    ID_grantInvoke = "grantInvoke";  // (24),
+    ID_denyInvoke = "denyInvoke";  // (25)
+}
+
+
+// ----------------------------------------------------------------------------
+//  lexer initialization
+// ----------------------------------------------------------------------------
+
+
+// ----------------------------------------------------------------------------
+// attribute description lexer rules from models
+// ----------------------------------------------------------------------------
+
+//  This is all messed up - could not figure out how to get antlr to represent
+//  the safe UTF-8 character set from RFC 3642 for production SafeUTF8Character
+
+protected SAFEUTF8CHAR :
+    '\u0001'..'\u0021' |
+    '\u0023'..'\u007F' |
+    '\u00c0'..'\u00d6' |
+    '\u00d8'..'\u00f6' |
+    '\u00f8'..'\u00ff' |
+    '\u0100'..'\u1fff' |
+    '\u3040'..'\u318f' |
+    '\u3300'..'\u337f' |
+    '\u3400'..'\u3d2d' |
+    '\u4e00'..'\u9fff' |
+    '\uf900'..'\ufaff' ;
+
+OPEN_CURLY : '{' ;
+
+CLOSE_CURLY : '}' ;
+
+SEP : ',' ;
+
+SP : ' ' | '\t' | '\n' { newline(); } | '\r' ;
+
+COLON : ':' ;
+
+protected DIGIT : '0' | LDIGIT ;
+
+protected LDIGIT : '1'..'9' ;
+
+protected ALPHA : 'A'..'Z' | 'a'..'z' ;
+
+protected INTEGER : DIGIT | ( LDIGIT ( DIGIT )+ ) ;
+
+protected HYPHEN : '-' ;
+
+protected NUMERICOID : INTEGER ( DOT INTEGER )+ ;
+
+protected DOT : '.' ;
+
+INTEGER_OR_NUMERICOID
+    :
+    ( INTEGER DOT ) => NUMERICOID
+    {
+        $setType( NUMERICOID );
+    }
+    |
+    INTEGER
+    {
+        $setType( INTEGER );
+    }
+    ;
+
+SAFEUTF8STRING : '"'! ( SAFEUTF8CHAR )* '"'! ;
+
+DESCR // THIS RULE ALSO STANDS FOR AN IDENTIFIER
+    :
+    ( "attributeValue" ( SP! )+ '{' ) =>
+      "attributeValue"! ( SP! )+ '{'! ( options { greedy = false; } : . )* '}'!
+      { $setType( ATTRIBUTE_VALUE_CANDIDATE ); }
+    | ( "rangeOfValues" ( SP! )+ '(' ) =>
+      "rangeOfValues"! ( SP! )+ FILTER
+      { $setType( RANGE_OF_VALUES_CANDIDATE ); }
+    | ALPHA ( ALPHA | DIGIT | HYPHEN )*
+    ;
+
+protected FILTER : '(' ( ( '&' (SP)* (FILTER)+ ) | ( '|' (SP)* (FILTER)+ ) | ( '!' (SP)* FILTER ) | FILTER_VALUE ) ')' (SP)* ;
+
+protected FILTER_VALUE : (options{greedy=true;}: ~( ')' | '(' | '&' | '|' | '!' ) ( ~(')') )* ) ;
+
+    
\ No newline at end of file

Added: directory/shared/trunk/ldap/src/main/antlr/SubtreeSpecificationChecker.g
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/antlr/SubtreeSpecificationChecker.g?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/antlr/SubtreeSpecificationChecker.g (added)
+++ directory/shared/trunk/ldap/src/main/antlr/SubtreeSpecificationChecker.g Thu Jul 15 10:04:06 2010
@@ -0,0 +1,466 @@
+header
+{
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+
+package org.apache.directory.shared.ldap.subtree;
+
+import org.apache.directory.shared.ldap.name.DN;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.LeafNode;
+import org.apache.directory.shared.ldap.filter.BranchNode;
+import org.apache.directory.shared.ldap.filter.AndNode;
+import org.apache.directory.shared.ldap.filter.OrNode;
+import org.apache.directory.shared.ldap.filter.NotNode;
+import org.apache.directory.shared.ldap.filter.EqualityNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.util.ComponentsMonitor;
+import org.apache.directory.shared.ldap.util.OptionalComponentsMonitor;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser class definition
+// ----------------------------------------------------------------------------
+
+/**
+ * The antlr generated subtree specification parser.
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+class AntlrSubtreeSpecificationChecker extends Parser;
+
+
+// ----------------------------------------------------------------------------
+// parser options
+// ----------------------------------------------------------------------------
+
+options
+{
+    k = 1;
+    defaultErrorHandler = false;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser initialization
+// ----------------------------------------------------------------------------
+
+{
+    private static final Logger log = LoggerFactory.getLogger( AntlrSubtreeSpecificationChecker.class );
+    
+    private ComponentsMonitor subtreeSpecificationComponentsMonitor = null;
+    
+    /** The SchemaManager */
+    private SchemaManager schemaManager;
+
+    /**
+     * Initiaize the checker
+     */
+    public void init( SchemaManager schemaManager )
+    {
+        this.schemaManager = schemaManager;
+    }
+    
+
+    private int token2Integer( Token token ) throws RecognitionException
+    {
+        int i = 0;
+        
+        try
+        {
+            i = Integer.parseInt( token.getText());
+        }
+        catch ( NumberFormatException e )
+        {
+            throw new RecognitionException( "Value of INTEGER token " +
+                                            token.getText() +
+                                            " cannot be converted to an Integer" );
+        }
+        
+        return i;
+    }
+}
+
+
+// ----------------------------------------------------------------------------
+// parser productions
+// ----------------------------------------------------------------------------
+
+wrapperEntryPoint
+{
+    log.debug( "entered wrapperEntryPoint()" );
+} :
+    subtreeSpecification "end"
+    ;
+
+subtreeSpecification
+{
+    log.debug( "entered subtreeSpecification()" );
+    subtreeSpecificationComponentsMonitor = new OptionalComponentsMonitor( 
+            new String [] { "base", "specificExclusions", "minimum", "maximum", "specificationFilter" } );
+}
+    :
+    OPEN_CURLY ( SP )*
+        ( subtreeSpecificationComponent ( SP )*
+            ( SEP ( SP )* subtreeSpecificationComponent ( SP )* )* )?
+    CLOSE_CURLY
+    ;
+
+subtreeSpecificationComponent
+{
+    log.debug( "entered subtreeSpecification()" );
+}
+    :
+    ss_base
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "base" );
+    }
+    | ss_specificExclusions
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "specificExclusions" );
+    }
+    | ss_minimum
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "minimum" );
+    }
+    | ss_maximum
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "maximum" );
+    }
+    | ss_specificationFilter
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "specificationFilter" );
+    }
+    ;
+    exception
+    catch [IllegalArgumentException e]
+    {
+        throw new RecognitionException( e.getMessage() );
+    }
+
+ss_base
+{
+    log.debug( "entered ss_base()" );
+}
+    :
+    ID_base ( SP )+ distinguishedName
+    ;
+
+ss_specificExclusions
+{
+    log.debug( "entered ss_specificExclusions()" );
+}
+    :
+    ID_specificExclusions ( SP )+ specificExclusions
+    ;
+
+specificExclusions
+{
+    log.debug( "entered specificExclusions()" );
+}
+    :
+    OPEN_CURLY ( SP )*
+        ( specificExclusion ( SP )*
+            ( SEP ( SP )* specificExclusion ( SP )* )*
+        )?
+    CLOSE_CURLY
+    ;
+
+specificExclusion
+{
+    log.debug( "entered specificExclusion()" );
+}
+    :
+    chopBefore | chopAfter
+    ;
+
+chopBefore
+{
+    log.debug( "entered chopBefore()" );
+}
+    :
+    ID_chopBefore ( SP )* COLON ( SP )* distinguishedName
+    ;
+
+chopAfter
+{
+    log.debug( "entered chopAfter()" );
+}
+    :
+    ID_chopAfter ( SP )* COLON ( SP )* distinguishedName
+    ;
+
+ss_minimum
+{
+    log.debug( "entered ss_minimum()" );
+}
+    :
+    ID_minimum ( SP )+ baseDistance
+    ;
+
+ss_maximum
+{
+    log.debug( "entered ss_maximum()" );
+}
+    :
+    ID_maximum ( SP )+ baseDistance
+    ;
+
+ss_specificationFilter
+{
+    log.debug( "entered ss_specificationFilter()" );
+}
+    :
+    ID_specificationFilter 
+    ( SP )+ 
+    (
+        ( refinement )
+        |
+        ( filter )
+    )
+    ;
+    
+filter
+{
+    log.debug( "entered filter()" );
+}
+    :
+    ( filterToken:FILTER { FilterParser.parse( filterToken.getText() ); } )
+    ;
+    exception
+    catch [Exception e]
+    {
+        throw new RecognitionException( "filterParser failed. " + e.getMessage() );
+    }
+
+    
+distinguishedName
+{
+    log.debug( "entered distinguishedName()" );
+}
+    :
+    token:SAFEUTF8STRING
+    {
+        new DN( token.getText() );
+        log.debug( "recognized a DistinguishedName: " + token.getText() );
+    }
+    ;
+    exception
+    catch [Exception e]
+    {
+        throw new RecognitionException( "dnParser failed for " + token.getText() + " " + e.getMessage() );
+    }
+
+baseDistance
+{
+    log.debug( "entered baseDistance()" );
+}
+    :
+    token:INTEGER
+    {
+        token2Integer(token);
+    }
+    ;
+
+oid
+{
+    log.debug( "entered oid()" );
+     Token token = null;
+}
+    :
+    { token = LT( 1 ); } // an interesting trick goes here ;-)
+    ( DESCR | NUMERICOID )
+    {
+        log.debug( "recognized an oid: " + token.getText() );
+    }
+    ;
+
+refinement
+{
+    log.debug( "entered refinement()" );
+}
+    :
+    item | and | or | not
+    ;
+
+item
+{
+    log.debug( "entered item()" );
+}
+    :
+    ID_item ( SP )* COLON ( SP )* oid
+    ;
+
+and
+{
+    log.debug( "entered and()" );
+}
+    :
+    ID_and ( SP )* COLON ( SP )* refinements
+    ;
+
+or
+{
+    log.debug( "entered or()" );
+}
+    :
+    ID_or ( SP )* COLON ( SP )* refinements
+    ;
+
+not
+{
+    log.debug( "entered not()" );
+}
+    :
+    ID_not ( SP )* COLON ( SP )* refinement
+    ;
+
+refinements
+{
+    log.debug( "entered refinements()" );
+}
+    :
+    OPEN_CURLY ( SP )*
+    (
+        refinement ( SP )*
+            ( SEP ( SP )* refinement ( SP )* )*
+    )? CLOSE_CURLY
+    ;
+
+
+// ----------------------------------------------------------------------------
+// lexer class definition
+// ----------------------------------------------------------------------------
+
+/**
+ * The parser's primary lexer.
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+class AntlrSubtreeSpecificationCheckerLexer extends Lexer;
+
+
+// ----------------------------------------------------------------------------
+// lexer options
+// ----------------------------------------------------------------------------
+
+options
+{
+    k = 2;
+
+    charVocabulary = '\u0001'..'\u0127';
+}
+
+tokens
+{
+    ID_base = "base";
+    ID_specificExclusions = "specificExclusions";
+    ID_chopBefore = "chopBefore";
+    ID_chopAfter = "chopAfter";
+    ID_minimum = "minimum";
+    ID_maximum = "maximum";
+    ID_specificationFilter = "specificationFilter";
+    ID_item = "item";
+    ID_and = "and";
+    ID_or = "or";
+    ID_not = "not";
+}
+
+
+//----------------------------------------------------------------------------
+// lexer initialization
+//----------------------------------------------------------------------------
+
+{
+    private static final Logger log = LoggerFactory.getLogger( AntlrSubtreeSpecificationLexer.class );
+}
+
+
+// ----------------------------------------------------------------------------
+// attribute description lexer rules from models
+// ----------------------------------------------------------------------------
+
+SP : ' ';
+
+COLON : ':' { log.debug( "matched COLON(':')" ); } ;
+
+OPEN_CURLY : '{' { log.debug( "matched LBRACKET('{')" ); } ;
+
+CLOSE_CURLY : '}' { log.debug( "matched RBRACKET('}')" ); } ;
+
+SEP : ',' { log.debug( "matched SEP(',')" ); } ;
+
+SAFEUTF8STRING : '"'! ( SAFEUTF8CHAR )* '"'! { log.debug( "matched SAFEUTF8CHAR: \"" + getText() + "\"" ); } ;
+
+DESCR : ALPHA ( ALPHA | DIGIT | '-' )* { log.debug( "matched DESCR" ); } ;
+
+INTEGER_OR_NUMERICOID
+    :
+    ( INTEGER DOT ) => NUMERICOID
+    {
+        $setType( NUMERICOID );
+    }
+    |
+    INTEGER
+    {
+        $setType( INTEGER );
+    }
+    ;
+
+protected INTEGER: DIGIT | ( LDIGIT ( DIGIT )+ ) { log.debug( "matched INTEGER: " + getText() ); } ;
+
+protected NUMERICOID: INTEGER ( DOT INTEGER )+ { log.debug( "matched NUMERICOID: " + getText() ); } ;
+
+protected DOT: '.' ;
+
+protected DIGIT: '0' | LDIGIT ;
+
+protected LDIGIT: '1'..'9' ;
+
+protected ALPHA: 'A'..'Z' | 'a'..'z' ;
+
+// This is all messed up - could not figure out how to get antlr to represent
+// the safe UTF-8 character set from RFC 3642 for production SafeUTF8Character
+
+protected SAFEUTF8CHAR:
+    '\u0001'..'\u0021' |
+    '\u0023'..'\u007F' |
+    '\u00c0'..'\u00d6' |
+    '\u00d8'..'\u00f6' |
+    '\u00f8'..'\u00ff' |
+    '\u0100'..'\u1fff' |
+    '\u3040'..'\u318f' |
+    '\u3300'..'\u337f' |
+    '\u3400'..'\u3d2d' |
+    '\u4e00'..'\u9fff' |
+    '\uf900'..'\ufaff' ;
+
+FILTER : '(' ( ( '&' (SP)* (FILTER)+ ) | ( '|' (SP)* (FILTER)+ ) | ( '!' (SP)* FILTER ) | FILTER_VALUE ) ')' (SP)* ;
+
+protected FILTER_VALUE : (options{greedy=true;}: ~( ')' | '(' | '&' | '|' | '!' ) ( ~(')') )* ) ;
+    
\ No newline at end of file

Added: directory/shared/trunk/ldap/src/main/antlr/subtree-specification.g
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/antlr/subtree-specification.g?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/antlr/subtree-specification.g (added)
+++ directory/shared/trunk/ldap/src/main/antlr/subtree-specification.g Thu Jul 15 10:04:06 2010
@@ -0,0 +1,598 @@
+header
+{
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+
+package org.apache.directory.shared.ldap.subtree;
+
+import java.util.Set;
+import java.util.Map;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.directory.shared.ldap.name.DN;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.LeafNode;
+import org.apache.directory.shared.ldap.filter.BranchNode;
+import org.apache.directory.shared.ldap.filter.AndNode;
+import org.apache.directory.shared.ldap.filter.OrNode;
+import org.apache.directory.shared.ldap.filter.NotNode;
+import org.apache.directory.shared.ldap.filter.EqualityNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.schema.ObjectClass;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
+import org.apache.directory.shared.ldap.subtree.SubtreeSpecification;
+import org.apache.directory.shared.ldap.subtree.SubtreeSpecificationModifier;
+import org.apache.directory.shared.ldap.schema.NormalizerMappingResolver;
+import org.apache.directory.shared.ldap.schema.normalizers.OidNormalizer;
+import org.apache.directory.shared.ldap.util.ComponentsMonitor;
+import org.apache.directory.shared.ldap.util.OptionalComponentsMonitor;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.StringValue;
+import org.apache.directory.shared.ldap.exception.LdapException;
+import org.apache.directory.shared.ldap.schema.AttributeType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser class definition
+// ----------------------------------------------------------------------------
+
+/**
+ * The antlr generated subtree specification parser.
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+class AntlrSubtreeSpecificationParser extends Parser;
+
+
+// ----------------------------------------------------------------------------
+// parser options
+// ----------------------------------------------------------------------------
+
+options
+{
+    k = 1;
+    defaultErrorHandler = false;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser initialization
+// ----------------------------------------------------------------------------
+
+{
+    private static final Logger log = LoggerFactory.getLogger( AntlrSubtreeSpecificationParser.class );
+    
+    private NormalizerMappingResolver resolver;
+    
+    private Set<DN> chopBeforeExclusions = null;
+    private Set<DN> chopAfterExclusions = null;
+
+    private SubtreeSpecificationModifier ssModifier = null;
+    
+    /** The schemaManager */
+    private SchemaManager schemaManager;
+    
+    /** The ObjectClass AT */
+    AttributeType OBJECT_CLASS_AT;
+    
+    private ComponentsMonitor subtreeSpecificationComponentsMonitor = null;
+    
+    
+
+    /**
+     * Does nothing.
+     */
+    public void init( SchemaManager schemaManager )
+    {
+        this.schemaManager = schemaManager;
+        OBJECT_CLASS_AT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
+        
+    }
+    
+    
+    public void setNormalizerMappingResolver( NormalizerMappingResolver resolver )
+    {
+        this.resolver = resolver;
+    }
+    
+    
+    public boolean isNormalizing()
+    {
+        return this.resolver != null;
+    }
+    
+
+    private int token2Integer( Token token ) throws RecognitionException
+    {
+        int i = 0;
+        
+        try
+        {
+            i = Integer.parseInt( token.getText());
+        }
+        catch ( NumberFormatException e )
+        {
+            throw new RecognitionException( "Value of INTEGER token " +
+                                            token.getText() +
+                                            " cannot be converted to an Integer" );
+        }
+        
+        return i;
+    }
+}
+
+
+// ----------------------------------------------------------------------------
+// parser productions
+// ----------------------------------------------------------------------------
+
+wrapperEntryPoint returns [SubtreeSpecification ss]
+{
+    log.debug( "entered wrapperEntryPoint()" );
+    ss = null;
+    SubtreeSpecification tempSs = null;
+} :
+    tempSs=subtreeSpecification "end"
+    {
+        ss = tempSs;
+    }
+    ;
+
+subtreeSpecification returns [SubtreeSpecification ss]
+{
+    log.debug( "entered subtreeSpecification()" );
+    // clear out ss, ssModifier, subtreeSpecificationComponentsMonitor,
+    // chopBeforeExclusions and chopAfterExclusions
+    // in case something is left from the last parse
+    ss = null;
+    ssModifier = new SubtreeSpecificationModifier();
+    subtreeSpecificationComponentsMonitor = new OptionalComponentsMonitor( 
+            new String [] { "base", "specificExclusions", "minimum", "maximum", "specificationFilter" } );
+    chopBeforeExclusions = new HashSet<DN>();
+    chopAfterExclusions = new HashSet<DN>();
+    // always create a new filter parser in case we may have some statefulness problems with it
+}
+    :
+    OPEN_CURLY ( SP )*
+        ( subtreeSpecificationComponent ( SP )*
+            ( SEP ( SP )* subtreeSpecificationComponent ( SP )* )* )?
+    CLOSE_CURLY
+    {
+        ss = ssModifier.getSubtreeSpecification();
+    }
+    ;
+
+subtreeSpecificationComponent
+{
+    log.debug( "entered subtreeSpecification()" );
+}
+    :
+    ss_base
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "base" );
+    }
+    | ss_specificExclusions
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "specificExclusions" );
+    }
+    | ss_minimum
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "minimum" );
+    }
+    | ss_maximum
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "maximum" );
+    }
+    | ss_specificationFilter
+    {
+        subtreeSpecificationComponentsMonitor.useComponent( "specificationFilter" );
+    }
+    ;
+    exception
+    catch [IllegalArgumentException e]
+    {
+        throw new RecognitionException( e.getMessage() );
+    }
+
+ss_base
+{
+    log.debug( "entered ss_base()" );
+    DN base = null;
+}
+    :
+    ID_base ( SP )+ base=distinguishedName
+    {
+        ssModifier.setBase( base );
+    }
+    ;
+
+ss_specificExclusions
+{
+    log.debug( "entered ss_specificExclusions()" );
+}
+    :
+    ID_specificExclusions ( SP )+ specificExclusions
+    {
+        ssModifier.setChopBeforeExclusions( chopBeforeExclusions );
+        ssModifier.setChopAfterExclusions( chopAfterExclusions );
+    }
+    ;
+
+specificExclusions
+{
+    log.debug( "entered specificExclusions()" );
+}
+    :
+    OPEN_CURLY ( SP )*
+        ( specificExclusion ( SP )*
+            ( SEP ( SP )* specificExclusion ( SP )* )*
+        )?
+    CLOSE_CURLY
+    ;
+
+specificExclusion
+{
+    log.debug( "entered specificExclusion()" );
+}
+    :
+    chopBefore | chopAfter
+    ;
+
+chopBefore
+{
+    log.debug( "entered chopBefore()" );
+    DN chopBeforeExclusion = null;
+}
+    :
+    ID_chopBefore ( SP )* COLON ( SP )* chopBeforeExclusion=distinguishedName
+    {
+        chopBeforeExclusions.add( chopBeforeExclusion );
+    }
+    ;
+
+chopAfter
+{
+    log.debug( "entered chopAfter()" );
+    DN chopAfterExclusion = null;
+}
+    :
+    ID_chopAfter ( SP )* COLON ( SP )* chopAfterExclusion=distinguishedName
+    {
+        chopAfterExclusions.add( chopAfterExclusion );
+    }
+    ;
+
+ss_minimum
+{
+    log.debug( "entered ss_minimum()" );
+    int minimum = 0;
+}
+    :
+    ID_minimum ( SP )+ minimum=baseDistance
+    {
+        ssModifier.setMinBaseDistance( minimum );
+    }
+    ;
+
+ss_maximum
+{
+    log.debug( "entered ss_maximum()" );
+    int maximum = 0;
+}
+    :
+    ID_maximum ( SP )+ maximum=baseDistance
+    {
+        ssModifier.setMaxBaseDistance( maximum );
+    }
+    ;
+
+ss_specificationFilter
+{
+    log.debug( "entered ss_specificationFilter()" );
+    ExprNode filterExpr = null;
+}
+    :
+    ID_specificationFilter 
+    ( SP )+ 
+    (
+        ( filterExpr=refinement )
+        |
+        ( filterExpr=filter )
+    )
+    { ssModifier.setRefinement( filterExpr ); }
+    ;
+    
+    
+filter returns [ ExprNode filterExpr = null ]
+{
+    log.debug( "entered filter()" );
+}
+    :
+    ( filterToken:FILTER { filterExpr=FilterParser.parse( schemaManager, filterToken.getText() ); } )
+    ;
+    exception
+    catch [Exception e]
+    {
+        throw new RecognitionException( "filterParser failed. " + e.getMessage() );
+    }
+    
+distinguishedName returns [ DN name ] 
+{
+    log.debug( "entered distinguishedName()" );
+    name = null;
+}
+    :
+    token:SAFEUTF8STRING
+    {
+        name = new DN( token.getText() );
+        name.normalize( schemaManager.getNormalizerMapping() );
+        
+        log.debug( "recognized a DistinguishedName: " + token.getText() );
+    }
+    ;
+    exception
+    catch [Exception e]
+    {
+        throw new RecognitionException( "dnParser failed for " + token.getText() + " " + e.getMessage() );
+    }
+
+baseDistance returns [ int distance ]
+{
+    log.debug( "entered baseDistance()" );
+    distance = 0;
+}
+    :
+    token:INTEGER
+    {
+        distance = token2Integer( token );
+    }
+    ;
+
+oid returns [ String result ]
+{
+    log.debug( "entered oid()" );
+    result = null;
+    Token token = null;
+}
+    :
+    { token = LT( 1 ); } // an interesting trick goes here ;-)
+    ( DESCR | NUMERICOID )
+    {
+        result = token.getText();
+        log.debug( "recognized an oid: " + result );
+    }
+    ;
+
+refinement returns [ ExprNode node ]
+{
+    log.debug( "entered refinement()" );
+    node = null;
+}
+    :
+    node=item | node=and | node=or | node=not
+    ;
+
+item returns [ LeafNode node ]
+{
+    log.debug( "entered item()" );
+    node = null;
+    String oid = null;
+    ObjectClass objectClass;
+}
+    :
+    ID_item ( SP )* COLON ( SP )* oid=oid
+    {
+        try
+        {
+            objectClass = schemaManager.lookupObjectClassRegistry( oid );
+        }
+        catch ( LdapException le )
+        {
+              // The oid does not exist
+              // TODO : deal with such an exception
+        }
+        
+        node = new EqualityNode( OBJECT_CLASS_AT, new StringValue( oid ) );
+    }
+    ;
+
+and returns [ BranchNode node ]
+{
+    log.debug( "entered and()" );
+    node = null;
+    List<ExprNode> children = null; 
+}
+    :
+    ID_and ( SP )* COLON ( SP )* children=refinements
+    {
+        node = new AndNode( children );
+    }
+    ;
+
+or returns [ BranchNode node ]
+{
+    log.debug( "entered or()" );
+    node = null;
+    List<ExprNode> children = null; 
+}
+    :
+    ID_or ( SP )* COLON ( SP )* children=refinements
+    {
+        node = new OrNode( children );
+    }
+    ;
+
+not returns [ BranchNode node ]
+{
+    log.debug( "entered not()" );
+    node = null;
+    ExprNode child = null;
+}
+    :
+    ID_not ( SP )* COLON ( SP )* child=refinement
+    {
+        node = new NotNode( child );
+    }
+    ;
+
+refinements returns [ List<ExprNode> children ]
+{
+    log.debug( "entered refinements()" );
+    children = null;
+    ExprNode child = null;
+    List<ExprNode> tempChildren = new ArrayList<ExprNode>();
+}
+    :
+    OPEN_CURLY ( SP )*
+    (
+        child=refinement ( SP )*
+        {
+            tempChildren.add( child );
+        }
+        ( SEP ( SP )* child=refinement ( SP )*
+        {
+            tempChildren.add( child );
+        } )*
+    )? CLOSE_CURLY
+    {
+        children = tempChildren;
+    }
+    ;
+
+
+// ----------------------------------------------------------------------------
+// lexer class definition
+// ----------------------------------------------------------------------------
+
+/**
+ * The parser's primary lexer.
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+class AntlrSubtreeSpecificationLexer extends Lexer;
+
+
+// ----------------------------------------------------------------------------
+// lexer options
+// ----------------------------------------------------------------------------
+
+options
+{
+    k = 5;
+
+    charVocabulary = '\u0001'..'\u0127';
+}
+
+tokens
+{
+    ID_base = "base";
+    ID_specificExclusions = "specificExclusions";
+    ID_chopBefore = "chopBefore";
+    ID_chopAfter = "chopAfter";
+    ID_minimum = "minimum";
+    ID_maximum = "maximum";
+    ID_specificationFilter = "specificationFilter";
+    ID_item = "item";
+    ID_and = "and";
+    ID_or = "or";
+    ID_not = "not";
+}
+
+
+//----------------------------------------------------------------------------
+// lexer initialization
+//----------------------------------------------------------------------------
+
+{
+    private static final Logger log = LoggerFactory.getLogger( AntlrSubtreeSpecificationLexer.class );
+}
+
+
+// ----------------------------------------------------------------------------
+// attribute description lexer rules from models
+// ----------------------------------------------------------------------------
+
+SP : ' ';
+
+COLON : ':' { log.debug( "matched COLON(':')" ); } ;
+
+OPEN_CURLY : '{' { log.debug( "matched LBRACKET('{')" ); } ;
+
+CLOSE_CURLY : '}' { log.debug( "matched RBRACKET('}')" ); } ;
+
+SEP : ',' { log.debug( "matched SEP(',')" ); } ;
+
+SAFEUTF8STRING : '"'! ( SAFEUTF8CHAR )* '"'! { log.debug( "matched SAFEUTF8CHAR: \"" + getText() + "\"" ); } ;
+
+DESCR : ALPHA ( ALPHA | DIGIT | '-' )* { log.debug( "matched DESCR" ); } ;
+
+INTEGER_OR_NUMERICOID
+    :
+    ( INTEGER DOT ) => NUMERICOID
+    {
+        $setType( NUMERICOID );
+    }
+    |
+    INTEGER
+    {
+        $setType( INTEGER );
+    }
+    ;
+
+protected INTEGER: DIGIT | ( LDIGIT ( DIGIT )+ ) { log.debug( "matched INTEGER: " + getText() ); } ;
+
+protected NUMERICOID: INTEGER ( DOT INTEGER )+ { log.debug( "matched NUMERICOID: " + getText() ); } ;
+
+protected DOT: '.' ;
+
+protected DIGIT: '0' | LDIGIT ;
+
+protected LDIGIT: '1'..'9' ;
+
+protected ALPHA: 'A'..'Z' | 'a'..'z' ;
+
+// This is all messed up - could not figure out how to get antlr to represent
+// the safe UTF-8 character set from RFC 3642 for production SafeUTF8Character
+
+protected SAFEUTF8CHAR:
+    '\u0001'..'\u0021' |
+    '\u0023'..'\u007F' |
+    '\u00c0'..'\u00d6' |
+    '\u00d8'..'\u00f6' |
+    '\u00f8'..'\u00ff' |
+    '\u0100'..'\u1fff' |
+    '\u3040'..'\u318f' |
+    '\u3300'..'\u337f' |
+    '\u3400'..'\u3d2d' |
+    '\u4e00'..'\u9fff' |
+    '\uf900'..'\ufaff' ;
+
+FILTER : '(' ( ( '&' (SP)* (FILTER)+ ) | ( '|' (SP)* (FILTER)+ ) | ( '!' (SP)* FILTER ) | FILTER_VALUE ) ')' (SP)* ;
+
+protected FILTER_VALUE : (options{greedy=true;}: ~( ')' | '(' | '&' | '|' | '!' ) ( ~(')') )* ) ;

Added: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItem.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItem.java?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItem.java (added)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItem.java Thu Jul 15 10:04:06 2010
@@ -0,0 +1,152 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.aci;
+
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.shared.i18n.I18n;
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+
+
+/**
+ * An abstract class that provides common properties and operations for
+ * {@link ItemFirstACIItem} and {@link UserFirstACIItem} as specified X.501
+ * specification.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public abstract class ACIItem
+{
+    /** The ACIItemComponet identifier */
+    private String identificationTag;
+
+    /** The precedence : a number in [0 - 255] */
+    private int precedence = 0;
+
+    /** The authentication level. One of 'none', 'simple' and 'strong' */
+    private AuthenticationLevel authenticationLevel;
+
+
+    /**
+     * Creates a new instance
+     * 
+     * @param identificationTag the id string of this item
+     * @param precedence the precedence of this item
+     * @param authenticationLevel the level of authentication required to this item
+     */
+    protected ACIItem( String identificationTag, int precedence, AuthenticationLevel authenticationLevel )
+    {
+        if ( identificationTag == null )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04001_NULL_IDENTIFICATION_TAG ) );
+        }
+        
+        if ( ( precedence < 0 ) || ( precedence > 255 ) )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04002_BAD_PRECENDENCE, precedence ) );
+        }
+        
+        if ( authenticationLevel == null )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04003_NULL_AUTHENTICATION_LEVEL ) );
+        }
+
+        this.identificationTag = identificationTag;
+        this.precedence = precedence;
+        this.authenticationLevel = authenticationLevel;
+    }
+
+
+    /**
+     * Returns the id string of this item.
+     */
+    public String getIdentificationTag()
+    {
+        return identificationTag;
+    }
+
+
+    /**
+     * Returns the precedence of this item.
+     */
+    public int getPrecedence()
+    {
+        return precedence;
+    }
+
+
+    /**
+     * Returns the level of authentication required to this item.
+     */
+    public AuthenticationLevel getAuthenticationLevel()
+    {
+        return authenticationLevel;
+    }
+
+
+    /**
+     * Converts this item into a collection of {@link ACITuple}s and returns
+     * it.
+     */
+    public abstract Collection<ACITuple> toTuples();
+
+
+    /**
+     * Converts a set of {@link GrantAndDenial}s into a set of
+     * {@link MicroOperation}s and returns it.
+     */
+    protected static Set<MicroOperation> toMicroOperations( Set<GrantAndDenial> grantsAndDenials )
+    {
+        Set<MicroOperation> microOps = new HashSet<MicroOperation>();
+        
+        for ( GrantAndDenial grantAndDenial:grantsAndDenials )
+        {
+            microOps.add( grantAndDenial.getMicroOperation() );
+        }
+        
+        return microOps;
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder buf = new StringBuilder();
+        
+        // identificationTag
+        buf.append( "identificationTag \"" );
+        buf.append( getIdentificationTag() );
+
+        // precedence
+        buf.append( "\", precedence " );
+        buf.append( getPrecedence() );
+        
+        // authenticationLevel
+        buf.append( ", authenticationLevel " );
+        buf.append( getAuthenticationLevel().getName() );
+        
+        return buf.toString();
+    }
+}

Added: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItemChecker.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItemChecker.java?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItemChecker.java (added)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItemChecker.java Thu Jul 15 10:04:06 2010
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+package org.apache.directory.shared.ldap.aci;
+
+
+import java.io.StringReader;
+import java.text.ParseException;
+
+import org.apache.directory.shared.i18n.I18n;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
+
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+
+
+/**
+ * A reusable wrapper around the antlr generated parser for an ACIItem as
+ * defined by X.501. This class enables the reuse of the antlr parser/lexer pair
+ * without having to recreate them every time.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ACIItemChecker
+{
+    /** the antlr generated parser being wrapped */
+    private ReusableAntlrACIItemParser checker;
+
+    /** the antlr generated lexer being wrapped */
+    private ReusableAntlrACIItemLexer lexer;
+
+    private final boolean isNormalizing;
+
+
+    /**
+     * Creates a ACIItem parser.
+     */
+    public ACIItemChecker( SchemaManager schemaManager )
+    {
+        this.lexer = new ReusableAntlrACIItemLexer( new StringReader( "" ) );
+        this.checker = new ReusableAntlrACIItemParser( lexer );
+        this.checker.init( schemaManager );
+        this.isNormalizing = false;
+    }
+
+
+    /**
+     * Initializes the plumbing by creating a pipe and coupling the parser/lexer
+     * pair with it. param spec the specification to be parsed
+     */
+    private synchronized void reset( String spec )
+    {
+        StringReader in = new StringReader( spec );
+        this.lexer.prepareNextInput( in );
+        this.checker.resetState();
+    }
+
+
+    /**
+     * Parses an ACIItem without exhausting the parser.
+     * 
+     * @param spec
+     *            the specification to be parsed
+     * @throws ParseException
+     *             if there are any recognition errors (bad syntax)
+     */
+    public synchronized void parse( String spec ) throws ParseException
+    {
+        if ( spec == null || spec.trim().equals( "" ) )
+        {
+            return;
+        }
+
+        reset( spec ); // reset and initialize the parser / lexer pair
+
+        try
+        {
+            this.checker.wrapperEntryPoint();
+        }
+        catch ( TokenStreamException e )
+        {
+            throw new ParseException( I18n.err( I18n.ERR_00004, spec, e.getLocalizedMessage() ), 0 );
+        }
+        catch ( RecognitionException e )
+        {
+            throw new ParseException( I18n.err( I18n.ERR_00004, spec, e.getLocalizedMessage() ), e.getColumn() );
+        }
+    }
+
+
+    /**
+     * Tests to see if this parser is normalizing.
+     * 
+     * @return true if it normalizes false otherwise
+     */
+    public boolean isNormizing()
+    {
+        return this.isNormalizing;
+    }
+}

Added: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItemParser.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItemParser.java?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItemParser.java (added)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItemParser.java Thu Jul 15 10:04:06 2010
@@ -0,0 +1,140 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+package org.apache.directory.shared.ldap.aci;
+
+
+import java.io.StringReader;
+import java.text.ParseException;
+
+import org.apache.directory.shared.i18n.I18n;
+import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
+
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+
+
+/**
+ * A reusable wrapper around the antlr generated parser for an ACIItem as
+ * defined by X.501. This class enables the reuse of the antlr parser/lexer pair
+ * without having to recreate them every time.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ACIItemParser
+{
+    /** the antlr generated parser being wrapped */
+    private ReusableAntlrACIItemParser parser;
+
+    /** the antlr generated lexer being wrapped */
+    private ReusableAntlrACIItemLexer lexer;
+
+    private final boolean isNormalizing;
+
+
+    /**
+     * Creates a ACIItem parser.
+     */
+    public ACIItemParser( SchemaManager schemaManager )
+    {
+        this.lexer = new ReusableAntlrACIItemLexer( new StringReader( "" ) );
+        this.parser = new ReusableAntlrACIItemParser( lexer );
+
+        this.parser.init( schemaManager ); // this method MUST be called while we cannot do
+        // constructor overloading for antlr generated parser
+        this.isNormalizing = false;
+    }
+
+
+    /**
+     * Creates a normalizing ACIItem parser.
+     */
+    public ACIItemParser( NameComponentNormalizer normalizer, SchemaManager schemaManager )
+    {
+        this.lexer = new ReusableAntlrACIItemLexer( new StringReader( "" ) );
+        this.parser = new ReusableAntlrACIItemParser( lexer );
+
+        this.parser.setNormalizer( normalizer );
+        this.parser.init( schemaManager ); // this method MUST be called while we cannot do
+        // constructor overloading for antlr generated parser
+        this.isNormalizing = true;
+    }
+
+
+    /**
+     * Initializes the plumbing by creating a pipe and coupling the parser/lexer
+     * pair with it. param spec the specification to be parsed
+     */
+    private synchronized void reset( String spec )
+    {
+        StringReader in = new StringReader( spec );
+        this.lexer.prepareNextInput( in );
+        this.parser.resetState();
+    }
+
+
+    /**
+     * Parses an ACIItem without exhausting the parser.
+     * 
+     * @param spec
+     *            the specification to be parsed
+     * @return the specification bean
+     * @throws ParseException
+     *             if there are any recognition errors (bad syntax)
+     */
+    public synchronized ACIItem parse( String spec ) throws ParseException
+    {
+        ACIItem aCIItem = null;
+
+        if ( spec == null || spec.trim().equals( "" ) )
+        {
+            return null;
+        }
+
+        reset( spec ); // reset and initialize the parser / lexer pair
+
+        try
+        {
+            aCIItem = this.parser.wrapperEntryPoint();
+        }
+        catch ( TokenStreamException e )
+        {
+            throw new ParseException( I18n.err( I18n.ERR_00004, spec, e.getLocalizedMessage() ), 0 );
+        }
+        catch ( RecognitionException e )
+        {
+            throw new ParseException( I18n.err( I18n.ERR_00004, spec, e.getLocalizedMessage() ), e.getColumn() );
+        }
+
+        return aCIItem;
+    }
+
+
+    /**
+     * Tests to see if this parser is normalizing.
+     * 
+     * @return true if it normalizes false otherwise
+     */
+    public boolean isNormizing()
+    {
+        return this.isNormalizing;
+    }
+}

Added: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACITuple.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACITuple.java?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACITuple.java (added)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACITuple.java Thu Jul 15 10:04:06 2010
@@ -0,0 +1,157 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.aci;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.shared.i18n.I18n;
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+
+
+/**
+ * A flatten entity which is converted from an {@link ACIItem}. The tuples are
+ * accepted by ACDF (Access Control Decision Function, 18.8, X.501)
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ACITuple
+{
+    /** The collection of {@link UserClass}es this tuple relates to **/
+    private final Collection<UserClass> userClasses;
+
+    /** The level of authentication required */
+    private final AuthenticationLevel authenticationLevel;
+
+    /** The collection of {@link ProtectedItem}s this tuple relates */
+    private final Collection<ProtectedItem> protectedItems;
+
+    /** The set of {@link MicroOperation}s this tuple relates */
+    private final Set<MicroOperation> microOperations;
+
+    /** Tells if this tuple grant some access */
+    private final boolean grant;
+
+    /** The precedence for this tuple */
+    private final Integer precedence;
+
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param userClasses the collection of {@link UserClass}es this tuple relates to
+     * @param authenticationLevel the level of authentication required
+     * @param protectedItems the collection of {@link ProtectedItem}s this tuple relates
+     * @param microOperations the set of {@link MicroOperation}s this tuple relates
+     * @param grant <tt>true</tt> if and only if this tuple grants an access
+     * @param precedence the precedence of this tuple (<tt>0</tt>-<tt>255</tt>)
+     */
+    public ACITuple( 
+            Collection<UserClass> userClasses, 
+            AuthenticationLevel authenticationLevel, 
+            Collection<ProtectedItem> protectedItems,
+            Set<MicroOperation> microOperations, 
+            boolean grant, 
+            Integer precedence )
+    {
+        if ( authenticationLevel == null )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04003_NULL_AUTHENTICATION_LEVEL ) );
+        }
+
+        if ( precedence < 0 || precedence > 255 )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_04002_BAD_PRECENDENCE, precedence ) );
+        }
+
+        this.userClasses = Collections.unmodifiableCollection( new ArrayList<UserClass>( userClasses ) );
+        this.authenticationLevel = authenticationLevel;
+        this.protectedItems = Collections.unmodifiableCollection( new ArrayList<ProtectedItem>( protectedItems ) );
+        this.microOperations = Collections.unmodifiableSet( new HashSet<MicroOperation>( microOperations ) );
+        this.grant = grant;
+        this.precedence = precedence;
+    }
+
+
+    /**
+     * Returns the collection of {@link UserClass}es this tuple relates to.
+     */
+    public Collection<UserClass> getUserClasses()
+    {
+        return userClasses;
+    }
+
+
+    /**
+     * Returns the level of authentication required.
+     */
+    public AuthenticationLevel getAuthenticationLevel()
+    {
+        return authenticationLevel;
+    }
+
+
+    /**
+     * Returns the collection of {@link ProtectedItem}s this tuple relates.
+     */
+    public Collection<ProtectedItem> getProtectedItems()
+    {
+        return protectedItems;
+    }
+
+
+    /**
+     * Returns the set of {@link MicroOperation}s this tuple relates.
+     */
+    public Set<MicroOperation> getMicroOperations()
+    {
+        return microOperations;
+    }
+
+
+    /**
+     * Returns <tt>true</tt> if and only if this tuple grants an access.
+     */
+    public boolean isGrant()
+    {
+        return grant;
+    }
+
+
+    /**
+     * Returns the precedence of this tuple (<tt>0</tt>-<tt>255</tt>).
+     */
+    public Integer getPrecedence()
+    {
+        return precedence;
+    }
+
+
+    public String toString()
+    {
+        return "ACITuple: userClasses=" + userClasses + ", " + "authenticationLevel=" + authenticationLevel + ", "
+            + "protectedItems=" + protectedItems + ", " + ( grant ? "grants=" : "denials=" ) + microOperations + ", "
+            + "precedence=" + precedence;
+    }
+}

Added: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/GrantAndDenial.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/GrantAndDenial.java?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/GrantAndDenial.java (added)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/GrantAndDenial.java Thu Jul 15 10:04:06 2010
@@ -0,0 +1,174 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.aci;
+
+
+/**
+ * An enumeration that represents grants or denials of {@link MicroOperation}s.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class GrantAndDenial
+{
+    // Permissions that may be used in conjunction with any component of
+    // <tt>ProtectedItem</tt>s.
+    /** Grant for {@link MicroOperation#ADD} */
+    public static final GrantAndDenial GRANT_ADD = new GrantAndDenial( MicroOperation.ADD, 0, true );
+
+    /** Denial for {@link MicroOperation#ADD} */
+    public static final GrantAndDenial DENY_ADD = new GrantAndDenial( MicroOperation.ADD, 1, false );
+
+    /** Grant for {@link MicroOperation#DISCLOSE_ON_ERROR} */
+    public static final GrantAndDenial GRANT_DISCLOSE_ON_ERROR = new GrantAndDenial( MicroOperation.DISCLOSE_ON_ERROR,
+        2, true );
+
+    /** Denial for {@link MicroOperation#DISCLOSE_ON_ERROR} */
+    public static final GrantAndDenial DENY_DISCLOSE_ON_ERROR = new GrantAndDenial( MicroOperation.DISCLOSE_ON_ERROR,
+        3, false );
+
+    /** Grant for {@link MicroOperation#READ} */
+    public static final GrantAndDenial GRANT_READ = new GrantAndDenial( MicroOperation.READ, 4, true );
+
+    /** Denial for {@link MicroOperation#READ} */
+    public static final GrantAndDenial DENY_READ = new GrantAndDenial( MicroOperation.READ, 5, false );
+
+    /** Grant for {@link MicroOperation#REMOVE} */
+    public static final GrantAndDenial GRANT_REMOVE = new GrantAndDenial( MicroOperation.REMOVE, 6, true );
+
+    /** Denial for {@link MicroOperation#REMOVE} */
+    public static final GrantAndDenial DENY_REMOVE = new GrantAndDenial( MicroOperation.REMOVE, 7, false );
+
+    // Permissions that may be used only in conjunction with the entry
+    // component.
+    /** Grant for {@link MicroOperation#BROWSE} */
+    public static final GrantAndDenial GRANT_BROWSE = new GrantAndDenial( MicroOperation.BROWSE, 8, true );
+
+    /** Denial for {@link MicroOperation#BROWSE} */
+    public static final GrantAndDenial DENY_BROWSE = new GrantAndDenial( MicroOperation.BROWSE, 9, false );
+
+    /** Grant for {@link MicroOperation#EXPORT} */
+    public static final GrantAndDenial GRANT_EXPORT = new GrantAndDenial( MicroOperation.EXPORT, 10, true );
+
+    /** Denial for {@link MicroOperation#EXPORT} */
+    public static final GrantAndDenial DENY_EXPORT = new GrantAndDenial( MicroOperation.EXPORT, 11, false );
+
+    /** Grant for {@link MicroOperation#IMPORT} */
+    public static final GrantAndDenial GRANT_IMPORT = new GrantAndDenial( MicroOperation.IMPORT, 12, true );
+
+    /** Denial for {@link MicroOperation#IMPORT} */
+    public static final GrantAndDenial DENY_IMPORT = new GrantAndDenial( MicroOperation.IMPORT, 13, false );
+
+    /** Grant for {@link MicroOperation#MODIFY} */
+    public static final GrantAndDenial GRANT_MODIFY = new GrantAndDenial( MicroOperation.MODIFY, 14, true );
+
+    /** Denial for {@link MicroOperation#MODIFY} */
+    public static final GrantAndDenial DENY_MODIFY = new GrantAndDenial( MicroOperation.MODIFY, 15, false );
+
+    /** Grant for {@link MicroOperation#RENAME} */
+    public static final GrantAndDenial GRANT_RENAME = new GrantAndDenial( MicroOperation.RENAME, 16, true );
+
+    /** Denial for {@link MicroOperation#RENAME} */
+    public static final GrantAndDenial DENY_RENAME = new GrantAndDenial( MicroOperation.RENAME, 17, false );
+
+    /** Grant for {@link MicroOperation#RETURN_DN} */
+    public static final GrantAndDenial GRANT_RETURN_DN = new GrantAndDenial( MicroOperation.RETURN_DN, 18, true );
+
+    /** Denial for {@link MicroOperation#RETURN_DN} */
+    public static final GrantAndDenial DENY_RETURN_DN = new GrantAndDenial( MicroOperation.RETURN_DN, 19, false );
+
+    // Permissions that may be used in conjunction with any component,
+    // except entry, of <tt>ProtectedItem</tt>s.
+    /** Grant for {@link MicroOperation#COMPARE} */
+    public static final GrantAndDenial GRANT_COMPARE = new GrantAndDenial( MicroOperation.COMPARE, 20, true );
+
+    /** Deny for {@link MicroOperation#COMPARE} */
+    public static final GrantAndDenial DENY_COMPARE = new GrantAndDenial( MicroOperation.COMPARE, 21, false );
+
+    /** Grant for {@link MicroOperation#FILTER_MATCH} */
+    public static final GrantAndDenial GRANT_FILTER_MATCH = new GrantAndDenial( MicroOperation.FILTER_MATCH, 22, true );
+
+    /** Denial for {@link MicroOperation#FILTER_MATCH} */
+    public static final GrantAndDenial DENY_FILTER_MATCH = new GrantAndDenial( MicroOperation.FILTER_MATCH, 23, false );
+
+    /** Grant for {@link MicroOperation#INVOKE} */
+    public static final GrantAndDenial GRANT_INVOKE = new GrantAndDenial( MicroOperation.INVOKE, 24, true );
+
+    /** Denial for {@link MicroOperation#INVOKE} */
+    public static final GrantAndDenial DENY_INVOKE = new GrantAndDenial( MicroOperation.INVOKE, 25, false );
+
+    private final MicroOperation microOperation;
+
+    private final int code;
+
+    private final String name;
+
+    private final boolean grant;
+
+
+    private GrantAndDenial(MicroOperation microOperation, int code, boolean grant)
+    {
+        this.microOperation = microOperation;
+        this.code = code;
+        this.name = ( grant ? "grant" : "deny" ) + microOperation.getName();
+        this.grant = grant;
+    }
+
+
+    /**
+     * Returns the {@link MicroOperation} related with this grant or denial.
+     */
+    public MicroOperation getMicroOperation()
+    {
+        return microOperation;
+    }
+
+
+    /**
+     * Return the code number of this grant or denial.
+     */
+    public int getCode()
+    {
+        return code;
+    }
+
+
+    /**
+     * Returns the name of this grant or denial.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+
+    /**
+     * Returns <tt>true</tt> if and only if this is grant.
+     */
+    public boolean isGrant()
+    {
+        return grant;
+    }
+
+
+    public String toString()
+    {
+        return name;
+    }
+}

Added: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemFirstACIItem.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemFirstACIItem.java?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemFirstACIItem.java (added)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemFirstACIItem.java Thu Jul 15 10:04:06 2010
@@ -0,0 +1,172 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.aci;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+
+
+/**
+ * An {@link ACIItem} which specifies {@link ProtectedItem}s first and then
+ * {@link UserClass}es each {@link ProtectedItem} will have. (18.4.2.4. X.501)
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ItemFirstACIItem extends ACIItem
+{
+    /** The list of protected items ( userClasses or userPermissions ) */
+    private final Collection<ProtectedItem> protectedItems;
+
+    /** The associated permissions */
+    private final Collection<ItemPermission> itemPermissions;
+
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param identificationTag the id string of this item
+     * @param precedence the precedence of this item
+     * @param authenticationLevel the level of authentication required to this item
+     * @param protectedItems the collection of {@link ProtectedItem}s this item protects
+     * @param itemPermissions the collection of {@link ItemPermission}s each <tt>protectedItems</tt> will have
+     */
+    public ItemFirstACIItem( String identificationTag, int precedence, AuthenticationLevel authenticationLevel,
+        Collection<ProtectedItem> protectedItems, Collection<ItemPermission> itemPermissions )
+    {
+        super( identificationTag, precedence, authenticationLevel );
+
+        this.protectedItems = Collections.unmodifiableCollection( new ArrayList<ProtectedItem>( protectedItems ) );
+        this.itemPermissions = Collections.unmodifiableCollection( new ArrayList<ItemPermission>( itemPermissions ) );
+    }
+
+
+    /**
+     * Returns the collection of {@link ProtectedItem}s.
+     */
+    public Collection<ProtectedItem> getProtectedItems()
+    {
+        return protectedItems;
+    }
+
+
+    /**
+     * Returns the collection of {@link ItemPermission}s.
+     */
+    public Collection<ItemPermission> getItemPermissions()
+    {
+        return itemPermissions;
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder buf = new StringBuilder();
+        
+        buf.append( "{" );
+        buf.append( super.toString() );
+        
+        // itemOrUserFirst
+        buf.append( ", itemOrUserFirst itemFirst: { " );
+        
+        // protectedItems
+        buf.append( "protectedItems { " );
+        
+        boolean isFirst = true;
+
+        for ( ProtectedItem item:protectedItems )
+        {
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
+
+            buf.append( item.toString() );
+        }
+
+        // itemPermissions
+        buf.append( " }, itemPermissions { " );
+
+        isFirst = true;
+        
+        for ( ItemPermission permission:itemPermissions )
+        {
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
+
+            buf.append( permission.toString() );
+        }
+
+        buf.append( " } } }" );
+        
+        return buf.toString();
+    }
+
+
+    /**
+     * Transform this protected Item and permissions to a set of Tuples
+     * 
+     * @return The list of created Tuples
+     */
+    public Collection<ACITuple> toTuples()
+    {
+        Collection<ACITuple> tuples = new ArrayList<ACITuple>();
+        
+        for ( ItemPermission itemPermission:itemPermissions )
+        {
+            Set<GrantAndDenial> grants = itemPermission.getGrants();
+            Set<GrantAndDenial> denials = itemPermission.getDenials();
+            int precedence = itemPermission.getPrecedence() != null ? 
+                itemPermission.getPrecedence() :
+                this.getPrecedence();
+
+            if ( grants.size() > 0 )
+            {
+                tuples.add( new ACITuple( itemPermission.getUserClasses(), getAuthenticationLevel(), protectedItems,
+                    toMicroOperations( grants ), true, precedence ) );
+            }
+            
+            if ( denials.size() > 0 )
+            {
+                tuples.add( new ACITuple( itemPermission.getUserClasses(), getAuthenticationLevel(), protectedItems,
+                    toMicroOperations( denials ), false, precedence ) );
+            }
+        }
+        
+        return tuples;
+    }
+}

Added: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemPermission.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemPermission.java?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemPermission.java (added)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemPermission.java Thu Jul 15 10:04:06 2010
@@ -0,0 +1,120 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.aci;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+
+/**
+ * Represents permissions to be applied to all {@link ProtectedItem}s in
+ * {@link ItemFirstACIItem}.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ItemPermission extends Permission
+{
+    private final Collection<UserClass> userClasses;
+
+
+    /**
+     * Creates a new instance
+     * 
+     * @param precedence
+     *            the precedence of this permission (<tt>-1</tt> to use the
+     *            default)
+     * @param grantsAndDenials
+     *            the set of {@link GrantAndDenial}s
+     * @param userClasses
+     *            the collection of {@link UserClass}es
+     */
+    public ItemPermission( Integer precedence, Collection<GrantAndDenial> grantsAndDenials, Collection<UserClass> userClasses )
+    {
+        super( precedence, grantsAndDenials );
+
+        this.userClasses = Collections.unmodifiableCollection( new ArrayList<UserClass>( userClasses ) );
+    }
+
+
+    /**
+     * Returns the collection of {@link UserClass}es.
+     */
+    public Collection<UserClass> getUserClasses()
+    {
+        return userClasses;
+    }
+
+
+    public String toString()
+    {
+        StringBuilder buffer = new StringBuilder();
+        
+        buffer.append( "{ " );
+
+        if ( getPrecedence() != null )
+        {
+            buffer.append( "precedence " );
+            buffer.append( getPrecedence() );
+            buffer.append( ", " );
+        }
+        
+        buffer.append( "userClasses { " );
+        
+        boolean isFirst = true;
+        
+        for ( UserClass userClass:userClasses )
+        {
+            if ( isFirst ) 
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buffer.append( ", " );
+            }
+
+            buffer.append( userClass.toString() );
+        }
+        
+        buffer.append( " }, grantsAndDenials { " );
+        
+        isFirst = true;
+        
+        for ( GrantAndDenial grantAndDenial:getGrantsAndDenials() )
+        {
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buffer.append( ", " );
+            }
+
+            buffer.append( grantAndDenial.toString() );
+        }
+        
+        buffer.append( " } }" );
+        
+        return buffer.toString();
+    }
+}

Added: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/MicroOperation.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/MicroOperation.java?rev=964361&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/MicroOperation.java (added)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/aci/MicroOperation.java Thu Jul 15 10:04:06 2010
@@ -0,0 +1,85 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.aci;
+
+
+/**
+ * An enumeration that represents all micro-operations that makes up LDAP
+ * operations.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum MicroOperation
+{
+    // Permissions that may be used in conjunction with any component of
+    // <tt>ProtectedItem</tt>s.
+    ADD( "Add" ),
+
+    DISCLOSE_ON_ERROR( "DiscloseOnError" ),
+
+    READ( "Read" ),
+
+    REMOVE( "Remove" ),
+
+    // Permissions that may be used only in conjunction with the entry
+    // component.
+    BROWSE( "Browse" ),
+
+    EXPORT( "Export" ),
+
+    IMPORT( "Import" ),
+
+    MODIFY( "Modify" ),
+
+    RENAME ( "Rename" ),
+
+    RETURN_DN( "ReturnDN" ),
+
+    // Permissions that may be used in conjunction with any component,
+    // except entry, of <tt>ProtectedItem</tt>s.
+    COMPARE( "Compare" ),
+
+    FILTER_MATCH( "FilterMatch" ),
+
+    INVOKE( "Invoke" );
+
+    private final String name;
+
+
+    private MicroOperation(String name)
+    {
+        this.name = name;
+    }
+
+
+    /**
+     * Returns the name of this micro-operation.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+
+    public String toString()
+    {
+        return name;
+    }
+}