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     */
020    package org.apache.directory.server.xdbm.search.impl;
021    
022    
023    import java.util.Iterator;
024    
025    import org.apache.directory.server.xdbm.Index;
026    import org.apache.directory.server.xdbm.IndexEntry;
027    import org.apache.directory.server.xdbm.Store;
028    import org.apache.directory.server.xdbm.search.Evaluator;
029    import org.apache.directory.shared.ldap.entry.EntryAttribute;
030    import org.apache.directory.shared.ldap.entry.ServerEntry;
031    import org.apache.directory.shared.ldap.filter.PresenceNode;
032    import org.apache.directory.shared.ldap.schema.AttributeType;
033    import org.apache.directory.shared.ldap.schema.SchemaManager;
034    
035    
036    /**
037     * An Evaluator which determines if candidates are matched by GreaterEqNode
038     * assertions.
039     *
040     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
041     * @version $Rev$
042     */
043    public class PresenceEvaluator<ID> implements Evaluator<PresenceNode, ServerEntry, ID>
044    {
045        private final PresenceNode node;
046        private final Store<ServerEntry, ID> db;
047        private final AttributeType type;
048        private final SchemaManager schemaManager;
049        private final Index<String, ServerEntry, ID> idx;
050    
051    
052        public PresenceEvaluator( PresenceNode node, Store<ServerEntry, ID> db, SchemaManager schemaManager )
053            throws Exception
054        {
055            this.db = db;
056            this.node = node;
057            this.schemaManager = schemaManager;
058            this.type = schemaManager.lookupAttributeTypeRegistry( node.getAttribute() );
059    
060            if ( db.hasUserIndexOn( node.getAttribute() ) )
061            {
062                idx = db.getPresenceIndex();
063            }
064            else
065            {
066                idx = null;
067            }
068        }
069    
070    
071        public PresenceNode getExpression()
072        {
073            return node;
074        }
075    
076    
077        public AttributeType getAttributeType()
078        {
079            return type;
080        }
081    
082    
083        // TODO - determine if comaparator and index entry should have the Value
084        // wrapper or the raw normalized value
085        public boolean evaluate( IndexEntry<?, ServerEntry, ID> indexEntry ) throws Exception
086        {
087            if ( idx != null )
088            {
089                return idx.forward( type.getOid(), indexEntry.getId() );
090            }
091    
092            ServerEntry entry = indexEntry.getObject();
093    
094            // resuscitate the entry if it has not been and set entry in IndexEntry
095            if ( null == entry )
096            {
097                entry = db.lookup( indexEntry.getId() );
098                indexEntry.setObject( entry );
099            }
100    
101            return evaluateEntry( entry );
102        }
103    
104    
105        // TODO - determine if comaparator and index entry should have the Value
106        // wrapper or the raw normalized value
107        public boolean evaluateId( ID id ) throws Exception
108        {
109            if ( idx != null )
110            {
111                return idx.forward( type.getOid(), id );
112            }
113    
114            return evaluateEntry( db.lookup( id ) );
115        }
116    
117    
118        // TODO - determine if comaparator and index entry should have the Value
119        // wrapper or the raw normalized value
120        public boolean evaluateEntry( ServerEntry entry ) throws Exception
121        {
122            if ( db.hasSystemIndexOn( node.getAttribute() ) )
123            {
124                // we don't maintain a presence index for objectClass, entryUUID, and entryCSN
125                // however as every entry has such an attribute this evaluator always evaluates to true
126                return true;
127            }
128    
129            // get the attribute
130            EntryAttribute attr = entry.get( type );
131    
132            // if the attribute exists just return true
133            if ( attr != null )
134            {
135                return true;
136            }
137    
138            // If we do not have the attribute, loop through the sub classes of
139            // the attributeType.  Perhaps the entry has an attribute value of a
140            // subtype (descendant) that will produce a match
141            if ( schemaManager.getAttributeTypeRegistry().hasDescendants( node.getAttribute() ) )
142            {
143                // TODO check to see if descendant handling is necessary for the
144                // index so we can match properly even when for example a name
145                // attribute is used instead of more specific commonName
146                Iterator<AttributeType> descendants = schemaManager.getAttributeTypeRegistry().descendants(
147                    node.getAttribute() );
148    
149                do
150                {
151                    AttributeType descendant = descendants.next();
152    
153                    attr = entry.get( descendant );
154    
155                    if ( attr != null )
156                    {
157                        return true;
158                    }
159                }
160                while ( descendants.hasNext() );
161            }
162    
163            // we fell through so a match was not found - assertion was false.
164            return false;
165        }
166    }