001 /*
002 * Copyright 2007-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2014 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.ldap.sdk;
022
023
024
025 import java.util.Collections;
026 import java.util.List;
027
028 import com.unboundid.asn1.ASN1StreamReader;
029 import com.unboundid.asn1.ASN1StreamReaderSequence;
030
031
032
033 /**
034 * This class provides a data structure for holding information about the result
035 * of processing a search request. This includes the elements of the
036 * {@code LDAPResult} object, but also contains additional information specific
037 * to the search operation. This includes:
038 * <UL>
039 * <LI>The number of {@code SearchResultEntry} objects returned from the
040 * server. This will be available regardless of whether the entries are
041 * included in this search result object or were returned through a
042 * {@code SearchResultListener}.</LI>
043 * <LI>The number of {@code SearchResultReference} objects returned from the
044 * server. This will be available regardless of whether the entries are
045 * included in this search result object or were returned through a
046 * {@code SearchResultListener}.</LI>
047 * <LI>A list of the {@code SearchResultEntry} objects returned from the
048 * server. This will be {@code null} if a {@code SearchResultListener}
049 * was used to return the entries.</LI>
050 * <LI>A list of the {@code SearchResultReference} objects returned from the
051 * server. This will be {@code null} if a {@code SearchResultListener}
052 * was used to return the entries.</LI>
053 * </UL>
054 */
055 public final class SearchResult
056 extends LDAPResult
057 {
058 /**
059 * The serial version UID for this serializable class.
060 */
061 private static final long serialVersionUID = 1938208530894131198L;
062
063
064
065 // The number of matching entries returned for this search.
066 private int numEntries;
067
068 // The number of search result references returned for this search.
069 private int numReferences;
070
071 // A list that may be used to hold the search result entries returned for
072 // this search.
073 private List<SearchResultEntry> searchEntries;
074
075 // A list that may be used to hold the search result references returned for
076 // this search.
077 private List<SearchResultReference> searchReferences;
078
079
080
081 /**
082 * Creates a new search result object with the provided information. This
083 * version of the constructor should be used if the search result entries and
084 * references were returned to the client via the {@code SearchResultListener}
085 * interface.
086 *
087 * @param messageID The message ID for the LDAP message that is
088 * associated with this LDAP result.
089 * @param resultCode The result code from the search result done
090 * response.
091 * @param diagnosticMessage The diagnostic message from the search result
092 * done response, if available.
093 * @param matchedDN The matched DN from the search result done
094 * response, if available.
095 * @param referralURLs The set of referral URLs from the search result
096 * done response, if available.
097 * @param numEntries The number of search result entries returned
098 * for this search.
099 * @param numReferences The number of search result references returned
100 * for this search.
101 * @param responseControls The set of controls from the search result done
102 * response, if available.
103 */
104 public SearchResult(final int messageID, final ResultCode resultCode,
105 final String diagnosticMessage, final String matchedDN,
106 final String[] referralURLs, final int numEntries,
107 final int numReferences, final Control[] responseControls)
108 {
109 super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
110 responseControls);
111
112 this.numEntries = numEntries;
113 this.numReferences = numReferences;
114
115 searchEntries = null;
116 searchReferences = null;
117 }
118
119
120
121 /**
122 * Creates a new search result object with the provided information. This
123 * version of the constructor should be used if the search result entries and
124 * references were collected in lists rather than returned to the requester
125 * through the {@code SearchResultListener} interface.
126 *
127 * @param messageID The message ID for the LDAP message that is
128 * associated with this LDAP result.
129 * @param resultCode The result code from the search result done
130 * response.
131 * @param diagnosticMessage The diagnostic message from the search result
132 * done response, if available.
133 * @param matchedDN The matched DN from the search result done
134 * response, if available.
135 * @param referralURLs The set of referral URLs from the search result
136 * done response, if available.
137 * @param searchEntries A list containing the set of search result
138 * entries returned by the server. It may only be
139 * {@code null} if the search result entries were
140 * returned through the
141 * {@code SearchResultListener} interface.
142 * @param searchReferences A list containing the set of search result
143 * references returned by the server. It may only
144 * be {@code null} if the search result entries
145 * were returned through the
146 * {@code SearchResultListener} interface.
147 * @param numEntries The number of search result entries returned
148 * for this search.
149 * @param numReferences The number of search result references returned
150 * for this search.
151 * @param responseControls The set of controls from the search result done
152 * response, if available.
153 */
154 public SearchResult(final int messageID, final ResultCode resultCode,
155 final String diagnosticMessage, final String matchedDN,
156 final String[] referralURLs,
157 final List<SearchResultEntry> searchEntries,
158 final List<SearchResultReference> searchReferences,
159 final int numEntries, final int numReferences,
160 final Control[] responseControls)
161 {
162 super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
163 responseControls);
164
165 this.numEntries = numEntries;
166 this.numReferences = numReferences;
167 this.searchEntries = searchEntries;
168 this.searchReferences = searchReferences;
169 }
170
171
172
173 /**
174 * Creates a new search result object with the provided message ID and with
175 * the protocol op and controls read from the given ASN.1 stream reader.
176 *
177 * @param messageID The LDAP message ID for the LDAP message that is
178 * associated with this LDAP result.
179 * @param messageSequence The ASN.1 stream reader sequence used in the
180 * course of reading the LDAP message elements.
181 * @param reader The ASN.1 stream reader from which to read the
182 * protocol op and controls.
183 *
184 * @return The decoded search result object.
185 *
186 * @throws LDAPException If a problem occurs while reading or decoding data
187 * from the ASN.1 stream reader.
188 */
189 static SearchResult readSearchResultFrom(final int messageID,
190 final ASN1StreamReaderSequence messageSequence,
191 final ASN1StreamReader reader)
192 throws LDAPException
193 {
194 final LDAPResult r =
195 LDAPResult.readLDAPResultFrom(messageID, messageSequence, reader);
196
197 return new SearchResult(messageID, r.getResultCode(),
198 r.getDiagnosticMessage(), r.getMatchedDN(), r.getReferralURLs(),
199 -1, -1, r.getResponseControls());
200 }
201
202
203
204 /**
205 * Retrieves the number of matching entries returned for the search operation.
206 *
207 * @return The number of matching entries returned for the search operation.
208 */
209 public int getEntryCount()
210 {
211 return numEntries;
212 }
213
214
215
216 /**
217 * Retrieves the number of search references returned for the search
218 * operation. This may be zero even if search references were received if the
219 * connection used when processing the search was configured to automatically
220 * follow referrals.
221 *
222 * @return The number of search references returned for the search operation.
223 */
224 public int getReferenceCount()
225 {
226 return numReferences;
227 }
228
229
230
231 /**
232 * Retrieves a list containing the matching entries returned from the search
233 * operation. This will only be available if a {@code SearchResultListener}
234 * was not used during the search.
235 *
236 * @return A list containing the matching entries returned from the search
237 * operation, or {@code null} if a {@code SearchResultListener} was
238 * used during the search.
239 */
240 public List<SearchResultEntry> getSearchEntries()
241 {
242 if (searchEntries == null)
243 {
244 return null;
245 }
246
247 return Collections.unmodifiableList(searchEntries);
248 }
249
250
251
252 /**
253 * Retrieves the search result entry with the specified DN from the set of
254 * entries returned. This will only be available if a
255 * {@code SearchResultListener} was not used during the search.
256 *
257 * @param dn The DN of the search result entry to retrieve. It must not
258 * be {@code null}.
259 *
260 * @return The search result entry with the provided DN, or {@code null} if
261 * the specified entry was not returned, or if a
262 * {@code SearchResultListener} was used for the search.
263 *
264 * @throws LDAPException If a problem is encountered while attempting to
265 * parse the provided DN or a search entry DN.
266 */
267 public SearchResultEntry getSearchEntry(final String dn)
268 throws LDAPException
269 {
270 if (searchEntries == null)
271 {
272 return null;
273 }
274
275 final DN parsedDN = new DN(dn);
276 for (final SearchResultEntry e : searchEntries)
277 {
278 if (parsedDN.equals(e.getParsedDN()))
279 {
280 return e;
281 }
282 }
283
284 return null;
285 }
286
287
288
289 /**
290 * Retrieves a list containing the search references returned from the search
291 * operation. This will only be available if a {@code SearchResultListener}
292 * was not used during the search, and may be empty even if search references
293 * were received if the connection used when processing the search was
294 * configured to automatically follow referrals.
295 *
296 * @return A list containing the search references returned from the search
297 * operation, or {@code null} if a {@code SearchResultListener} was
298 * used during the search.
299 */
300 public List<SearchResultReference> getSearchReferences()
301 {
302 if (searchReferences == null)
303 {
304 return null;
305 }
306
307 return Collections.unmodifiableList(searchReferences);
308 }
309
310
311
312 /**
313 * Provides information about the entries and references returned for the
314 * search operation. This must only be called when a search result is created
315 * and the search result must not be altered at any point after that.
316 *
317 * @param numEntries The number of entries returned for the search
318 * operation.
319 * @param searchEntries A list containing the entries returned from the
320 * search operation, or {@code null} if a
321 * {@code SearchResultListener} was used during the
322 * search.
323 * @param numReferences The number of references returned for the search
324 * operation.
325 * @param searchReferences A list containing the search references returned
326 * from the search operation, or {@code null} if a
327 * {@code SearchResultListener} was used during the
328 * search.
329 */
330 void setCounts(final int numEntries,
331 final List<SearchResultEntry> searchEntries,
332 final int numReferences,
333 final List<SearchResultReference> searchReferences)
334 {
335 this.numEntries = numEntries;
336 this.numReferences = numReferences;
337
338 if (searchEntries == null)
339 {
340 this.searchEntries = null;
341 }
342 else
343 {
344 this.searchEntries = Collections.unmodifiableList(searchEntries);
345 }
346
347 if (searchReferences == null)
348 {
349 this.searchReferences = null;
350 }
351 else
352 {
353 this.searchReferences = Collections.unmodifiableList(searchReferences);
354 }
355 }
356
357
358
359 /**
360 * Appends a string representation of this LDAP result to the provided buffer.
361 *
362 * @param buffer The buffer to which to append a string representation of
363 * this LDAP result.
364 */
365 @Override()
366 public void toString(final StringBuilder buffer)
367 {
368 buffer.append("SearchResult(resultCode=");
369 buffer.append(getResultCode());
370
371 final int messageID = getMessageID();
372 if (messageID >= 0)
373 {
374 buffer.append(", messageID=");
375 buffer.append(messageID);
376 }
377
378 final String diagnosticMessage = getDiagnosticMessage();
379 if (diagnosticMessage != null)
380 {
381 buffer.append(", diagnosticMessage='");
382 buffer.append(diagnosticMessage);
383 buffer.append('\'');
384 }
385
386 final String matchedDN = getMatchedDN();
387 if (matchedDN != null)
388 {
389 buffer.append(", matchedDN='");
390 buffer.append(matchedDN);
391 buffer.append('\'');
392 }
393
394 final String[] referralURLs = getReferralURLs();
395 if (referralURLs.length > 0)
396 {
397 buffer.append(", referralURLs={");
398 for (int i=0; i < referralURLs.length; i++)
399 {
400 if (i > 0)
401 {
402 buffer.append(", ");
403 }
404
405 buffer.append('\'');
406 buffer.append(referralURLs[i]);
407 buffer.append('\'');
408 }
409 buffer.append('}');
410 }
411
412 if (numEntries >= 0)
413 {
414 buffer.append(", entriesReturned=");
415 buffer.append(numEntries);
416 }
417
418 if (numReferences >= 0)
419 {
420 buffer.append(", referencesReturned=");
421 buffer.append(numReferences);
422 }
423
424 final Control[] responseControls = getResponseControls();
425 if (responseControls.length > 0)
426 {
427 buffer.append(", responseControls={");
428 for (int i=0; i < responseControls.length; i++)
429 {
430 if (i > 0)
431 {
432 buffer.append(", ");
433 }
434
435 buffer.append(responseControls[i]);
436 }
437 buffer.append('}');
438 }
439
440 buffer.append(')');
441 }
442 }