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 */ 021package com.unboundid.ldap.sdk; 022 023 024 025import java.util.Collections; 026import java.util.List; 027 028import com.unboundid.asn1.ASN1StreamReader; 029import com.unboundid.asn1.ASN1StreamReaderSequence; 030import com.unboundid.util.NotMutable; 031import com.unboundid.util.ThreadSafety; 032import 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) 060public 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}