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.core.normalization;
021    
022    
023    import java.util.Iterator;
024    import java.util.List;
025    
026    import org.apache.directory.server.i18n.I18n;
027    import org.apache.directory.shared.ldap.exception.LdapException;
028    import org.apache.directory.shared.ldap.filter.ApproximateNode;
029    import org.apache.directory.shared.ldap.filter.BranchNode;
030    import org.apache.directory.shared.ldap.filter.EqualityNode;
031    import org.apache.directory.shared.ldap.filter.ExprNode;
032    import org.apache.directory.shared.ldap.filter.ExtensibleNode;
033    import org.apache.directory.shared.ldap.filter.FilterVisitor;
034    import org.apache.directory.shared.ldap.filter.GreaterEqNode;
035    import org.apache.directory.shared.ldap.filter.LeafNode;
036    import org.apache.directory.shared.ldap.filter.LessEqNode;
037    import org.apache.directory.shared.ldap.filter.OrNode;
038    import org.apache.directory.shared.ldap.filter.PresenceNode;
039    import org.apache.directory.shared.ldap.filter.SubstringNode;
040    import org.apache.directory.shared.ldap.schema.AttributeType;
041    import org.apache.directory.shared.ldap.schema.SchemaManager;
042    
043    
044    /**
045     *
046     *
047     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
048     * @version $Rev: 429176 $
049     */
050    public class ExpandingVisitor implements FilterVisitor
051    {
052        /** The schemaManager */
053        private SchemaManager schemaManager;
054        
055        
056        /**
057         * 
058         * Creates a new instance of ExpandingVisitor.
059         *
060         * @param schemaManager The schemaManager
061         */
062        public ExpandingVisitor( SchemaManager schemaManager )
063        {
064            this.schemaManager = schemaManager;
065        }
066    
067    
068        public boolean canVisit( ExprNode node )
069        {
070            return node instanceof BranchNode;
071        }
072    
073    
074        public List<ExprNode> getOrder( BranchNode node, List<ExprNode> children )
075        {
076            return children;
077        }
078    
079    
080        public boolean isPrefix()
081        {
082            return false;
083        }
084    
085    
086        public Object visit( ExprNode node )
087        {
088            BranchNode bnode = ( BranchNode ) node;
089    
090            // --------------------------------------------------------------------
091            // we want to check each child leaf node to see if it must be expanded
092            // children that are branch nodes are recursively visited
093            // --------------------------------------------------------------------
094    
095            final List<ExprNode> children = bnode.getChildren();
096            int childNumber = 0;
097    
098            for ( ExprNode child : children )
099            {
100                if ( child instanceof LeafNode )
101                {
102                    LeafNode leaf = ( LeafNode ) child;
103    
104                    try
105                    {
106                        if ( schemaManager.getAttributeTypeRegistry().hasDescendants( leaf.getAttribute() ) )
107                        {
108                            // create a new OR node to hold all descendent forms
109                            // add to this node the generalized leaf node and 
110                            // replace the old leaf with the new OR branch node
111                            BranchNode orNode = new OrNode();
112                            orNode.getChildren().add( leaf );
113                            children.set( childNumber++, orNode );
114    
115                            // iterate through descendants adding them to the orNode
116                            Iterator<AttributeType> descendants = schemaManager.getAttributeTypeRegistry().descendants( leaf.getAttribute() );
117    
118                            while ( descendants.hasNext() )
119                            {
120                                LeafNode newLeaf = null;
121                                AttributeType descendant = descendants.next();
122    
123                                if ( leaf instanceof PresenceNode )
124                                {
125                                    newLeaf = new PresenceNode( descendant.getOid() );
126                                }
127                                else if ( leaf instanceof ApproximateNode )
128                                {
129                                    ApproximateNode approximateNode = ( ApproximateNode ) leaf;
130    
131                                    newLeaf = new ApproximateNode( descendant.getOid(), approximateNode.getValue() );
132                                }
133                                else if ( leaf instanceof EqualityNode )
134                                {
135                                    EqualityNode equalityNode = ( EqualityNode ) leaf;
136    
137                                    newLeaf = new EqualityNode( descendant.getOid(), equalityNode.getValue() );
138                                }
139                                else if ( leaf instanceof GreaterEqNode )
140                                {
141                                    GreaterEqNode greaterEqNode = ( GreaterEqNode ) leaf;
142    
143                                    newLeaf = new GreaterEqNode( descendant.getOid(), greaterEqNode.getValue() );
144                                }
145                                else if ( leaf instanceof LessEqNode )
146                                {
147                                    LessEqNode lessEqNode = ( LessEqNode ) leaf;
148    
149                                    newLeaf = new LessEqNode( descendant.getOid(), lessEqNode.getValue() );
150                                }
151                                else if ( leaf instanceof ExtensibleNode )
152                                {
153                                    ExtensibleNode extensibleNode = ( ExtensibleNode ) leaf;
154                                    newLeaf = new ExtensibleNode( descendant.getOid(), extensibleNode.getValue(),
155                                        extensibleNode.getMatchingRuleId(), extensibleNode.hasDnAttributes() );
156                                }
157                                else if ( leaf instanceof SubstringNode )
158                                {
159                                    SubstringNode substringNode = ( SubstringNode ) leaf;
160                                    newLeaf = new SubstringNode( descendant.getOid(), substringNode.getInitial(),
161                                        substringNode.getFinal() );
162                                }
163                                else
164                                {
165                                    throw new IllegalStateException( I18n.err( I18n.ERR_260, leaf ) );
166                                }
167    
168                                orNode.addNode( newLeaf );
169                            }
170                        }
171                    }
172                    catch ( LdapException e )
173                    {
174                        // log something here and throw a runtime excpetion
175                        throw new RuntimeException( I18n.err( I18n.ERR_261 ) );
176                    }
177                }
178                else
179                {
180                    visit( child );
181                }
182            } // end for loop
183    
184            return null;
185        }
186    }