1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.rest.model;
21
22 import java.io.IOException;
23 import java.io.Serializable;
24 import java.io.StringReader;
25 import java.io.StringWriter;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.NavigableSet;
30
31 import javax.xml.bind.annotation.XmlAttribute;
32 import javax.xml.bind.annotation.XmlElement;
33 import javax.xml.bind.annotation.XmlRootElement;
34
35 import com.google.protobuf.HBaseZeroCopyByteString;
36 import org.apache.hadoop.classification.InterfaceAudience;
37 import org.apache.hadoop.hbase.HConstants;
38 import org.apache.hadoop.hbase.client.Scan;
39 import org.apache.hadoop.hbase.filter.BinaryComparator;
40 import org.apache.hadoop.hbase.filter.BinaryPrefixComparator;
41 import org.apache.hadoop.hbase.filter.BitComparator;
42 import org.apache.hadoop.hbase.filter.ByteArrayComparable;
43 import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
44 import org.apache.hadoop.hbase.filter.ColumnPaginationFilter;
45 import org.apache.hadoop.hbase.filter.ColumnPrefixFilter;
46 import org.apache.hadoop.hbase.filter.ColumnRangeFilter;
47 import org.apache.hadoop.hbase.filter.CompareFilter;
48 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
49 import org.apache.hadoop.hbase.filter.DependentColumnFilter;
50 import org.apache.hadoop.hbase.filter.FamilyFilter;
51 import org.apache.hadoop.hbase.filter.Filter;
52 import org.apache.hadoop.hbase.filter.FilterList;
53 import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
54 import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
55 import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
56 import org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter;
57 import org.apache.hadoop.hbase.filter.NullComparator;
58 import org.apache.hadoop.hbase.filter.PageFilter;
59 import org.apache.hadoop.hbase.filter.PrefixFilter;
60 import org.apache.hadoop.hbase.filter.QualifierFilter;
61 import org.apache.hadoop.hbase.filter.RandomRowFilter;
62 import org.apache.hadoop.hbase.filter.RegexStringComparator;
63 import org.apache.hadoop.hbase.filter.RowFilter;
64 import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter;
65 import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
66 import org.apache.hadoop.hbase.filter.SkipFilter;
67 import org.apache.hadoop.hbase.filter.SubstringComparator;
68 import org.apache.hadoop.hbase.filter.TimestampsFilter;
69 import org.apache.hadoop.hbase.filter.ValueFilter;
70 import org.apache.hadoop.hbase.filter.WhileMatchFilter;
71 import org.apache.hadoop.hbase.rest.ProtobufMessageHandler;
72 import org.apache.hadoop.hbase.rest.protobuf.generated.ScannerMessage.Scanner;
73 import org.apache.hadoop.hbase.security.visibility.Authorizations;
74 import org.apache.hadoop.hbase.util.Base64;
75 import org.apache.hadoop.hbase.util.Bytes;
76
77 import com.google.protobuf.ByteString;
78 import com.sun.jersey.api.json.JSONConfiguration;
79 import com.sun.jersey.api.json.JSONJAXBContext;
80 import com.sun.jersey.api.json.JSONMarshaller;
81 import com.sun.jersey.api.json.JSONUnmarshaller;
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 @XmlRootElement(name="Scanner")
103 @InterfaceAudience.Private
104 public class ScannerModel implements ProtobufMessageHandler, Serializable {
105
106 private static final long serialVersionUID = 1L;
107
108 private byte[] startRow = HConstants.EMPTY_START_ROW;
109 private byte[] endRow = HConstants.EMPTY_END_ROW;;
110 private List<byte[]> columns = new ArrayList<byte[]>();
111 private int batch = Integer.MAX_VALUE;
112 private long startTime = 0;
113 private long endTime = Long.MAX_VALUE;
114 private String filter = null;
115 private int maxVersions = Integer.MAX_VALUE;
116 private int caching = -1;
117 private List<String> labels = new ArrayList<String>();
118
119 @XmlRootElement
120 static class FilterModel {
121
122 @XmlRootElement
123 static class ByteArrayComparableModel {
124 @XmlAttribute public String type;
125 @XmlAttribute public String value;
126 @XmlAttribute public String op;
127
128 static enum ComparatorType {
129 BinaryComparator,
130 BinaryPrefixComparator,
131 BitComparator,
132 NullComparator,
133 RegexStringComparator,
134 SubstringComparator
135 }
136
137 public ByteArrayComparableModel() { }
138
139 public ByteArrayComparableModel(
140 ByteArrayComparable comparator) {
141 String typeName = comparator.getClass().getSimpleName();
142 ComparatorType type = ComparatorType.valueOf(typeName);
143 this.type = typeName;
144 switch (type) {
145 case BinaryComparator:
146 case BinaryPrefixComparator:
147 this.value = Base64.encodeBytes(comparator.getValue());
148 break;
149 case BitComparator:
150 this.value = Base64.encodeBytes(comparator.getValue());
151 this.op = ((BitComparator)comparator).getOperator().toString();
152 break;
153 case NullComparator:
154 break;
155 case RegexStringComparator:
156 case SubstringComparator:
157 this.value = Bytes.toString(comparator.getValue());
158 break;
159 default:
160 throw new RuntimeException("unhandled filter type: " + type);
161 }
162 }
163
164 public ByteArrayComparable build() {
165 ByteArrayComparable comparator;
166 switch (ComparatorType.valueOf(type)) {
167 case BinaryComparator:
168 comparator = new BinaryComparator(Base64.decode(value));
169 break;
170 case BinaryPrefixComparator:
171 comparator = new BinaryPrefixComparator(Base64.decode(value));
172 break;
173 case BitComparator:
174 comparator = new BitComparator(Base64.decode(value),
175 BitComparator.BitwiseOp.valueOf(op));
176 break;
177 case NullComparator:
178 comparator = new NullComparator();
179 break;
180 case RegexStringComparator:
181 comparator = new RegexStringComparator(value);
182 break;
183 case SubstringComparator:
184 comparator = new SubstringComparator(value);
185 break;
186 default:
187 throw new RuntimeException("unhandled comparator type: " + type);
188 }
189 return comparator;
190 }
191
192 }
193
194
195
196 @XmlAttribute public String type;
197 @XmlAttribute public String op;
198 @XmlElement ByteArrayComparableModel comparator;
199 @XmlAttribute public String value;
200 @XmlElement public List<FilterModel> filters;
201 @XmlAttribute public Integer limit;
202 @XmlAttribute public Integer offset;
203 @XmlAttribute public String family;
204 @XmlAttribute public String qualifier;
205 @XmlAttribute public Boolean ifMissing;
206 @XmlAttribute public Boolean latestVersion;
207 @XmlAttribute public String minColumn;
208 @XmlAttribute public Boolean minColumnInclusive;
209 @XmlAttribute public String maxColumn;
210 @XmlAttribute public Boolean maxColumnInclusive;
211 @XmlAttribute public Boolean dropDependentColumn;
212 @XmlAttribute public Float chance;
213 @XmlElement public List<String> prefixes;
214 @XmlElement public List<Long> timestamps;
215
216 static enum FilterType {
217 ColumnCountGetFilter,
218 ColumnPaginationFilter,
219 ColumnPrefixFilter,
220 ColumnRangeFilter,
221 DependentColumnFilter,
222 FamilyFilter,
223 FilterList,
224 FirstKeyOnlyFilter,
225 InclusiveStopFilter,
226 KeyOnlyFilter,
227 MultipleColumnPrefixFilter,
228 PageFilter,
229 PrefixFilter,
230 QualifierFilter,
231 RandomRowFilter,
232 RowFilter,
233 SingleColumnValueExcludeFilter,
234 SingleColumnValueFilter,
235 SkipFilter,
236 TimestampsFilter,
237 ValueFilter,
238 WhileMatchFilter
239 }
240
241 public FilterModel() { }
242
243 public FilterModel(Filter filter) {
244 String typeName = filter.getClass().getSimpleName();
245 FilterType type = FilterType.valueOf(typeName);
246 this.type = typeName;
247 switch (type) {
248 case ColumnCountGetFilter:
249 this.limit = ((ColumnCountGetFilter)filter).getLimit();
250 break;
251 case ColumnPaginationFilter:
252 this.limit = ((ColumnPaginationFilter)filter).getLimit();
253 this.offset = ((ColumnPaginationFilter)filter).getOffset();
254 break;
255 case ColumnPrefixFilter:
256 this.value = Base64.encodeBytes(((ColumnPrefixFilter)filter).getPrefix());
257 break;
258 case ColumnRangeFilter:
259 this.minColumn = Base64.encodeBytes(((ColumnRangeFilter)filter).getMinColumn());
260 this.minColumnInclusive = ((ColumnRangeFilter)filter).getMinColumnInclusive();
261 this.maxColumn = Base64.encodeBytes(((ColumnRangeFilter)filter).getMaxColumn());
262 this.maxColumnInclusive = ((ColumnRangeFilter)filter).getMaxColumnInclusive();
263 break;
264 case DependentColumnFilter: {
265 DependentColumnFilter dcf = (DependentColumnFilter)filter;
266 this.family = Base64.encodeBytes(dcf.getFamily());
267 byte[] qualifier = dcf.getQualifier();
268 if (qualifier != null) {
269 this.qualifier = Base64.encodeBytes(qualifier);
270 }
271 this.op = dcf.getOperator().toString();
272 this.comparator = new ByteArrayComparableModel(dcf.getComparator());
273 this.dropDependentColumn = dcf.dropDependentColumn();
274 } break;
275 case FilterList:
276 this.op = ((FilterList)filter).getOperator().toString();
277 this.filters = new ArrayList<FilterModel>();
278 for (Filter child: ((FilterList)filter).getFilters()) {
279 this.filters.add(new FilterModel(child));
280 }
281 break;
282 case FirstKeyOnlyFilter:
283 case KeyOnlyFilter:
284 break;
285 case InclusiveStopFilter:
286 this.value =
287 Base64.encodeBytes(((InclusiveStopFilter)filter).getStopRowKey());
288 break;
289 case MultipleColumnPrefixFilter:
290 this.prefixes = new ArrayList<String>();
291 for (byte[] prefix: ((MultipleColumnPrefixFilter)filter).getPrefix()) {
292 this.prefixes.add(Base64.encodeBytes(prefix));
293 }
294 break;
295 case PageFilter:
296 this.value = Long.toString(((PageFilter)filter).getPageSize());
297 break;
298 case PrefixFilter:
299 this.value = Base64.encodeBytes(((PrefixFilter)filter).getPrefix());
300 break;
301 case FamilyFilter:
302 case QualifierFilter:
303 case RowFilter:
304 case ValueFilter:
305 this.op = ((CompareFilter)filter).getOperator().toString();
306 this.comparator =
307 new ByteArrayComparableModel(
308 ((CompareFilter)filter).getComparator());
309 break;
310 case RandomRowFilter:
311 this.chance = ((RandomRowFilter)filter).getChance();
312 break;
313 case SingleColumnValueExcludeFilter:
314 case SingleColumnValueFilter: {
315 SingleColumnValueFilter scvf = (SingleColumnValueFilter) filter;
316 this.family = Base64.encodeBytes(scvf.getFamily());
317 byte[] qualifier = scvf.getQualifier();
318 if (qualifier != null) {
319 this.qualifier = Base64.encodeBytes(qualifier);
320 }
321 this.op = scvf.getOperator().toString();
322 this.comparator =
323 new ByteArrayComparableModel(scvf.getComparator());
324 if (scvf.getFilterIfMissing()) {
325 this.ifMissing = true;
326 }
327 if (scvf.getLatestVersionOnly()) {
328 this.latestVersion = true;
329 }
330 } break;
331 case SkipFilter:
332 this.filters = new ArrayList<FilterModel>();
333 this.filters.add(new FilterModel(((SkipFilter)filter).getFilter()));
334 break;
335 case TimestampsFilter:
336 this.timestamps = ((TimestampsFilter)filter).getTimestamps();
337 break;
338 case WhileMatchFilter:
339 this.filters = new ArrayList<FilterModel>();
340 this.filters.add(
341 new FilterModel(((WhileMatchFilter)filter).getFilter()));
342 break;
343 default:
344 throw new RuntimeException("unhandled filter type " + type);
345 }
346 }
347
348 public Filter build() {
349 Filter filter;
350 switch (FilterType.valueOf(type)) {
351 case ColumnCountGetFilter:
352 filter = new ColumnCountGetFilter(limit);
353 break;
354 case ColumnPaginationFilter:
355 filter = new ColumnPaginationFilter(limit, offset);
356 break;
357 case ColumnPrefixFilter:
358 filter = new ColumnPrefixFilter(Base64.decode(value));
359 break;
360 case ColumnRangeFilter:
361 filter = new ColumnRangeFilter(Base64.decode(minColumn),
362 minColumnInclusive, Base64.decode(maxColumn),
363 maxColumnInclusive);
364 break;
365 case DependentColumnFilter:
366 filter = new DependentColumnFilter(Base64.decode(family),
367 qualifier != null ? Base64.decode(qualifier) : null,
368 dropDependentColumn, CompareOp.valueOf(op), comparator.build());
369 break;
370 case FamilyFilter:
371 filter = new FamilyFilter(CompareOp.valueOf(op), comparator.build());
372 break;
373 case FilterList: {
374 List<Filter> list = new ArrayList<Filter>();
375 for (FilterModel model: filters) {
376 list.add(model.build());
377 }
378 filter = new FilterList(FilterList.Operator.valueOf(op), list);
379 } break;
380 case FirstKeyOnlyFilter:
381 filter = new FirstKeyOnlyFilter();
382 break;
383 case InclusiveStopFilter:
384 filter = new InclusiveStopFilter(Base64.decode(value));
385 break;
386 case KeyOnlyFilter:
387 filter = new KeyOnlyFilter();
388 break;
389 case MultipleColumnPrefixFilter: {
390 byte[][] values = new byte[prefixes.size()][];
391 for (int i = 0; i < prefixes.size(); i++) {
392 values[i] = Base64.decode(prefixes.get(i));
393 }
394 filter = new MultipleColumnPrefixFilter(values);
395 } break;
396 case PageFilter:
397 filter = new PageFilter(Long.valueOf(value));
398 break;
399 case PrefixFilter:
400 filter = new PrefixFilter(Base64.decode(value));
401 break;
402 case QualifierFilter:
403 filter = new QualifierFilter(CompareOp.valueOf(op), comparator.build());
404 break;
405 case RandomRowFilter:
406 filter = new RandomRowFilter(chance);
407 break;
408 case RowFilter:
409 filter = new RowFilter(CompareOp.valueOf(op), comparator.build());
410 break;
411 case SingleColumnValueFilter:
412 filter = new SingleColumnValueFilter(Base64.decode(family),
413 qualifier != null ? Base64.decode(qualifier) : null,
414 CompareOp.valueOf(op), comparator.build());
415 if (ifMissing != null) {
416 ((SingleColumnValueFilter)filter).setFilterIfMissing(ifMissing);
417 }
418 if (latestVersion != null) {
419 ((SingleColumnValueFilter)filter).setLatestVersionOnly(latestVersion);
420 }
421 break;
422 case SingleColumnValueExcludeFilter:
423 filter = new SingleColumnValueExcludeFilter(Base64.decode(family),
424 qualifier != null ? Base64.decode(qualifier) : null,
425 CompareOp.valueOf(op), comparator.build());
426 if (ifMissing != null) {
427 ((SingleColumnValueExcludeFilter)filter).setFilterIfMissing(ifMissing);
428 }
429 if (latestVersion != null) {
430 ((SingleColumnValueExcludeFilter)filter).setLatestVersionOnly(latestVersion);
431 }
432 break;
433 case SkipFilter:
434 filter = new SkipFilter(filters.get(0).build());
435 break;
436 case TimestampsFilter:
437 filter = new TimestampsFilter(timestamps);
438 break;
439 case ValueFilter:
440 filter = new ValueFilter(CompareOp.valueOf(op), comparator.build());
441 break;
442 case WhileMatchFilter:
443 filter = new WhileMatchFilter(filters.get(0).build());
444 break;
445 default:
446 throw new RuntimeException("unhandled filter type: " + type);
447 }
448 return filter;
449 }
450
451 }
452
453
454
455
456
457
458 public static Filter buildFilter(String s) throws Exception {
459 JSONJAXBContext context =
460 new JSONJAXBContext(JSONConfiguration.natural().build(),
461 FilterModel.class);
462 JSONUnmarshaller unmarshaller = context.createJSONUnmarshaller();
463 FilterModel model = unmarshaller.unmarshalFromJSON(new StringReader(s),
464 FilterModel.class);
465 return model.build();
466 }
467
468
469
470
471
472
473 public static String stringifyFilter(final Filter filter) throws Exception {
474 JSONJAXBContext context =
475 new JSONJAXBContext(JSONConfiguration.natural().build(),
476 FilterModel.class);
477 JSONMarshaller marshaller = context.createJSONMarshaller();
478 StringWriter writer = new StringWriter();
479 marshaller.marshallToJSON(new FilterModel(filter), writer);
480 return writer.toString();
481 }
482
483 private static final byte[] COLUMN_DIVIDER = Bytes.toBytes(":");
484
485
486
487
488
489 public static ScannerModel fromScan(Scan scan) throws Exception {
490 ScannerModel model = new ScannerModel();
491 model.setStartRow(scan.getStartRow());
492 model.setEndRow(scan.getStopRow());
493 Map<byte [], NavigableSet<byte []>> families = scan.getFamilyMap();
494 if (families != null) {
495 for (Map.Entry<byte [], NavigableSet<byte []>> entry : families.entrySet()) {
496 if (entry.getValue() != null) {
497 for (byte[] qualifier: entry.getValue()) {
498 model.addColumn(Bytes.add(entry.getKey(), COLUMN_DIVIDER, qualifier));
499 }
500 } else {
501 model.addColumn(entry.getKey());
502 }
503 }
504 }
505 model.setStartTime(scan.getTimeRange().getMin());
506 model.setEndTime(scan.getTimeRange().getMax());
507 int caching = scan.getCaching();
508 if (caching > 0) {
509 model.setCaching(caching);
510 }
511 int batch = scan.getBatch();
512 if (batch > 0) {
513 model.setBatch(batch);
514 }
515 int maxVersions = scan.getMaxVersions();
516 if (maxVersions > 0) {
517 model.setMaxVersions(maxVersions);
518 }
519 Filter filter = scan.getFilter();
520 if (filter != null) {
521 model.setFilter(stringifyFilter(filter));
522 }
523
524 Authorizations authorizations = scan.getAuthorizations();
525 if (authorizations != null) {
526 List<String> labels = authorizations.getLabels();
527 for (String label : labels) {
528 model.addLabel(label);
529 }
530 }
531 return model;
532 }
533
534
535
536
537 public ScannerModel() {}
538
539
540
541
542
543
544
545
546
547
548
549
550
551 public ScannerModel(byte[] startRow, byte[] endRow, List<byte[]> columns,
552 int batch, int caching, long endTime, int maxVersions, String filter) {
553 super();
554 this.startRow = startRow;
555 this.endRow = endRow;
556 this.columns = columns;
557 this.batch = batch;
558 this.caching = caching;
559 this.endTime = endTime;
560 this.maxVersions = maxVersions;
561 this.filter = filter;
562 }
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577 public ScannerModel(byte[] startRow, byte[] endRow, List<byte[]> columns,
578 int batch, int caching, long startTime, long endTime, String filter) {
579 super();
580 this.startRow = startRow;
581 this.endRow = endRow;
582 this.columns = columns;
583 this.batch = batch;
584 this.caching = caching;
585 this.startTime = startTime;
586 this.endTime = endTime;
587 this.filter = filter;
588 }
589
590
591
592
593
594 public void addColumn(byte[] column) {
595 columns.add(column);
596 }
597
598
599
600
601 public void addLabel(String label) {
602 labels.add(label);
603 }
604
605
606
607 public boolean hasStartRow() {
608 return !Bytes.equals(startRow, HConstants.EMPTY_START_ROW);
609 }
610
611
612
613
614 @XmlAttribute
615 public byte[] getStartRow() {
616 return startRow;
617 }
618
619
620
621
622 public boolean hasEndRow() {
623 return !Bytes.equals(endRow, HConstants.EMPTY_END_ROW);
624 }
625
626
627
628
629 @XmlAttribute
630 public byte[] getEndRow() {
631 return endRow;
632 }
633
634
635
636
637 @XmlElement(name="column")
638 public List<byte[]> getColumns() {
639 return columns;
640 }
641
642 @XmlElement(name="label")
643 public List<String> getLabels() {
644 return labels;
645 }
646
647
648
649
650 @XmlAttribute
651 public int getBatch() {
652 return batch;
653 }
654
655
656
657
658 @XmlAttribute
659 public int getCaching() {
660 return caching;
661 }
662
663
664
665
666 @XmlAttribute
667 public long getStartTime() {
668 return startTime;
669 }
670
671
672
673
674 @XmlAttribute
675 public long getEndTime() {
676 return endTime;
677 }
678
679
680
681
682 @XmlAttribute
683 public int getMaxVersions() {
684 return maxVersions;
685 }
686
687
688
689
690 @XmlElement
691 public String getFilter() {
692 return filter;
693 }
694
695
696
697
698 public void setStartRow(byte[] startRow) {
699 this.startRow = startRow;
700 }
701
702
703
704
705 public void setEndRow(byte[] endRow) {
706 this.endRow = endRow;
707 }
708
709
710
711
712 public void setColumns(List<byte[]> columns) {
713 this.columns = columns;
714 }
715
716
717
718
719 public void setBatch(int batch) {
720 this.batch = batch;
721 }
722
723
724
725
726 public void setCaching(int caching) {
727 this.caching = caching;
728 }
729
730
731
732
733 public void setMaxVersions(int maxVersions) {
734 this.maxVersions = maxVersions;
735 }
736
737
738
739
740 public void setStartTime(long startTime) {
741 this.startTime = startTime;
742 }
743
744
745
746
747 public void setEndTime(long endTime) {
748 this.endTime = endTime;
749 }
750
751
752
753
754 public void setFilter(String filter) {
755 this.filter = filter;
756 }
757
758 @Override
759 public byte[] createProtobufOutput() {
760 Scanner.Builder builder = Scanner.newBuilder();
761 if (!Bytes.equals(startRow, HConstants.EMPTY_START_ROW)) {
762 builder.setStartRow(HBaseZeroCopyByteString.wrap(startRow));
763 }
764 if (!Bytes.equals(endRow, HConstants.EMPTY_START_ROW)) {
765 builder.setEndRow(HBaseZeroCopyByteString.wrap(endRow));
766 }
767 for (byte[] column: columns) {
768 builder.addColumns(HBaseZeroCopyByteString.wrap(column));
769 }
770 if (startTime != 0) {
771 builder.setStartTime(startTime);
772 }
773 if (endTime != 0) {
774 builder.setEndTime(endTime);
775 }
776 builder.setBatch(getBatch());
777 if (caching > 0) {
778 builder.setCaching(caching);
779 }
780 builder.setMaxVersions(maxVersions);
781 if (filter != null) {
782 builder.setFilter(filter);
783 }
784 if (labels != null && labels.size() > 0) {
785 for (String label : labels)
786 builder.addLabels(label);
787 }
788 return builder.build().toByteArray();
789 }
790
791 @Override
792 public ProtobufMessageHandler getObjectFromMessage(byte[] message)
793 throws IOException {
794 Scanner.Builder builder = Scanner.newBuilder();
795 builder.mergeFrom(message);
796 if (builder.hasStartRow()) {
797 startRow = builder.getStartRow().toByteArray();
798 }
799 if (builder.hasEndRow()) {
800 endRow = builder.getEndRow().toByteArray();
801 }
802 for (ByteString column: builder.getColumnsList()) {
803 addColumn(column.toByteArray());
804 }
805 if (builder.hasBatch()) {
806 batch = builder.getBatch();
807 }
808 if (builder.hasCaching()) {
809 caching = builder.getCaching();
810 }
811 if (builder.hasStartTime()) {
812 startTime = builder.getStartTime();
813 }
814 if (builder.hasEndTime()) {
815 endTime = builder.getEndTime();
816 }
817 if (builder.hasMaxVersions()) {
818 maxVersions = builder.getMaxVersions();
819 }
820 if (builder.hasFilter()) {
821 filter = builder.getFilter();
822 }
823 if(builder.getLabelsList() != null) {
824 List<String> labels = builder.getLabelsList();
825 for(String label : labels) {
826 addLabel(label);
827 }
828 }
829 return this;
830 }
831
832 }