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 }