1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.normalization;
18
19
20 import org.apache.ldap.common.filter.*;
21 import org.apache.ldap.common.name.NameComponentNormalizer;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import javax.naming.NamingException;
26 import java.util.ArrayList;
27
28
29 /***
30 * A filter visitor which normalizes leaf node values as it visits them. It also removes
31 * leaf nodes from branches whose attributeType is undefined. It obviously cannot remove
32 * a leaf node from a filter which is only a leaf node. Checks to see if a filter is a
33 * leaf node with undefined attributeTypes should be done outside this visitor.
34 *
35 * Since this visitor may remove filter nodes it may produce negative results on filters,
36 * like NOT branch nodes without a child or AND and OR nodes with one or less children. This
37 * might make some partition implementations choke. To avoid this problem we clean up branch
38 * nodes that don't make sense. For example all BranchNodes without children are just
39 * removed. An AND and OR BranchNode with a single child is replaced with it's child for
40 * all but the topmost branchnode which we cannot replace. So again the top most branch
41 * node must be inspected by code outside of this visitor.
42 *
43 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
44 * @version $Rev$
45 */
46 public class ValueNormalizingVisitor implements FilterVisitor
47 {
48 /*** logger used by this class */
49 private final static Logger log = LoggerFactory.getLogger( ValueNormalizingVisitor.class );
50 /*** the name component normalizer used by this visitor */
51 private final NameComponentNormalizer ncn;
52
53
54 public ValueNormalizingVisitor( NameComponentNormalizer ncn )
55 {
56 this.ncn = ncn;
57 }
58
59
60 public void visit( ExprNode node )
61 {
62 if ( node instanceof SimpleNode )
63 {
64 SimpleNode snode = ( SimpleNode ) node;
65 String normalized;
66
67 try
68 {
69
70
71 if ( ! ncn.isDefined( snode.getAttribute() ) )
72 {
73 normalized = snode.getValue();
74 }
75 else if ( Character.isDigit( snode.getAttribute().charAt( 0 ) ) )
76 {
77 normalized = ncn.normalizeByOid( snode.getAttribute(), snode.getValue() );
78 }
79 else
80 {
81 normalized = ncn.normalizeByName( snode.getAttribute(), snode.getValue() );
82 }
83 }
84 catch ( NamingException e )
85 {
86 log.error( "Failed to normalize filter value: " + e.getMessage(), e );
87 throw new RuntimeException( e.getMessage() );
88 }
89
90 snode.setValue( normalized );
91 return;
92 }
93
94 if ( node instanceof BranchNode )
95 {
96 BranchNode bnode = ( BranchNode ) node;
97 StringBuffer buf = null;
98 for ( int ii = 0; ii < bnode.getChildren().size() ; ii++ )
99 {
100
101
102 ExprNode child = ( ExprNode ) bnode.getChildren().get( ii );
103 if ( child.isLeaf() )
104 {
105 LeafNode ln = ( LeafNode ) child;
106 if ( ! ncn.isDefined( ln.getAttribute() ) )
107 {
108 if ( buf == null )
109 {
110 buf = new StringBuffer();
111 }
112 else
113 {
114 buf.setLength( 0 );
115 }
116 buf.append( "Removing leaf node based on undefined attribute '" );
117 buf.append( ln.getAttribute() );
118 buf.append( "' from filter." );
119 log.warn( buf.toString() );
120
121
122 bnode.getChildren().remove( child );
123 ii--;
124 continue;
125 }
126 }
127
128 visit( child );
129 }
130
131
132
133
134
135 for ( int ii = 0; ii < bnode.getChildren().size() ; ii++ )
136 {
137 ExprNode unknown = ( ExprNode ) bnode.getChildren().get( ii );
138 if ( !unknown.isLeaf() )
139 {
140 BranchNode child = ( BranchNode ) unknown;
141
142
143 if ( child.getChildren().size() == 0 )
144 {
145
146 bnode.getChildren().remove( child );
147 ii--;
148 continue;
149 }
150
151
152
153 if ( child.getChildren().size() == 1 && child.getOperator() != BranchNode.NOT )
154 {
155 bnode.getChildren().remove( child );
156 if ( ii >= bnode.getChildren().size() )
157 {
158 bnode.getChildren().add( child.getChild() );
159 }
160 else
161 {
162 bnode.getChildren().add( ii, child.getChild() );
163 }
164 }
165 }
166 }
167 }
168 }
169
170
171 public boolean canVisit( ExprNode node )
172 {
173 return node instanceof BranchNode || node instanceof SimpleNode;
174 }
175
176
177 public boolean isPrefix()
178 {
179 return false;
180 }
181
182
183 public ArrayList getOrder( BranchNode node, ArrayList children )
184 {
185 return children;
186 }
187 }