001 /* 002 * Copyright 2007-2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2008-2015 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 }