001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *  
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *  
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License. 
018 *  
019 */
020package org.apache.directory.server.core.api.subtree;
021
022
023import java.util.Iterator;
024
025import org.apache.directory.api.ldap.model.constants.SchemaConstants;
026import org.apache.directory.api.ldap.model.entry.Attribute;
027import org.apache.directory.api.ldap.model.exception.LdapException;
028import org.apache.directory.api.ldap.model.filter.EqualityNode;
029import org.apache.directory.api.ldap.model.filter.SimpleNode;
030import org.apache.directory.api.ldap.model.schema.AttributeType;
031import org.apache.directory.api.ldap.model.schema.SchemaManager;
032import org.apache.directory.server.i18n.I18n;
033
034
035/**
036 * A refinement leaf node evaluator.  This evaluator checks to see if the
037 * objectClass attribute of a candidate entry is matched by a leaf node in
038 * a refinement filter expression tree.
039 *
040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
041 */
042public class RefinementLeafEvaluator
043{
044    /** A SchemaManager instance */
045    private final SchemaManager schemaManager;
046
047    /** A storage for the ObjectClass attributeType */
048    private AttributeType objectClassAT;
049
050
051    /**
052     * Creates a refinement filter's leaf node evaluator.
053     *
054     * @param schemaManager The server schemaManager
055     */
056    public RefinementLeafEvaluator( SchemaManager schemaManager )
057    {
058        this.schemaManager = schemaManager;
059        objectClassAT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
060    }
061
062
063    /**
064     * Evaluates whether or not a simple leaf node of a refinement filter selects an
065     * entry based on the entry's objectClass attribute values.
066     *
067     * @param node the leaf node of the refinement filter
068     * @param objectClasses the objectClass attribute's values
069     * @return true if the leaf node selects the entry based on objectClass values, false
070     * if it rejects the entry
071     * @throws LdapException If the evaluation failed
072     */
073    public boolean evaluate( SimpleNode node, Attribute objectClasses ) throws LdapException
074    {
075        if ( node == null )
076        {
077            throw new IllegalArgumentException( I18n.err( I18n.ERR_295 ) );
078        }
079
080        if ( !( node instanceof EqualityNode ) )
081        {
082            throw new LdapException( I18n.err( I18n.ERR_301, node ) );
083        }
084
085        if ( node.isSchemaAware() )
086        {
087            if ( !node.getAttributeType().equals( objectClassAT ) )
088            {
089                throw new IllegalArgumentException( I18n.err( I18n.ERR_302, node.getAttribute() ) );
090            }
091        }
092        else if ( !node.getAttribute().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT )
093            && !node.getAttribute().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT_OID ) )
094        {
095            throw new IllegalArgumentException( I18n.err( I18n.ERR_302, node.getAttribute() ) );
096        }
097
098        if ( null == objectClasses )
099        {
100            throw new IllegalArgumentException( I18n.err( I18n.ERR_303 ) );
101        }
102
103        if ( !( objectClasses.isInstanceOf( objectClassAT ) ) )
104        {
105            throw new IllegalArgumentException( I18n.err( I18n.ERR_304 ) );
106        }
107
108        // check if Ava value exists in attribute
109        // If the filter value for the objectClass is an OID we need to resolve a name
110        String value = node.getValue().getString();
111
112        if ( objectClasses.contains( value ) )
113        {
114            return true;
115        }
116
117        if ( Character.isDigit( value.charAt( 0 ) ) )
118        {
119            Iterator<String> list = schemaManager.getGlobalOidRegistry().getNameSet( value ).iterator();
120
121            while ( list.hasNext() )
122            {
123                String objectClass = list.next();
124
125                if ( objectClasses.contains( objectClass ) )
126                {
127                    return true;
128                }
129            }
130        }
131
132        // no match so return false
133        return false;
134    }
135}