/*
 *   @(#) $Id$
 *   
 *   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.ldap.server.authz.support;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;

import org.apache.ldap.common.aci.ACITuple;
import org.apache.ldap.common.aci.AuthenticationLevel;
import org.apache.ldap.common.aci.ProtectedItem;
import org.apache.ldap.server.interceptor.NextInterceptor;

public class MostSpecificProtectedItemFilter implements ACITupleFilter
{
    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
    {
        if( tuples.size() <= 1 )
        {
            return tuples;
        }

        Collection filteredTuples = new ArrayList();
        
        // If the protected item is an attribute and there are tuples that
        // specify the attribute type explicitly, discard all other tuples.
        for( Iterator i = tuples.iterator(); i.hasNext(); )
        {
            ACITuple tuple = ( ACITuple ) i.next();
            itemLoop: for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
            {
                ProtectedItem item = ( ProtectedItem ) j.next();
                if( item instanceof ProtectedItem.AttributeType )
                {
                    if( contains( attrId, ( ( ProtectedItem.AttributeType ) item ).iterator() ) )
                    {
                        filteredTuples.add( tuple );
                        break;
                    }
                }
                else if( item instanceof ProtectedItem.AllAttributeValues )
                {
                    if( contains( attrId, ( ( ProtectedItem.AllAttributeValues ) item ).iterator() ) )
                    {
                        filteredTuples.add( tuple );
                        break;
                    }
                }
                else if( item instanceof ProtectedItem.SelfValue )
                {
                    if( contains( attrId, ( ( ProtectedItem.SelfValue ) item ).iterator() ) )
                    {
                        filteredTuples.add( tuple );
                        break;
                    }
                }
                else if( item instanceof ProtectedItem.AttributeValue )
                {
                    if( attrId == null || attrValue == null )
                    {
                        continue;
                    }

                    filteredTuples.add( tuple );
                    break;
                }
            }
        }
        
        if( filteredTuples.size() > 0 )
        {
            return filteredTuples;
        }

        // If the protected item is an attribute value, and there are tuples
        // that specify the attribute value explicitly, discard all other tuples.
        // A protected item which is a rangeOfValues is to be treated as
        // specifying an attribute value explicitly. 
        for( Iterator i = tuples.iterator(); i.hasNext(); )
        {
            ACITuple tuple = ( ACITuple ) i.next();
            for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
            {
                ProtectedItem item = ( ProtectedItem ) j.next();
                if( item instanceof ProtectedItem.RangeOfValues )
                {
                    filteredTuples.add( tuple );
                }
            }
        }

        if( filteredTuples.size() > 0 )
        {
            return filteredTuples;
        }
        
        return tuples;
    }
    
    private static boolean contains( Object needle, Iterator haystack )
    {
        if( needle == null )
        {
            return false;
        }

        while( haystack.hasNext() )
        {
            if( haystack.next().equals( needle ) )
            {
                return true;
            }
        }
        
        return false;
    }
}

@@ -2162,132 +2162,8 @@
   %7B%0A
-                    if( contains( attrId, ( ( ProtectedItem.AttributeType ) item ).iterator() ) )%0A                    %7B%0A    
     
@@ -2231,41 +2231,15 @@
     
-    
 break;%0A
-                    %7D%0A
     
@@ -2350,137 +2350,8 @@
   %7B%0A
-                    if( contains( attrId, ( ( ProtectedItem.AllAttributeValues ) item ).iterator() ) )%0A                    %7B%0A    
     
@@ -2411,39 +2411,31 @@
             
-    
 break;%0A
-    
             
@@ -2440,34 +2440,16 @@
       %7D%0A
-                %7D%0A
         
@@ -2529,128 +2529,8 @@
   %7B%0A
-                    if( contains( attrId, ( ( ProtectedItem.SelfValue ) item ).iterator() ) )%0A                    %7B%0A    
     
@@ -2590,39 +2590,31 @@
             
- 
-   
 break;%0A
-    
             
@@ -2619,34 +2619,16 @@
       %7D%0A
-                %7D%0A
         
@@ -2713,149 +2713,8 @@
   %7B%0A
-                    if( attrId == null %7C%7C attrValue == null )%0A                    %7B%0A                        continue;%0A                    %7D%0A%0A
     
@@ -3815,366 +3815,6 @@
   %7D%0A
-    %0A    private static boolean contains( Object needle, Iterator haystack )%0A    %7B%0A        if( needle == null )%0A        %7B%0A            return false;%0A        %7D%0A%0A        while( haystack.hasNext() )%0A        %7B%0A            if( haystack.next().equals( needle ) )%0A            %7B%0A                return true;%0A            %7D%0A        %7D%0A        %0A        return false;%0A    %7D%0A
 %7D%0A

Removed unnecessary assertion code.