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