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