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   *    https://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.api.ldap.codec.actions.request.search;
21  
22  
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.directory.api.asn1.DecoderException;
27  import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
28  import org.apache.directory.api.i18n.I18n;
29  import org.apache.directory.api.ldap.codec.AttributeValueAssertion;
30  import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
31  import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
32  import org.apache.directory.api.ldap.codec.search.AndFilter;
33  import org.apache.directory.api.ldap.codec.search.AttributeValueAssertionFilter;
34  import org.apache.directory.api.ldap.codec.search.ConnectorFilter;
35  import org.apache.directory.api.ldap.codec.search.ExtensibleMatchFilter;
36  import org.apache.directory.api.ldap.codec.search.Filter;
37  import org.apache.directory.api.ldap.codec.search.OrFilter;
38  import org.apache.directory.api.ldap.codec.search.PresentFilter;
39  import org.apache.directory.api.ldap.codec.search.SubstringFilter;
40  import org.apache.directory.api.ldap.model.entry.Value;
41  import org.apache.directory.api.ldap.model.exception.LdapSchemaException;
42  import org.apache.directory.api.ldap.model.filter.AndNode;
43  import org.apache.directory.api.ldap.model.filter.ApproximateNode;
44  import org.apache.directory.api.ldap.model.filter.BranchNode;
45  import org.apache.directory.api.ldap.model.filter.EqualityNode;
46  import org.apache.directory.api.ldap.model.filter.ExprNode;
47  import org.apache.directory.api.ldap.model.filter.ExtensibleNode;
48  import org.apache.directory.api.ldap.model.filter.GreaterEqNode;
49  import org.apache.directory.api.ldap.model.filter.LeafNode;
50  import org.apache.directory.api.ldap.model.filter.LessEqNode;
51  import org.apache.directory.api.ldap.model.filter.NotNode;
52  import org.apache.directory.api.ldap.model.filter.OrNode;
53  import org.apache.directory.api.ldap.model.filter.PresenceNode;
54  import org.apache.directory.api.ldap.model.filter.SubstringNode;
55  import org.apache.directory.api.ldap.model.message.SearchRequest;
56  import org.slf4j.Logger;
57  import org.slf4j.LoggerFactory;
58  
59  
60  /**
61   * The action used to initialize the AttributeDesc list
62   * <pre>
63   * SearchRequest ::= [APPLICATION 3] SEQUENCE {
64   *     ...
65   *     filter      Filter,
66   *     attributes  AttributeDescriptionList }
67   *
68   * AttributeDescriptionList ::= SEQUENCE OF
69   *     AttributeDescription
70   * </pre>
71   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
72   */
73  public class InitSearchRequestAttributeDescList extends GrammarAction<LdapMessageContainer<SearchRequest>>
74  {
75      /** The logger */
76      private static final Logger LOG = LoggerFactory.getLogger( InitSearchRequestAttributeDescList.class );
77  
78      /**
79       * Instantiates a new init attribute desc list action.
80       */
81      public InitSearchRequestAttributeDescList()
82      {
83          super( "Initialize AttributeDesc list" );
84      }
85  
86  
87      /**
88       * Transform the Filter part of a SearchRequest to an ExprNode
89       *
90       * @param filter The filter to be transformed
91       * @return An ExprNode
92       * @throws LdapSchemaException If teh filter is invalid
93       */
94      private ExprNode transform( Filter filter ) throws LdapSchemaException
95      {
96          if ( filter != null )
97          {
98              // Transform OR, AND or NOT leaves
99              if ( filter instanceof ConnectorFilter )
100             {
101                 BranchNode branch;
102 
103                 if ( filter instanceof AndFilter )
104                 {
105                     branch = new AndNode();
106                 }
107                 else if ( filter instanceof OrFilter )
108                 {
109                     branch = new OrNode();
110                 }
111                 else
112                 {
113                     branch = new NotNode();
114                 }
115 
116                 List<Filter> filtersSet = ( ( ConnectorFilter ) filter ).getFilterSet();
117 
118                 // Loop on all AND/OR children
119                 if ( filtersSet != null )
120                 {
121                     for ( Filter node : filtersSet )
122                     {
123                         branch.addNode( transform( node ) );
124                     }
125                 }
126 
127                 return branch;
128             }
129             else
130             {
131                 // Transform PRESENT or ATTRIBUTE_VALUE_ASSERTION
132                 LeafNode branch = null;
133 
134                 if ( filter instanceof PresentFilter )
135                 {
136                     branch = new PresenceNode( ( ( PresentFilter ) filter ).getAttributeDescription() );
137                 }
138                 else if ( filter instanceof AttributeValueAssertionFilter )
139                 {
140                     AttributeValueAssertion ava = ( ( AttributeValueAssertionFilter ) filter ).getAssertion();
141 
142                     // Transform =, >=, <=, ~= filters
143                     int filterType = ( ( AttributeValueAssertionFilter ) filter ).getFilterType();
144                     
145                     switch ( filterType )
146                     {
147                         case LdapCodecConstants.EQUALITY_MATCH_FILTER:
148                             branch = new EqualityNode( ava.getAttributeDesc(), ava.getAssertion() );
149                             break;
150 
151                         case LdapCodecConstants.GREATER_OR_EQUAL_FILTER:
152                             branch = new GreaterEqNode( ava.getAttributeDesc(), ava.getAssertion() );
153                             break;
154 
155                         case LdapCodecConstants.LESS_OR_EQUAL_FILTER:
156                             branch = new LessEqNode( ava.getAttributeDesc(), ava.getAssertion() );
157                             break;
158 
159                         case LdapCodecConstants.APPROX_MATCH_FILTER:
160                             branch = new ApproximateNode( ava.getAttributeDesc(), ava.getAssertion() );
161                             break;
162 
163                         default:
164                             throw new IllegalArgumentException( I18n.err( I18n.ERR_05503_UNEXPECTED_FILTER_TYPE, filterType ) );
165                     }
166 
167                 }
168                 else if ( filter instanceof SubstringFilter )
169                 {
170                     // Transform Substring filters
171                     SubstringFilter substrFilter = ( SubstringFilter ) filter;
172                     String initialString = null;
173                     String finalString = null;
174                     List<String> anyString = null;
175 
176                     if ( substrFilter.getInitialSubstrings() != null )
177                     {
178                         initialString = substrFilter.getInitialSubstrings();
179                     }
180 
181                     if ( substrFilter.getFinalSubstrings() != null )
182                     {
183                         finalString = substrFilter.getFinalSubstrings();
184                     }
185 
186                     if ( substrFilter.getAnySubstrings() != null )
187                     {
188                         anyString = new ArrayList<>();
189 
190                         for ( String any : substrFilter.getAnySubstrings() )
191                         {
192                             anyString.add( any );
193                         }
194                     }
195 
196                     branch = new SubstringNode( anyString, substrFilter.getType(), initialString, finalString );
197                 }
198                 else if ( filter instanceof ExtensibleMatchFilter )
199                 {
200                     // Transform Extensible Match Filter
201                     ExtensibleMatchFilter extFilter = ( ExtensibleMatchFilter ) filter;
202                     String matchingRule = null;
203 
204                     Value value = extFilter.getMatchValue();
205 
206                     if ( extFilter.getMatchingRule() != null )
207                     {
208                         matchingRule = extFilter.getMatchingRule();
209                     }
210 
211                     branch = new ExtensibleNode( extFilter.getType(), value, matchingRule, extFilter.isDnAttributes() );
212                 }
213 
214                 return branch;
215             }
216         }
217         else
218         {
219             // We have found nothing to transform. Return null then.
220             return null;
221         }
222     }
223 
224 
225     /**
226      * {@inheritDoc}
227      */
228     public void action( LdapMessageContainer<SearchRequest> container ) throws DecoderException
229     {
230         // Here, we have to inject the decoded filter into the SearchRequest
231         SearchRequest searchRequest = container.getMessage();
232 
233         try
234         {
235             searchRequest.setFilter( transform( container.getTopFilter() ) );
236         }
237         catch ( LdapSchemaException lse )
238         {
239             throw new DecoderException( lse.getMessage(), lse ); 
240         }
241 
242         // We can have an END transition
243         container.setGrammarEndAllowed( true );
244 
245         if ( LOG.isDebugEnabled() )
246         {
247             LOG.debug( I18n.msg( I18n.MSG_05158_INITIALIZE_ATT_DESC_LIST ) );
248         }
249     }
250 }