View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.core.normalization;
21  
22  
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import javax.naming.NamingException;
27  
28  import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
29  import org.apache.directory.shared.ldap.filter.ApproximateNode;
30  import org.apache.directory.shared.ldap.filter.BranchNode;
31  import org.apache.directory.shared.ldap.filter.EqualityNode;
32  import org.apache.directory.shared.ldap.filter.ExprNode;
33  import org.apache.directory.shared.ldap.filter.ExtensibleNode;
34  import org.apache.directory.shared.ldap.filter.FilterVisitor;
35  import org.apache.directory.shared.ldap.filter.GreaterEqNode;
36  import org.apache.directory.shared.ldap.filter.LeafNode;
37  import org.apache.directory.shared.ldap.filter.LessEqNode;
38  import org.apache.directory.shared.ldap.filter.OrNode;
39  import org.apache.directory.shared.ldap.filter.PresenceNode;
40  import org.apache.directory.shared.ldap.filter.SubstringNode;
41  import org.apache.directory.shared.ldap.schema.AttributeType;
42  
43  
44  /**
45   *
46   *
47   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
48   * @version $Rev: 429176 $
49   */
50  public class ExpandingVisitor implements FilterVisitor
51  {
52      private final AttributeTypeRegistry attrRegistry;
53  
54  
55      /**
56       * 
57       * Creates a new instance of ExpandingVisitor.
58       *
59       * @param attrRegistry The AttributeType registry
60       */
61      public ExpandingVisitor( AttributeTypeRegistry attrRegistry )
62      {
63          this.attrRegistry = attrRegistry;
64      }
65  
66  
67      public boolean canVisit( ExprNode node )
68      {
69          return node instanceof BranchNode;
70      }
71  
72  
73      public List<ExprNode> getOrder( BranchNode node, List<ExprNode> children )
74      {
75          return children;
76      }
77  
78  
79      public boolean isPrefix()
80      {
81          return false;
82      }
83  
84  
85      public Object visit( ExprNode node )
86      {
87          BranchNode bnode = ( BranchNode ) node;
88  
89          // --------------------------------------------------------------------
90          // we want to check each child leaf node to see if it must be expanded
91          // children that are branch nodes are recursively visited
92          // --------------------------------------------------------------------
93  
94          final List<ExprNode> children = bnode.getChildren();
95          int childNumber = 0;
96  
97          for ( ExprNode child : children )
98          {
99              if ( child instanceof LeafNode )
100             {
101                 LeafNode leaf = ( LeafNode ) child;
102 
103                 try
104                 {
105                     if ( attrRegistry.hasDescendants( leaf.getAttribute() ) )
106                     {
107                         // create a new OR node to hold all descendent forms
108                         // add to this node the generalized leaf node and 
109                         // replace the old leaf with the new OR branch node
110                         BranchNode orNode = new OrNode();
111                         orNode.getChildren().add( leaf );
112                         children.set( childNumber++, orNode );
113 
114                         // iterate through descendants adding them to the orNode
115                         Iterator<AttributeType> descendants = attrRegistry.descendants( leaf.getAttribute() );
116 
117                         while ( descendants.hasNext() )
118                         {
119                             LeafNode newLeaf = null;
120                             AttributeType descendant = descendants.next();
121 
122                             if ( leaf instanceof PresenceNode )
123                             {
124                                 newLeaf = new PresenceNode( descendant.getOid() );
125                             }
126                             else if ( leaf instanceof ApproximateNode )
127                             {
128                                 ApproximateNode approximateNode = ( ApproximateNode ) leaf;
129 
130                                 newLeaf = new ApproximateNode( descendant.getOid(), approximateNode.getValue() );
131                             }
132                             else if ( leaf instanceof EqualityNode )
133                             {
134                                 EqualityNode equalityNode = ( EqualityNode ) leaf;
135 
136                                 newLeaf = new EqualityNode( descendant.getOid(), equalityNode.getValue() );
137                             }
138                             else if ( leaf instanceof GreaterEqNode )
139                             {
140                                 GreaterEqNode greaterEqNode = ( GreaterEqNode ) leaf;
141 
142                                 newLeaf = new GreaterEqNode( descendant.getOid(), greaterEqNode.getValue() );
143                             }
144                             else if ( leaf instanceof LessEqNode )
145                             {
146                                 LessEqNode lessEqNode = ( LessEqNode ) leaf;
147 
148                                 newLeaf = new LessEqNode( descendant.getOid(), lessEqNode.getValue() );
149                             }
150                             else if ( leaf instanceof ExtensibleNode )
151                             {
152                                 ExtensibleNode extensibleNode = ( ExtensibleNode ) leaf;
153                                 newLeaf = new ExtensibleNode( descendant.getOid(), extensibleNode.getValue(),
154                                     extensibleNode.getMatchingRuleId(), extensibleNode.hasDnAttributes() );
155                             }
156                             else if ( leaf instanceof SubstringNode )
157                             {
158                                 SubstringNode substringNode = ( SubstringNode ) leaf;
159                                 newLeaf = new SubstringNode( descendant.getOid(), substringNode.getInitial(),
160                                     substringNode.getFinal() );
161                             }
162                             else
163                             {
164                                 throw new IllegalStateException( "Unknown assertion type: " + leaf );
165                             }
166 
167                             orNode.addNode( newLeaf );
168                         }
169                     }
170                 }
171                 catch ( NamingException e )
172                 {
173                     // log something here and throw a runtime excpetion
174                     throw new RuntimeException( "Failed to expand node" );
175                 }
176             }
177             else
178             {
179                 visit( child );
180             }
181         } // end for loop
182 
183         return null;
184     }
185 }