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 *    https://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 */
020package org.apache.directory.api.ldap.model.message;
021
022
023import java.util.HashSet;
024import java.util.Set;
025
026import javax.naming.directory.SearchControls;
027
028import org.apache.directory.api.i18n.I18n;
029import org.apache.directory.api.ldap.model.exception.LdapException;
030import org.apache.directory.api.ldap.model.schema.AttributeType;
031import org.apache.directory.api.ldap.model.schema.AttributeTypeOptions;
032import org.apache.directory.api.ldap.model.schema.SchemaManager;
033import org.apache.directory.api.ldap.model.schema.SchemaUtils;
034import org.apache.directory.api.util.Strings;
035import org.slf4j.Logger;
036import org.slf4j.LoggerFactory;
037
038
039/**
040 * A container for Search parameters. It replaces the SearchControls.
041 *
042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043 */
044public class SearchParams
045{
046    /** The LoggerFactory used by this class */
047    private static final Logger LOG = LoggerFactory.getLogger( SearchParams.class );
048
049    /** The search scope. Default to OBJECT */
050    private SearchScope scope = SearchScope.OBJECT;
051
052    /** The time limit. Default to 0 (infinite) */
053    private int timeLimit = 0;
054
055    /** The size limit. Default to 0 (infinite) */
056    private long sizeLimit = 0;
057
058    /** If we should return only types. Default to false */
059    private boolean typesOnly = false;
060
061    /** The aliasDerefMode. Default to DEREF_ALWAYS */
062    private AliasDerefMode aliasDerefMode = AliasDerefMode.DEREF_ALWAYS;
063
064    /** The list of attributes to return, as Strings. Default to an empty set */
065    private Set<String> returningAttributesStr;
066
067    /** The list of attributes to return, once it has been normalized. Default to an empty set */
068    private Set<AttributeTypeOptions> returningAttributes;
069
070    /** The set of controls for this search. Default to an empty set */
071    private Set<Control> controls;
072
073
074    /**
075     * Creates a new instance of SearchContext, with all the values set to 
076     * default.
077     */
078    public SearchParams()
079    {
080        returningAttributes = new HashSet<>();
081        returningAttributesStr = new HashSet<>();
082        controls = new HashSet<>();
083    }
084
085
086    /**
087     * @return the scope
088     */
089    public SearchScope getScope()
090    {
091        return scope;
092    }
093
094
095    /**
096     * @param scope the scope to set
097     */
098    public void setScope( SearchScope scope )
099    {
100        this.scope = scope;
101    }
102
103
104    /**
105     * @return the timeLimit
106     */
107    public int getTimeLimit()
108    {
109        return timeLimit;
110    }
111
112
113    /**
114     * @param timeLimit the timeLimit to set
115     */
116    public void setTimeLimit( int timeLimit )
117    {
118        this.timeLimit = timeLimit;
119    }
120
121
122    /**
123     * @return the sizeLimit
124     */
125    public long getSizeLimit()
126    {
127        return sizeLimit;
128    }
129
130
131    /**
132     * @param sizeLimit the sizeLimit to set
133     */
134    public void setSizeLimit( long sizeLimit )
135    {
136        this.sizeLimit = sizeLimit;
137    }
138
139
140    /**
141     * @return the typesOnly
142     */
143    public boolean isTypesOnly()
144    {
145        return typesOnly;
146    }
147
148
149    /**
150     * @param typesOnly the typesOnly to set
151     */
152    public void setTypesOnly( boolean typesOnly )
153    {
154        this.typesOnly = typesOnly;
155    }
156
157
158    /**
159     * @return the aliasDerefMode
160     */
161    public AliasDerefMode getAliasDerefMode()
162    {
163        return aliasDerefMode;
164    }
165
166
167    /**
168     * @param aliasDerefMode the aliasDerefMode to set
169     */
170    public void setAliasDerefMode( AliasDerefMode aliasDerefMode )
171    {
172        this.aliasDerefMode = aliasDerefMode;
173    }
174
175
176    /**
177     * @return the returningAttributes
178     */
179    public Set<AttributeTypeOptions> getReturningAttributes()
180    {
181        return returningAttributes;
182    }
183
184
185    /**
186     * @return the returningAttributes
187     */
188    public Set<String> getReturningAttributesStr()
189    {
190        return returningAttributesStr;
191    }
192
193
194    /**
195     * Normalize the ReturningAttributes. It reads all the String from the returningAttributesString,
196     * and grab the associated AttributeType from the schema to store it into the returningAttributes
197     * Set.
198     *
199     * @param schemaManager The schema manager
200     */
201    public void normalize( SchemaManager schemaManager )
202    {
203        for ( String returnAttribute : returningAttributesStr )
204        {
205            try
206            {
207                String id = SchemaUtils.stripOptions( returnAttribute );
208                Set<String> options = SchemaUtils.getOptions( returnAttribute );
209
210                AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id );
211                AttributeTypeOptions attrOptions = new AttributeTypeOptions( attributeType, options );
212
213                returningAttributes.add( attrOptions );
214            }
215            catch ( LdapException ne )
216            {
217                if ( LOG.isWarnEnabled() )
218                {
219                    LOG.warn( I18n.msg( I18n.MSG_13500_ATTRIBUTE_NOT_IN_SCHEMA, returnAttribute ) );
220                }
221                
222                // Unknown attributes should be silently ignored, as RFC 2251 states
223            }
224        }
225    }
226
227
228    /**
229     * @param returningAttributes the returningAttributes to set
230     */
231    public void setReturningAttributes( String... returningAttributes )
232    {
233        if ( returningAttributes != null )
234        {
235            for ( String returnAttribute : returningAttributes )
236            {
237                this.returningAttributesStr.add( returnAttribute );
238            }
239        }
240    }
241
242
243    /**
244     * @param returningAttribute the returningAttributes to add
245     */
246    public void addReturningAttributes( String returningAttribute )
247    {
248        this.returningAttributesStr.add( returningAttribute );
249    }
250
251
252    /**
253     * @return the controls
254     */
255    public Set<Control> getControls()
256    {
257        return controls;
258    }
259
260
261    /**
262     * @param controls the controls to set
263     */
264    public void setControls( Set<Control> controls )
265    {
266        this.controls = controls;
267    }
268
269
270    /**
271     * @param control the controls to set
272     */
273    public void addControl( Control control )
274    {
275        this.controls.add( control );
276    }
277
278
279    /**
280     * Creates a {@link SearchParams} from JNDI search controls.
281     *
282     * @param searchControls the search controls
283     * @param aliasDerefMode the alias deref mode
284     * @return the search params
285     */
286    public static SearchParams toSearchParams( SearchControls searchControls, AliasDerefMode aliasDerefMode )
287    {
288        SearchParams searchParams = new SearchParams();
289
290        searchParams.setAliasDerefMode( aliasDerefMode );
291        searchParams.setTimeLimit( searchControls.getTimeLimit() );
292        searchParams.setSizeLimit( searchControls.getCountLimit() );
293        searchParams.setScope( SearchScope.getSearchScope( searchControls.getSearchScope() ) );
294        searchParams.setTypesOnly( searchControls.getReturningObjFlag() );
295
296        if ( searchControls.getReturningAttributes() != null )
297        {
298            for ( String returningAttribute : searchControls.getReturningAttributes() )
299            {
300                searchParams.addReturningAttributes( returningAttribute );
301            }
302        }
303
304        return searchParams;
305    }
306
307
308    /**
309     * {@inheritDoc}
310     */
311    @Override
312    public String toString()
313    {
314        StringBuilder sb = new StringBuilder();
315
316        sb.append( "Search parameters :\n" );
317        sb.append( "    scope : " ).append( scope ).append( "\n" );
318        sb.append( "    Alias dereferencing : " ).append( aliasDerefMode ).append( "\n" );
319        sb.append( "    types only : " ).append( typesOnly ).append( "\n" );
320
321        if ( !returningAttributesStr.isEmpty() )
322        {
323            sb.append( "    returning attributes : " ).append( Strings.setToString( returningAttributesStr ) )
324                .append( "\n" );
325        }
326
327        if ( timeLimit > 0 )
328        {
329            sb.append( "    timeLimit : " ).append( timeLimit ).append( "\n" );
330        }
331        else
332        {
333            sb.append( "    no timeLimit\n" );
334        }
335
336        if ( timeLimit > 0 )
337        {
338            sb.append( "    sizeLimit : " ).append( sizeLimit ).append( "\n" );
339        }
340        else
341        {
342            sb.append( "    no sizeLimit\n" );
343        }
344
345        if ( !controls.isEmpty() )
346        {
347            for ( Control control : controls )
348            {
349                sb.append( "    control : " ).
350                    append( control.getOid() ).append( "/" ).
351                    append( control.getClass().getName() ).append( "\n" );
352            }
353        }
354
355        return sb.toString();
356    }
357}