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.controls;
022
023
024
025 import com.unboundid.asn1.ASN1Element;
026 import com.unboundid.asn1.ASN1Integer;
027 import com.unboundid.asn1.ASN1OctetString;
028 import com.unboundid.asn1.ASN1Sequence;
029 import com.unboundid.ldap.sdk.Control;
030 import com.unboundid.ldap.sdk.LDAPException;
031 import com.unboundid.ldap.sdk.ResultCode;
032 import com.unboundid.util.NotMutable;
033 import com.unboundid.util.ThreadSafety;
034 import com.unboundid.util.ThreadSafetyLevel;
035
036 import static com.unboundid.ldap.sdk.controls.ControlMessages.*;
037 import static com.unboundid.util.Debug.*;
038 import static com.unboundid.util.StaticUtils.*;
039 import static com.unboundid.util.Validator.*;
040
041
042
043 /**
044 * This class provides an implementation of the LDAP virtual list view (VLV)
045 * request control as defined in draft-ietf-ldapext-ldapv3-vlv. This control
046 * may be used to retrieve arbitrary "pages" of entries from the complete set of
047 * search results. It is similar to the {@link SimplePagedResultsControl}, with
048 * the exception that the simple paged results control requires scrolling
049 * through the results in sequential order, while the VLV control allows
050 * starting and resuming at any arbitrary point in the result set. The starting
051 * point may be specified using either a positional offset, or based on the
052 * first entry with a value that is greater than or equal to a specified value.
053 * <BR><BR>
054 * When the start of the result set is to be specified using an offset, then the
055 * virtual list view request control should include the following elements:
056 * <UL>
057 * <LI>{@code targetOffset} -- The position in the result set of the entry to
058 * target for the next page of results to return. Note that the offset is
059 * one-based (so the first entry has offset 1, the second entry has offset
060 * 2, etc.).</LI>
061 * <LI>{@code beforeCount} -- The number of entries before the entry specified
062 * as the target offset that should be retrieved.</LI>
063 * <LI>{@code afterCount} -- The number of entries after the entry specified
064 * as the target offset that should be retrieved.</LI>
065 * <LI>{@code contentCount} -- The estimated total number of entries that
066 * are in the total result set. This should be zero for the first request
067 * in a VLV search sequence, but should be the value returned by the
068 * server in the corresponding response control for subsequent searches as
069 * part of the VLV sequence.</LI>
070 * <LI>{@code contextID} -- This is an optional cookie that may be used to
071 * help the server resume processing on a VLV search. It should be absent
072 * from the initial request, but for subsequent requests should be the
073 * value returned in the previous VLV response control.</LI>
074 * </UL>
075 * When the start of the result set is to be specified using a search string,
076 * then the virtual list view request control should include the following
077 * elements:
078 * <UL>
079 * <LI>{@code assertionValue} -- The value that specifies the start of the
080 * page of results to retrieve. The target entry will be the first entry
081 * in which the value for the primary sort attribute is greater than or
082 * equal to this assertion value.</LI>
083 * <LI>{@code beforeCount} -- The number of entries before the entry specified
084 * by the assertion value that should be retrieved.</LI>
085 * <LI>{@code afterCount} -- The number of entries after the entry specified
086 * by the assertion value that should be retrieved.</LI>
087 * <LI>{@code contentCount} -- The estimated total number of entries that
088 * are in the total result set. This should be zero for the first request
089 * in a VLV search sequence, but should be the value returned by the
090 * server in the corresponding response control for subsequent searches as
091 * part of the VLV sequence.</LI>
092 * <LI>{@code contextID} -- This is an optional cookie that may be used to
093 * help the server resume processing on a VLV search. It should be absent
094 * from the initial request, but for subsequent requests should be the
095 * value returned in the previous VLV response control.</LI>
096 * </UL>
097 * Note that the virtual list view request control may only be included in a
098 * search request if that search request also includes the
099 * {@link ServerSideSortRequestControl}. This is necessary to ensure that a
100 * consistent order is used for the resulting entries.
101 * <BR><BR>
102 * If the search is successful, then the search result done response may include
103 * a {@link VirtualListViewResponseControl} to provide information about the
104 * state of the virtual list view processing.
105 * <BR><BR>
106 * <H2>Example</H2>
107 * The following example demonstrates the use of the virtual list view request
108 * control to iterate through all users, retrieving up to 10 entries at a time:
109 * <PRE>
110 * // Perform a search to retrieve all users in the server, but only retrieving
111 * // ten at a time. Ensure that the users are sorted in ascending order by
112 * // last name, then first name.
113 * int numSearches = 0;
114 * int totalEntriesReturned = 0;
115 * SearchRequest searchRequest = new SearchRequest("dc=example,dc=com",
116 * SearchScope.SUB, Filter.createEqualityFilter("objectClass", "person"));
117 * int vlvOffset = 1;
118 * int vlvContentCount = 0;
119 * ASN1OctetString vlvContextID = null;
120 * while (true)
121 * {
122 * // Note that the VLV control always requires the server-side sort
123 * // control.
124 * searchRequest.setControls(
125 * new ServerSideSortRequestControl(new SortKey("sn"),
126 * new SortKey("givenName")),
127 * new VirtualListViewRequestControl(vlvOffset, 0, 9, vlvContentCount,
128 * vlvContextID));
129 * SearchResult searchResult = connection.search(searchRequest);
130 * numSearches++;
131 * totalEntriesReturned += searchResult.getEntryCount();
132 * for (SearchResultEntry e : searchResult.getSearchEntries())
133 * {
134 * // Do something with each entry...
135 * }
136 *
137 * LDAPTestUtils.assertHasControl(searchResult,
138 * VirtualListViewResponseControl.VIRTUAL_LIST_VIEW_RESPONSE_OID);
139 * VirtualListViewResponseControl vlvResponseControl =
140 * VirtualListViewResponseControl.get(searchResult);
141 * vlvContentCount = vlvResponseControl.getContentCount();
142 * vlvOffset += 10;
143 * vlvContextID = vlvResponseControl.getContextID();
144 * if (vlvOffset > vlvContentCount)
145 * {
146 * break;
147 * }
148 * }
149 * </PRE>
150 */
151 @NotMutable()
152 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
153 public final class VirtualListViewRequestControl
154 extends Control
155 {
156 /**
157 * The OID (2.16.840.1.113730.3.4.9) for the virtual list view request
158 * control.
159 */
160 public static final String VIRTUAL_LIST_VIEW_REQUEST_OID =
161 "2.16.840.1.113730.3.4.9";
162
163
164
165 /**
166 * The BER type that will be used for the target element when the target is
167 * specified by offset.
168 */
169 private static final byte TARGET_TYPE_OFFSET = (byte) 0xA0;
170
171
172
173 /**
174 * The BER type that will be used for the target element when the target is
175 * specified by an assertion value.
176 */
177 private static final byte TARGET_TYPE_GREATER_OR_EQUAL = (byte) 0x81;
178
179
180
181 /**
182 * The serial version UID for this serializable class.
183 */
184 private static final long serialVersionUID = 4348423177859960815L;
185
186
187
188 // The assertion value that will be used to identify the start of the
189 // requested page of results for a greater-or-equal target type.
190 private final ASN1OctetString assertionValue;
191
192 // The context ID that may be used to help the server continue in the same
193 // result set for subsequent searches.
194 private final ASN1OctetString contextID;
195
196 // The maximum number of entries to return after the target entry.
197 private final int afterCount;
198
199 // The maximum number of entries to return before the target entry.
200 private final int beforeCount;
201
202 // The estimated number of entries in the complete result set.
203 private final int contentCount;
204
205 // The position of the entry at the start of the requested page of results for
206 // an offset-based target type.
207 private final int targetOffset;
208
209
210
211 /**
212 * Creates a new virtual list view request control that will identify the
213 * beginning of the result set by a target offset. It will be marked
214 * critical.
215 *
216 * @param targetOffset The position of the entry that should be used as the
217 * start of the result set.
218 * @param beforeCount The maximum number of entries that should be returned
219 * before the entry with the specified target offset.
220 * @param afterCount The maximum number of entries that should be returned
221 * after the entry with the specified target offset.
222 * @param contentCount The estimated number of entries in the result set.
223 * For the first request in a series of searches with
224 * the VLV control, it should be zero. For subsequent
225 * searches in the VLV sequence, it should be the
226 * content count included in the response control from
227 * the previous search.
228 * @param contextID The context ID that may be used to help the server
229 * continue in the same result set for subsequent
230 * searches. For the first request in a series of
231 * searches with the VLV control, it should be
232 * {@code null}. For subsequent searches in the VLV
233 * sequence, it should be the (possibly {@code null}
234 * context ID included in the response control from the
235 * previous search.
236 */
237 public VirtualListViewRequestControl(final int targetOffset,
238 final int beforeCount, final int afterCount,
239 final int contentCount, final ASN1OctetString contextID)
240 {
241 this(targetOffset, beforeCount, afterCount, contentCount, contextID, true);
242 }
243
244
245
246 /**
247 * Creates a new virtual list view request control that will identify the
248 * beginning of the result set by an assertion value. It will be marked
249 * critical.
250 *
251 * @param assertionValue The assertion value that will be used to identify
252 * the start of the result set. The target entry will
253 * be the first entry with a value for the primary
254 * sort attribute that is greater than or equal to
255 * this assertion value. It must not be {@code null}.
256 * @param beforeCount The maximum number of entries that should be
257 * returned before the first entry with a value
258 * greater than or equal to the provided assertion
259 * value.
260 * @param afterCount The maximum number of entries that should be
261 * returned after the first entry with a value
262 * greater than or equal to the provided assertion
263 * value.
264 * @param contextID The context ID that may be used to help the server
265 * continue in the same result set for subsequent
266 * searches. For the first request in a series of
267 * searches with the VLV control, it should be
268 * {@code null}. For subsequent searches in the VLV
269 * sequence, it should be the (possibly {@code null}
270 * context ID included in the response control from
271 * the previous search.
272 */
273 public VirtualListViewRequestControl(final String assertionValue,
274 final int beforeCount, final int afterCount,
275 final ASN1OctetString contextID)
276 {
277 this(new ASN1OctetString(assertionValue), beforeCount, afterCount,
278 contextID, true);
279 }
280
281
282
283 /**
284 * Creates a new virtual list view request control that will identify the
285 * beginning of the result set by an assertion value. It will be marked
286 * critical.
287 *
288 * @param assertionValue The assertion value that will be used to identify
289 * the start of the result set. The target entry will
290 * be the first entry with a value for the primary
291 * sort attribute that is greater than or equal to
292 * this assertion value. It must not be {@code null}.
293 * @param beforeCount The maximum number of entries that should be
294 * returned before the first entry with a value
295 * greater than or equal to the provided assertion
296 * value.
297 * @param afterCount The maximum number of entries that should be
298 * returned after the first entry with a value
299 * greater than or equal to the provided assertion
300 * value.
301 * @param contextID The context ID that may be used to help the server
302 * continue in the same result set for subsequent
303 * searches. For the first request in a series of
304 * searches with the VLV control, it should be
305 * {@code null}. For subsequent searches in the VLV
306 * sequence, it should be the (possibly {@code null}
307 * context ID included in the response control from
308 * the previous search.
309 */
310 public VirtualListViewRequestControl(final byte[] assertionValue,
311 final int beforeCount, final int afterCount,
312 final ASN1OctetString contextID)
313 {
314 this(new ASN1OctetString(assertionValue), beforeCount, afterCount,
315 contextID, true);
316 }
317
318
319
320 /**
321 * Creates a new virtual list view request control that will identify the
322 * beginning of the result set by an assertion value. It will be marked
323 * critical.
324 *
325 * @param assertionValue The assertion value that will be used to identify
326 * the start of the result set. The target entry will
327 * be the first entry with a value for the primary
328 * sort attribute that is greater than or equal to
329 * this assertion value. It must not be {@code null}.
330 * @param beforeCount The maximum number of entries that should be
331 * returned before the first entry with a value
332 * greater than or equal to the provided assertion
333 * value.
334 * @param afterCount The maximum number of entries that should be
335 * returned after the first entry with a value
336 * greater than or equal to the provided assertion
337 * value.
338 * @param contextID The context ID that may be used to help the server
339 * continue in the same result set for subsequent
340 * searches. For the first request in a series of
341 * searches with the VLV control, it should be
342 * {@code null}. For subsequent searches in the VLV
343 * sequence, it should be the (possibly {@code null}
344 * context ID included in the response control from
345 * the previous search.
346 */
347 public VirtualListViewRequestControl(final ASN1OctetString assertionValue,
348 final int beforeCount, final int afterCount,
349 final ASN1OctetString contextID)
350 {
351 this(assertionValue, beforeCount, afterCount, contextID, true);
352 }
353
354
355
356 /**
357 * Creates a new virtual list view request control that will identify the
358 * beginning of the result set by a target offset.
359 *
360 * @param targetOffset The position of the entry that should be used as the
361 * start of the result set.
362 * @param beforeCount The maximum number of entries that should be returned
363 * before the entry with the specified target offset.
364 * @param afterCount The maximum number of entries that should be returned
365 * after the entry with the specified target offset.
366 * @param contentCount The estimated number of entries in the result set.
367 * For the first request in a series of searches with
368 * the VLV control, it should be zero. For subsequent
369 * searches in the VLV sequence, it should be the
370 * content count included in the response control from
371 * the previous search.
372 * @param contextID The context ID that may be used to help the server
373 * continue in the same result set for subsequent
374 * searches. For the first request in a series of
375 * searches with the VLV control, it should be
376 * {@code null}. For subsequent searches in the VLV
377 * sequence, it should be the (possibly {@code null}
378 * context ID included in the response control from the
379 * previous search.
380 * @param isCritical Indicates whether this control should be marked
381 * critical.
382 */
383 public VirtualListViewRequestControl(final int targetOffset,
384 final int beforeCount, final int afterCount,
385 final int contentCount, final ASN1OctetString contextID,
386 final boolean isCritical)
387 {
388 super(VIRTUAL_LIST_VIEW_REQUEST_OID, isCritical,
389 encodeValue(targetOffset, beforeCount, afterCount, contentCount,
390 contextID));
391
392 this.targetOffset = targetOffset;
393 this.beforeCount = beforeCount;
394 this.afterCount = afterCount;
395 this.contentCount = contentCount;
396 this.contextID = contextID;
397
398 assertionValue = null;
399 }
400
401
402
403 /**
404 * Creates a new virtual list view request control that will identify the
405 * beginning of the result set by an assertion value. It will be marked
406 * critical.
407 *
408 * @param assertionValue The assertion value that will be used to identify
409 * the start of the result set. The target entry will
410 * be the first entry with a value for the primary
411 * sort attribute that is greater than or equal to
412 * this assertion value. It must not be {@code null}.
413 * @param beforeCount The maximum number of entries that should be
414 * returned before the first entry with a value
415 * greater than or equal to the provided assertion
416 * value.
417 * @param afterCount The maximum number of entries that should be
418 * returned after the first entry with a value
419 * greater than or equal to the provided assertion
420 * value.
421 * @param contextID The context ID that may be used to help the server
422 * continue in the same result set for subsequent
423 * searches. For the first request in a series of
424 * searches with the VLV control, it should be
425 * {@code null}. For subsequent searches in the VLV
426 * sequence, it should be the (possibly {@code null}
427 * context ID included in the response control from
428 * the previous search.
429 * @param isCritical Indicates whether this control should be marked
430 * critical.
431 */
432 public VirtualListViewRequestControl(final String assertionValue,
433 final int beforeCount, final int afterCount,
434 final ASN1OctetString contextID, final boolean isCritical)
435 {
436 this(new ASN1OctetString(assertionValue), beforeCount, afterCount,
437 contextID, isCritical);
438 }
439
440
441
442 /**
443 * Creates a new virtual list view request control that will identify the
444 * beginning of the result set by an assertion value. It will be marked
445 * critical.
446 *
447 * @param assertionValue The assertion value that will be used to identify
448 * the start of the result set. The target entry will
449 * be the first entry with a value for the primary
450 * sort attribute that is greater than or equal to
451 * this assertion value. It must not be {@code null}.
452 * @param beforeCount The maximum number of entries that should be
453 * returned before the first entry with a value
454 * greater than or equal to the provided assertion
455 * value.
456 * @param afterCount The maximum number of entries that should be
457 * returned after the first entry with a value
458 * greater than or equal to the provided assertion
459 * value.
460 * @param contextID The context ID that may be used to help the server
461 * continue in the same result set for subsequent
462 * searches. For the first request in a series of
463 * searches with the VLV control, it should be
464 * {@code null}. For subsequent searches in the VLV
465 * sequence, it should be the (possibly {@code null}
466 * context ID included in the response control from
467 * the previous search.
468 * @param isCritical Indicates whether this control should be marked
469 * critical.
470 */
471 public VirtualListViewRequestControl(final byte[] assertionValue,
472 final int beforeCount, final int afterCount,
473 final ASN1OctetString contextID, final boolean isCritical)
474 {
475 this(new ASN1OctetString(assertionValue), beforeCount, afterCount,
476 contextID, isCritical);
477 }
478
479
480
481 /**
482 * Creates a new virtual list view request control that will identify the
483 * beginning of the result set by an assertion value. It will be marked
484 * critical.
485 *
486 * @param assertionValue The assertion value that will be used to identify
487 * the start of the result set. The target entry will
488 * be the first entry with a value for the primary
489 * sort attribute that is greater than or equal to
490 * this assertion value. It must not be {@code null}.
491 * @param beforeCount The maximum number of entries that should be
492 * returned before the first entry with a value
493 * greater than or equal to the provided assertion
494 * value.
495 * @param afterCount The maximum number of entries that should be
496 * returned after the first entry with a value
497 * greater than or equal to the provided assertion
498 * value.
499 * @param contextID The context ID that may be used to help the server
500 * continue in the same result set for subsequent
501 * searches. For the first request in a series of
502 * searches with the VLV control, it should be
503 * {@code null}. For subsequent searches in the VLV
504 * sequence, it should be the (possibly {@code null}
505 * context ID included in the response control from
506 * the previous search.
507 * @param isCritical Indicates whether this control should be marked
508 * critical.
509 */
510 public VirtualListViewRequestControl(final ASN1OctetString assertionValue,
511 final int beforeCount, final int afterCount,
512 final ASN1OctetString contextID, final boolean isCritical)
513 {
514 super(VIRTUAL_LIST_VIEW_REQUEST_OID, isCritical,
515 encodeValue(assertionValue, beforeCount, afterCount, contextID));
516
517 this.assertionValue = assertionValue;
518 this.beforeCount = beforeCount;
519 this.afterCount = afterCount;
520 this.contextID = contextID;
521
522 targetOffset = -1;
523 contentCount = -1;
524 }
525
526
527
528 /**
529 * Creates a new virtual list view request control which is decoded from the
530 * provided generic control.
531 *
532 * @param control The generic control to be decoded as a virtual list view
533 * request control.
534 *
535 * @throws LDAPException If the provided control cannot be decoded as a
536 * virtual list view request control.
537 */
538 public VirtualListViewRequestControl(final Control control)
539 throws LDAPException
540 {
541 super(control);
542
543 final ASN1OctetString value = control.getValue();
544 if (value == null)
545 {
546 throw new LDAPException(ResultCode.DECODING_ERROR,
547 ERR_VLV_REQUEST_NO_VALUE.get());
548 }
549
550 try
551 {
552 final ASN1Element valueElement = ASN1Element.decode(value.getValue());
553 final ASN1Element[] elements =
554 ASN1Sequence.decodeAsSequence(valueElement).elements();
555
556 beforeCount = ASN1Integer.decodeAsInteger(elements[0]).intValue();
557 afterCount = ASN1Integer.decodeAsInteger(elements[1]).intValue();
558
559 switch (elements[2].getType())
560 {
561 case TARGET_TYPE_OFFSET:
562 assertionValue = null;
563 final ASN1Element[] offsetElements =
564 ASN1Sequence.decodeAsSequence(elements[2]).elements();
565 targetOffset =
566 ASN1Integer.decodeAsInteger(offsetElements[0]).intValue();
567 contentCount =
568 ASN1Integer.decodeAsInteger(offsetElements[1]).intValue();
569 break;
570
571 case TARGET_TYPE_GREATER_OR_EQUAL:
572 assertionValue = ASN1OctetString.decodeAsOctetString(elements[2]);
573 targetOffset = -1;
574 contentCount = -1;
575 break;
576
577 default:
578 throw new LDAPException(ResultCode.DECODING_ERROR,
579 ERR_VLV_REQUEST_INVALID_ELEMENT_TYPE.get(
580 toHex(elements[2].getType())));
581 }
582
583 if (elements.length == 4)
584 {
585 contextID = ASN1OctetString.decodeAsOctetString(elements[3]);
586 }
587 else
588 {
589 contextID = null;
590 }
591 }
592 catch (LDAPException le)
593 {
594 debugException(le);
595 throw le;
596 }
597 catch (Exception e)
598 {
599 debugException(e);
600 throw new LDAPException(ResultCode.DECODING_ERROR,
601 ERR_VLV_REQUEST_CANNOT_DECODE.get(e), e);
602 }
603 }
604
605
606
607 /**
608 * Encodes the provided information into an octet string that can be used as
609 * the value for this control.
610 *
611 * @param targetOffset The position of the entry that should be used as the
612 * start of the result set.
613 * @param beforeCount The maximum number of entries that should be returned
614 * before the entry with the specified target offset.
615 * @param afterCount The maximum number of entries that should be returned
616 * after the entry with the specified target offset.
617 * @param contentCount The estimated number of entries in the result set.
618 * For the first request in a series of searches with
619 * the VLV control, it should be zero. For subsequent
620 * searches in the VLV sequence, it should be the
621 * content count included in the response control from
622 * the previous search.
623 * @param contextID The context ID that may be used to help the server
624 * continue in the same result set for subsequent
625 * searches. For the first request in a series of
626 * searches with the VLV control, it should be
627 * {@code null}. For subsequent searches in the VLV
628 * sequence, it should be the (possibly {@code null}
629 * context ID included in the response control from the
630 * previous search.
631 *
632 * @return An ASN.1 octet string that can be used as the value for this
633 * control.
634 */
635 private static ASN1OctetString encodeValue(final int targetOffset,
636 final int beforeCount,
637 final int afterCount,
638 final int contentCount,
639 final ASN1OctetString contextID)
640 {
641 final ASN1Element[] targetElements =
642 {
643 new ASN1Integer(targetOffset),
644 new ASN1Integer(contentCount)
645 };
646
647 final ASN1Element[] vlvElements;
648 if (contextID == null)
649 {
650 vlvElements = new ASN1Element[]
651 {
652 new ASN1Integer(beforeCount),
653 new ASN1Integer(afterCount),
654 new ASN1Sequence(TARGET_TYPE_OFFSET, targetElements)
655 };
656 }
657 else
658 {
659 vlvElements = new ASN1Element[]
660 {
661 new ASN1Integer(beforeCount),
662 new ASN1Integer(afterCount),
663 new ASN1Sequence(TARGET_TYPE_OFFSET, targetElements),
664 contextID
665 };
666 }
667
668 return new ASN1OctetString(new ASN1Sequence(vlvElements).encode());
669 }
670
671
672
673 /**
674 * Encodes the provided information into an octet string that can be used as
675 * the value for this control.
676 *
677 * @param assertionValue The assertion value that will be used to identify
678 * the start of the result set. The target entry will
679 * be the first entry with a value for the primary
680 * sort attribute that is greater than or equal to
681 * this assertion value.
682 * @param beforeCount The maximum number of entries that should be
683 * returned before the first entry with a value
684 * greater than or equal to the provided assertion
685 * value.
686 * @param afterCount The maximum number of entries that should be
687 * returned after the first entry with a value
688 * greater than or equal to the provided assertion
689 * value.
690 * @param contextID The context ID that may be used to help the server
691 * continue in the same result set for subsequent
692 * searches. For the first request in a series of
693 * searches with the VLV control, it should be
694 * {@code null}. For subsequent searches in the VLV
695 * sequence, it should be the (possibly {@code null}
696 * context ID included in the response control from
697 * the previous search.
698 *
699 * @return An ASN.1 octet string that can be used as the value for this
700 * control.
701 */
702 private static ASN1OctetString encodeValue(
703 final ASN1OctetString assertionValue,
704 final int beforeCount,
705 final int afterCount,
706 final ASN1OctetString contextID)
707 {
708 ensureNotNull(assertionValue);
709
710 final ASN1Element[] vlvElements;
711 if (contextID == null)
712 {
713 vlvElements = new ASN1Element[]
714 {
715 new ASN1Integer(beforeCount),
716 new ASN1Integer(afterCount),
717 new ASN1OctetString(TARGET_TYPE_GREATER_OR_EQUAL,
718 assertionValue.getValue())
719 };
720 }
721 else
722 {
723 vlvElements = new ASN1Element[]
724 {
725 new ASN1Integer(beforeCount),
726 new ASN1Integer(afterCount),
727 new ASN1OctetString(TARGET_TYPE_GREATER_OR_EQUAL,
728 assertionValue.getValue()),
729 contextID
730 };
731 }
732
733 return new ASN1OctetString(new ASN1Sequence(vlvElements).encode());
734 }
735
736
737
738 /**
739 * Retrieves the target offset position for this virtual list view request
740 * control, if applicable.
741 *
742 * @return The target offset position for this virtual list view request
743 * control, or -1 if the target is specified by an assertion value.
744 */
745 public int getTargetOffset()
746 {
747 return targetOffset;
748 }
749
750
751
752 /**
753 * Retrieves the string representation of the assertion value for this virtual
754 * list view request control, if applicable.
755 *
756 * @return The string representation of the assertion value for this virtual
757 * list view request control, or {@code null} if the target is
758 * specified by offset.
759 */
760 public String getAssertionValueString()
761 {
762 if (assertionValue == null)
763 {
764 return null;
765 }
766 else
767 {
768 return assertionValue.stringValue();
769 }
770 }
771
772
773
774 /**
775 * Retrieves the byte array representation of the assertion value for this
776 * virtual list view request control, if applicable.
777 *
778 * @return The byte array representation of the assertion value for this
779 * virtual list view request control, or {@code null} if the target
780 * is specified by offset.
781 */
782 public byte[] getAssertionValueBytes()
783 {
784 if (assertionValue == null)
785 {
786 return null;
787 }
788 else
789 {
790 return assertionValue.getValue();
791 }
792 }
793
794
795
796 /**
797 * Retrieves the assertion value for this virtual list view request control,
798 * if applicable.
799 *
800 * @return The assertion value for this virtual list view request control, or
801 * {@code null} if the target is specified by offset.
802 */
803 public ASN1OctetString getAssertionValue()
804 {
805 return assertionValue;
806 }
807
808
809
810 /**
811 * Retrieves the number of entries that should be retrieved before the target
812 * entry.
813 *
814 * @return The number of entries that should be retrieved before the target
815 * entry.
816 */
817 public int getBeforeCount()
818 {
819 return beforeCount;
820 }
821
822
823
824 /**
825 * Retrieves the number of entries that should be retrieved after the target
826 * entry.
827 *
828 * @return The number of entries that should be retrieved after the target
829 * entry.
830 */
831 public int getAfterCount()
832 {
833 return afterCount;
834 }
835
836
837
838 /**
839 * Retrieves the estimated number of entries in the result set, if applicable.
840 *
841 * @return The estimated number of entries in the result set, zero if it
842 * is not known (for the first search in a sequence where the
843 * target is specified by offset), or -1 if the target is specified
844 * by an assertion value.
845 */
846 public int getContentCount()
847 {
848 return contentCount;
849 }
850
851
852
853 /**
854 * Retrieves the context ID for this virtual list view request control, if
855 * available.
856 *
857 * @return The context ID for this virtual list view request control, or
858 * {@code null} if there is none.
859 */
860 public ASN1OctetString getContextID()
861 {
862 return contextID;
863 }
864
865
866
867 /**
868 * {@inheritDoc}
869 */
870 @Override()
871 public String getControlName()
872 {
873 return INFO_CONTROL_NAME_VLV_REQUEST.get();
874 }
875
876
877
878 /**
879 * {@inheritDoc}
880 */
881 @Override()
882 public void toString(final StringBuilder buffer)
883 {
884 buffer.append("VirtualListViewRequestControl(beforeCount=");
885 buffer.append(beforeCount);
886 buffer.append(", afterCount=");
887 buffer.append(afterCount);
888
889 if (assertionValue == null)
890 {
891 buffer.append(", targetOffset=");
892 buffer.append(targetOffset);
893 buffer.append(", contentCount=");
894 buffer.append(contentCount);
895 }
896 else
897 {
898 buffer.append(", assertionValue='");
899 buffer.append(assertionValue.stringValue());
900 buffer.append('\'');
901 }
902
903 buffer.append(", isCritical=");
904 buffer.append(isCritical());
905 buffer.append(')');
906 }
907 }