/*
 *  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.studio.openldap.config.acl.model;


import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import antlr.RecognitionException;

import org.apache.directory.studio.openldap.config.acl.model.AclAttribute;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

//assertThrows(ParseException.class, () -> parser.parse( "" ));

/**
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class OpenLdapAclParserTest
{
    @Test
    public void testEmpty() throws Exception
    {
        System.out.println( "\n--> testEmpty" );
        OpenLdapAclParser parser = new OpenLdapAclParser();
        assertThrows(ParseException.class, () -> parser.parse( "" ));
    }


    @Test
    public void testImpliedWhatStarWithAccess() throws Exception
    {
        System.out.println( "\n--> testImpliedWhatStarWithAccess" );
        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access   to by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseStar );
        
        System.out.println( "<-- ACL:" + aclItem );
    }


    @Test
    public void testWhatStarWithAccess() throws Exception
    {
        System.out.println( "\n--> testWhatStarWithAccess" );
        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access   to * by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseStar );
        
        System.out.println( "<-- ACL:" + aclItem );
    }

    
    @Test
    public void testWhatStarWithoutAccess() throws Exception
    {
        System.out.println( "\n--> testWhatStarWithoutAccess" );
        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( " to * by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseStar );
        
        System.out.println( "<-- ACL:" + aclItem );
    }


    @Test
    public void testWhatStarWithSpaces() throws Exception
    {
        System.out.println( "\n--> testWhatStarWithSpaces" );
        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "   access    to     *    by    *    " );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseStar );
        
        System.out.println( "<-- ACL:" + aclItem );
    }


    @Test
    public void testWhatTwoStars() throws Exception
    {
        System.out.println( "\n--> testWhatTwoStars" );
        OpenLdapAclParser parser = new OpenLdapAclParser();
        assertThrows(ParseException.class, () -> parser.parse( "to * * by *" ));
    }

    
    //-----------------------------------------------------------------------------------------
    // The WHAT DN rule
    //-----------------------------------------------------------------------------------------
    @Test
    public void testWhatDnValidDnWithQuote() throws Exception
    {
        System.out.println( "\n--> testWhatDnValidDnWithQuote" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn)whatClause;
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        
        System.out.println( "<-- ACL:" + aclItem );
    }

    
    @Test
    public void testWhatDnStar() throws Exception
    {
        System.out.println( "\n--> testWhatDnStar" );
        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn=* by *" ));
    }

    
    @Test
    public void testWhatDnValidDnNoQuote() throws Exception
    {
        System.out.println( "\n--> testWhatDnValidDnNoQuote" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn=" + dnPattern + "\n by *" ));
    }

    @Disabled
    @Test
    public void testWhatDnBadDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnBadDn" );
        String dnPattern = "Blah";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn=\"" + dnPattern + "\"\n by *" ));
    }

    
    //-----------------------------------------------------------------------------------------
    // The basic-dn-style WHAT DN exact
    //-----------------------------------------------------------------------------------------
    @Test
    public void testWhatDnBasicDnExact() throws Exception
    {
        System.out.println( "\n--> testWhatDnBasicDnExact" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.exact=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.EXACT, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }
    
    
    @Test
    public void testWhatDnBasicDnExactNoQuote() throws Exception
    {
        System.out.println( "\n--> testWhatDnBasicDnExactNoQuote" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn.exact=" + dnPattern + " by *" ));
    }
    
    
    @Test
    public void testWhatDnBasicDnExactBadDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnBasicDnExactBadDn" );
        String dnPattern = "example";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn.exact=" + dnPattern + " by *" ));
    }
    
    
    //-----------------------------------------------------------------------------------------
    // The basic-dn-style WHAT DN regex
    //-----------------------------------------------------------------------------------------
    @Test
    public void testWhatDnBasicDnRegex() throws Exception
    {
        System.out.println( "\n--> testWhatDnBasicDnRegex" );
        String dnPattern = "dc=*";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.regex=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.REGEX, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }
    
    
    @Test
    public void testWhatDnBasicDnRegexNoQuote() throws Exception
    {
        System.out.println( "\n--> testWhatDnBasicDnRegexNoQuote" );
        String dnPattern = "dc=*,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn.regex=" + dnPattern + " by *" ));
    }
    
    
    //-----------------------------------------------------------------------------------------
    // The scope-dn-clause WHAT DN regex
    //-----------------------------------------------------------------------------------------
    @Test
    public void testWhatDnScopeOneQuotedDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeOneQuotedDn" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.one=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.ONE, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }
    
    
    @Test
    public void testWhatDnScopeOneLevelQuotedDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeOneLevelQuotedDn" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.onelevel=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.ONE_LEVEL, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }
    
    
    @Test
    public void testWhatDnScopeBaseQuotedDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeBaseQuotedDn" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.base=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.BASE, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }
    
    
    @Test
    public void testWhatDnScopeBaseobjectQuotedDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeBaseobjectQuotedDn" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.baseobject=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.BASE_OBJECT, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }
    
    
    @Test
    public void testWhatDnScopeSubQuotedDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeSubQuotedDn" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.sub=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.SUB, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }
    
    
    @Test
    public void testWhatDnScopeSubtreeQuotedDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeSubtreeQuotedDn" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.subtree=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.SUBTREE, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }
    
    
    @Test
    public void testWhatDnScopeChildrenQuotedDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeChildrenQuotedDn" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.children=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.CHILDREN, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }

    
    @Test
    public void testWhatDnScopeOneEmptyDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeOneEmptyDn" );

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to dn.one=\"\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseDn );
        AclWhatClauseDn whatClauseDn = (AclWhatClauseDn) whatClause;

        // test the content
        assertEquals( "", whatClauseDn.getPattern() );
        assertEquals( AclWhatClauseDnTypeEnum.ONE, whatClauseDn.getType() );

        System.out.println( "<-- ACL:" + aclItem );
    }

    
    @Test
    public void testWhatDnScopeOneNoQuotedDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeOneNoQuotedDn" );
        String dnPattern = "dc=example,dc=com";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn.one=" + dnPattern + " by *" ));
    }

    
    @Test
    public void testWhatDnScopeOneNoDn() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeOneNoDn" );

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn.one= by *" ));
    }

    
    @Test
    public void testWhatDnScopeOneStar() throws Exception
    {
        System.out.println( "\n--> testWhatDnScopeOneStar" );

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to dn.one=* by *" ));
    }
    
    
    //-----------------------------------------------------------------------------------------
    // The scope-dn-clause WHAT FILTER 
    //-----------------------------------------------------------------------------------------
    @Test
    public void testWhatFilterSimple() throws Exception
    {
        System.out.println( "\n--> testWhatFilter" );
        String filter = "(objectclass=*)";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to filter=" + filter + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseFilter );
        
        AclWhatClauseFilter whatClauseFilter = (AclWhatClauseFilter) whatClause;

        // test the content
        assertEquals( filter, whatClauseFilter.getFilter() );

        System.out.println( "<-- ACL:" + aclItem );
    }


    @Test
    public void testWhatFilterComplex() throws Exception
    {
        System.out.println( "\n--> testWhatFilterComplex" );
        String filter = "(&(objectclass=*)(cn=test)(!(sn=test)))";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to filter=" + filter + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        assertTrue( whatClause instanceof AclWhatClauseFilter );
        
        AclWhatClauseFilter whatClauseFilter = (AclWhatClauseFilter) whatClause;

        // test the content
        assertEquals( filter, whatClauseFilter.getFilter() );

        System.out.println( "<-- ACL:" + aclItem );
    }


    @Test
    public void testWhatFilterWrongSimple() throws Exception
    {
        System.out.println( "\n--> testWhatFilterWrongSimple" );
        String filter = "(objectclass=*";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        assertThrows(ParseException.class, () -> parser.parse( "access to filter=" + filter + " by *" ));
    }
 

    

    @Disabled
    @Test
    public void testFail() throws Exception
    {
        fail();
    }
    
    /*
    @Test
    public void testWhatDnWithoutAccess() throws Exception
    {
        String dnPattern = "dsqdsqdq";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "to dn=\"" + dnPattern + "\" by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseDn whatClauseDn = whatClause.getDnClause();
        assertNotNull( whatClauseDn );
        assertEquals( dnPattern, whatClauseDn.getPattern() );
    }


    @Test
    public void testWhatTwoDns() throws Exception
    {
        try
        {
            OpenLdapAclParser parser = new OpenLdapAclParser();
            parser.parse( "to dn=\"dsdsfsd\" dn=\"dsdsfsd\" by *" );

            fail();
        }
        catch ( Exception e )
        {
            // Should happen
        }
    }


    @Test
    public void testWhatAttributes() throws Exception
    {
        String attribute = "userPassword";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to attrs=" + attribute + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseAttributes whatClauseAttributes = whatClause.getAttributesClause();
        assertNotNull( whatClauseAttributes );
        List<AclAttribute> attributesList = whatClauseAttributes.getAttributes();
        assertEquals( 1, attributesList.size() );
        assertEquals( attribute, attributesList.get( 0 ).getName() );
    }


    @Test
    public void testWhatAttributesWithoutAccess() throws Exception
    {
        String attribute = "userPassword";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "to attrs=" + attribute + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseAttributes whatClauseAttributes = whatClause.getAttributesClause();
        assertNotNull( whatClauseAttributes );
        List<AclAttribute> attributesList = whatClauseAttributes.getAttributes();
        assertEquals( 1, attributesList.size() );
        assertEquals( attribute, attributesList.get( 0 ).getName() );
    }


    @Test
    public void testWhatAttributesWithSpaces() throws Exception
    {
        String attribute = "userPassword";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "   access    to     attrs=" + attribute + "    by    *    " );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseAttributes whatClauseAttributes = whatClause.getAttributesClause();
        assertNotNull( whatClauseAttributes );
        List<AclAttribute> attributesList = whatClauseAttributes.getAttributes();
        assertEquals( 1, attributesList.size() );
        assertEquals( attribute, attributesList.get( 0 ).getName() );
    }


    @Test
    public void testWhatAttributesMultiple() throws Exception
    {
        String attribute1 = "userPassword";
        String attribute2 = "uid";
        String attribute3 = "cn";

        String attributes = attribute1 + "," + attribute2 + "," + attribute3;

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to attrs=" + attributes + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseAttributes whatClauseAttributes = whatClause.getAttributesClause();
        assertNotNull( whatClauseAttributes );
        List<AclAttribute> attributesList = whatClauseAttributes.getAttributes();
        assertEquals( 3, attributesList.size() );
        assertEquals( attribute1, attributesList.get( 0 ).getName() );
        assertEquals( attribute2, attributesList.get( 1 ).getName() );
        assertEquals( attribute3, attributesList.get( 2 ).getName() );
    }


    @Test
    public void testWhatAttributesMultipleWithoutAccess() throws Exception
    {
        String attribute1 = "userPassword";
        String attribute2 = "uid";
        String attribute3 = "cn";

        String attributes = attribute1 + "," + attribute2 + "," + attribute3;

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "to attrs=" + attributes + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseAttributes whatClauseAttributes = whatClause.getAttributesClause();
        assertNotNull( whatClauseAttributes );
        List<AclAttribute> attributesList = whatClauseAttributes.getAttributes();
        assertEquals( 3, attributesList.size() );
        assertEquals( attribute1, attributesList.get( 0 ).getName() );
        assertEquals( attribute2, attributesList.get( 1 ).getName() );
        assertEquals( attribute3, attributesList.get( 2 ).getName() );
    }


    @Test
    public void testWhatTwoAttributes() throws Exception
    {
        try
        {
            OpenLdapAclParser parser = new OpenLdapAclParser();
            parser.parse( "access to attrs=userPassword attrs=userPassword by *" );

            fail();
        }
        catch ( Exception e )
        {
            // Should happen
        }
    }


    @Test
    public void testWhatFilterWithoutAccess() throws Exception
    {
        String filter = "(objectclass=*)";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "to filter=" + filter + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseFilter whatClauseFilter = whatClause.getFilterClause();
        assertNotNull( whatClauseFilter );
        assertEquals( filter, whatClauseFilter.getFilter() );
    }


    @Test
    public void testWhatFilterWithSpaces() throws Exception
    {
        String filter = "(objectclass=*)";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "   access    to     filter=" + filter + "    by    *    " );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseFilter whatClauseFilter = whatClause.getFilterClause();
        assertNotNull( whatClauseFilter );
        assertEquals( filter, whatClauseFilter.getFilter() );
    }


    @Test
    public void testWhatFilterComplex() throws Exception
    {
        String filter = "(&(&(!(cn=jbond))(|(ou=ResearchAndDevelopment)(ou=HumanResources)))(objectclass=Person))";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to filter=" + filter + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseFilter whatClauseFilter = whatClause.getFilterClause();
        assertNotNull( whatClauseFilter );
        assertEquals( filter, whatClauseFilter.getFilter() );
    }


    @Test
    public void testWhatFilterComplexWithoutAccess() throws Exception
    {
        String filter = "(&(&(!(cn=jbond))(|(ou=ResearchAndDevelopment)(ou=HumanResources)))(objectclass=Person))";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "to filter=" + filter + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseFilter whatClauseFilter = whatClause.getFilterClause();
        assertNotNull( whatClauseFilter );
        assertEquals( filter, whatClauseFilter.getFilter() );
    }


    @Test
    public void testWhatTwoFilters() throws Exception
    {
        try
        {
            OpenLdapAclParser parser = new OpenLdapAclParser();
            parser.parse( "access to filter=(objectClass=*) filter=(objectClass=*) by *" );

            fail();
        }
        catch ( Exception e )
        {
            // Should happen
        }
    }


    @Test
    public void testWhatDnAndFilter() throws Exception
    {
        String dnPattern = "dsqdsqdq";
        String filter = "(objectclass=*)";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to  dn=\"" + dnPattern + "\" filter=" + filter + " by *" );
        assertNotNull( aclItem );

        // Testing the 'what' clause
        AclWhatClause whatClause = aclItem.getWhatClause();
        assertNotNull( whatClause );
        AclWhatClauseDn whatClauseDn = whatClause.getDnClause();
        assertNotNull( whatClauseDn );
        assertEquals( dnPattern, whatClauseDn.getPattern() );
        AclWhatClauseFilter whatClauseFilter = whatClause.getFilterClause();
        assertNotNull( whatClauseFilter );
        assertEquals( filter, whatClauseFilter.getFilter() );
    }


    @Test
    public void testWhatDnAndAttributes() throws Exception
    {
        String dnPattern = "dsqdsqdq";
        String attribute = "userPassword";

        // Create parser
        OpenLdapAclParser parser = new OpenLdapAclParser();

        // Testing the ACL item
        AclItem aclItem = parser.parse( "access to  dn=\"" + dnPattern + "\" attrs=" + attribute + " by *" );
        assertNotNull( aclItem );

