1 /**
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.apache.hadoop.hbase.client;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotNull;
23 import org.apache.hadoop.hbase.Cell;
24 import org.apache.hadoop.hbase.CellUtil;
25 import org.apache.hadoop.hbase.HConstants;
26 import org.apache.hadoop.hbase.KeyValue;
27 import org.apache.hadoop.hbase.testclassification.SmallTests;
28 import org.junit.Assert;
29 import org.junit.Test;
30 
31 import java.io.IOException;
32 import java.nio.ByteBuffer;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 
38 import org.apache.hadoop.hbase.filter.BinaryComparator;
39 import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
40 import org.apache.hadoop.hbase.filter.ColumnPaginationFilter;
41 import org.apache.hadoop.hbase.filter.ColumnPrefixFilter;
42 import org.apache.hadoop.hbase.filter.ColumnRangeFilter;
43 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
44 import org.apache.hadoop.hbase.filter.DependentColumnFilter;
45 import org.apache.hadoop.hbase.filter.FamilyFilter;
46 import org.apache.hadoop.hbase.filter.Filter;
47 import org.apache.hadoop.hbase.filter.FilterList;
48 import org.apache.hadoop.hbase.filter.FilterList.Operator;
49 import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
50 import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
51 import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
52 import org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter;
53 import org.apache.hadoop.hbase.filter.PageFilter;
54 import org.apache.hadoop.hbase.filter.PrefixFilter;
55 import org.apache.hadoop.hbase.filter.QualifierFilter;
56 import org.apache.hadoop.hbase.filter.RowFilter;
57 import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
58 import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter;
59 import org.apache.hadoop.hbase.filter.SkipFilter;
60 import org.apache.hadoop.hbase.filter.TimestampsFilter;
61 import org.apache.hadoop.hbase.filter.ValueFilter;
62 import org.apache.hadoop.hbase.filter.WhileMatchFilter;
63 import org.apache.hadoop.hbase.util.BuilderStyleTest;
64 import org.apache.hadoop.hbase.util.Bytes;
65 import org.codehaus.jackson.map.ObjectMapper;
66 import org.junit.experimental.categories.Category;
67 
68 /**
69  * Run tests that use the functionality of the Operation superclass for
70  * Puts, Gets, Deletes, Scans, and MultiPuts.
71  */
72 @Category(SmallTests.class)
73 public class TestOperation {
74   private static byte [] ROW = Bytes.toBytes("testRow");
75   private static byte [] FAMILY = Bytes.toBytes("testFamily");
76   private static byte [] QUALIFIER = Bytes.toBytes("testQualifier");
77   private static byte [] VALUE = Bytes.toBytes("testValue");
78 
79   private static ObjectMapper mapper = new ObjectMapper();
80 
81   private static List<Long> TS_LIST = Arrays.asList(2L, 3L, 5L);
82   private static TimestampsFilter TS_FILTER = new TimestampsFilter(TS_LIST);
83   private static String STR_TS_FILTER =
84       TS_FILTER.getClass().getSimpleName() + " (3/3): [2, 3, 5]";
85 
86   private static List<Long> L_TS_LIST =
87       Arrays.asList(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L);
88   private static TimestampsFilter L_TS_FILTER =
89       new TimestampsFilter(L_TS_LIST);
90   private static String STR_L_TS_FILTER =
91       L_TS_FILTER.getClass().getSimpleName() + " (5/11): [0, 1, 2, 3, 4]";
92 
93   private static String COL_NAME_1 = "col1";
94   private static ColumnPrefixFilter COL_PRE_FILTER =
95       new ColumnPrefixFilter(COL_NAME_1.getBytes());
96   private static String STR_COL_PRE_FILTER =
97       COL_PRE_FILTER.getClass().getSimpleName() + " " + COL_NAME_1;
98 
99   private static String COL_NAME_2 = "col2";
100   private static ColumnRangeFilter CR_FILTER = new ColumnRangeFilter(
101       COL_NAME_1.getBytes(), true, COL_NAME_2.getBytes(), false);
102   private static String STR_CR_FILTER = CR_FILTER.getClass().getSimpleName()
103       + " [" + COL_NAME_1 + ", " + COL_NAME_2 + ")";
104 
105   private static int COL_COUNT = 9;
106   private static ColumnCountGetFilter CCG_FILTER =
107       new ColumnCountGetFilter(COL_COUNT);
108   private static String STR_CCG_FILTER =
109       CCG_FILTER.getClass().getSimpleName() + " " + COL_COUNT;
110 
111   private static int LIMIT = 3;
112   private static int OFFSET = 4;
113   private static ColumnPaginationFilter CP_FILTER =
114       new ColumnPaginationFilter(LIMIT, OFFSET);
115   private static String STR_CP_FILTER = CP_FILTER.getClass().getSimpleName()
116       + " (" + LIMIT + ", " + OFFSET + ")";
117 
118   private static String STOP_ROW_KEY = "stop";
119   private static InclusiveStopFilter IS_FILTER =
120       new InclusiveStopFilter(STOP_ROW_KEY.getBytes());
121   private static String STR_IS_FILTER =
122       IS_FILTER.getClass().getSimpleName() + " " + STOP_ROW_KEY;
123 
124   private static String PREFIX = "prefix";
125   private static PrefixFilter PREFIX_FILTER =
126       new PrefixFilter(PREFIX.getBytes());
127   private static String STR_PREFIX_FILTER = "PrefixFilter " + PREFIX;
128 
129   private static byte[][] PREFIXES = {
130       "0".getBytes(), "1".getBytes(), "2".getBytes()};
131   private static MultipleColumnPrefixFilter MCP_FILTER =
132       new MultipleColumnPrefixFilter(PREFIXES);
133   private static String STR_MCP_FILTER =
134       MCP_FILTER.getClass().getSimpleName() + " (3/3): [0, 1, 2]";
135 
136   private static byte[][] L_PREFIXES = {
137     "0".getBytes(), "1".getBytes(), "2".getBytes(), "3".getBytes(),
138     "4".getBytes(), "5".getBytes(), "6".getBytes(), "7".getBytes()};
139   private static MultipleColumnPrefixFilter L_MCP_FILTER =
140       new MultipleColumnPrefixFilter(L_PREFIXES);
141   private static String STR_L_MCP_FILTER =
142       L_MCP_FILTER.getClass().getSimpleName() + " (5/8): [0, 1, 2, 3, 4]";
143 
144   private static int PAGE_SIZE = 9;
145   private static PageFilter PAGE_FILTER = new PageFilter(PAGE_SIZE);
146   private static String STR_PAGE_FILTER =
147       PAGE_FILTER.getClass().getSimpleName() + " " + PAGE_SIZE;
148 
149   private static SkipFilter SKIP_FILTER = new SkipFilter(L_TS_FILTER);
150   private static String STR_SKIP_FILTER =
151       SKIP_FILTER.getClass().getSimpleName() + " " + STR_L_TS_FILTER;
152 
153   private static WhileMatchFilter WHILE_FILTER =
154       new WhileMatchFilter(L_TS_FILTER);
155   private static String STR_WHILE_FILTER =
156       WHILE_FILTER.getClass().getSimpleName() + " " + STR_L_TS_FILTER;
157 
158   private static KeyOnlyFilter KEY_ONLY_FILTER = new KeyOnlyFilter();
159   private static String STR_KEY_ONLY_FILTER =
160       KEY_ONLY_FILTER.getClass().getSimpleName();
161 
162   private static FirstKeyOnlyFilter FIRST_KEY_ONLY_FILTER =
163       new FirstKeyOnlyFilter();
164   private static String STR_FIRST_KEY_ONLY_FILTER =
165       FIRST_KEY_ONLY_FILTER.getClass().getSimpleName();
166 
167   private static CompareOp CMP_OP = CompareOp.EQUAL;
168   private static byte[] CMP_VALUE = "value".getBytes();
169   private static BinaryComparator BC = new BinaryComparator(CMP_VALUE);
170   private static DependentColumnFilter DC_FILTER =
171       new DependentColumnFilter(FAMILY, QUALIFIER, true, CMP_OP, BC);
172   private static String STR_DC_FILTER = String.format(
173       "%s (%s, %s, %s, %s, %s)", DC_FILTER.getClass().getSimpleName(),
174       Bytes.toStringBinary(FAMILY), Bytes.toStringBinary(QUALIFIER), true,
175       CMP_OP.name(), Bytes.toStringBinary(BC.getValue()));
176 
177   private static FamilyFilter FAMILY_FILTER = new FamilyFilter(CMP_OP, BC);
178   private static String STR_FAMILY_FILTER =
179       FAMILY_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
180 
181   private static QualifierFilter QUALIFIER_FILTER =
182       new QualifierFilter(CMP_OP, BC);
183   private static String STR_QUALIFIER_FILTER =
184       QUALIFIER_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
185 
186   private static RowFilter ROW_FILTER = new RowFilter(CMP_OP, BC);
187   private static String STR_ROW_FILTER =
188       ROW_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
189 
190   private static ValueFilter VALUE_FILTER = new ValueFilter(CMP_OP, BC);
191   private static String STR_VALUE_FILTER =
192       VALUE_FILTER.getClass().getSimpleName() + " (EQUAL, value)";
193 
194   private static SingleColumnValueFilter SCV_FILTER =
195       new SingleColumnValueFilter(FAMILY, QUALIFIER, CMP_OP, CMP_VALUE);
196   private static String STR_SCV_FILTER = String.format("%s (%s, %s, %s, %s)",
197       SCV_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY),
198       Bytes.toStringBinary(QUALIFIER), CMP_OP.name(),
199       Bytes.toStringBinary(CMP_VALUE));
200 
201   private static SingleColumnValueExcludeFilter SCVE_FILTER =
202       new SingleColumnValueExcludeFilter(FAMILY, QUALIFIER, CMP_OP, CMP_VALUE);
203   private static String STR_SCVE_FILTER = String.format("%s (%s, %s, %s, %s)",
204       SCVE_FILTER.getClass().getSimpleName(), Bytes.toStringBinary(FAMILY),
205       Bytes.toStringBinary(QUALIFIER), CMP_OP.name(),
206       Bytes.toStringBinary(CMP_VALUE));
207 
208   private static FilterList AND_FILTER_LIST = new FilterList(
209       Operator.MUST_PASS_ALL, Arrays.asList((Filter) TS_FILTER, L_TS_FILTER,
210           CR_FILTER));
211   private static String STR_AND_FILTER_LIST = String.format(
212       "%s AND (3/3): [%s, %s, %s]", AND_FILTER_LIST.getClass().getSimpleName(),
213       STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER);
214 
215   private static FilterList OR_FILTER_LIST = new FilterList(
216       Operator.MUST_PASS_ONE, Arrays.asList((Filter) TS_FILTER, L_TS_FILTER,
217           CR_FILTER));
218   private static String STR_OR_FILTER_LIST = String.format(
219       "%s OR (3/3): [%s, %s, %s]", AND_FILTER_LIST.getClass().getSimpleName(),
220       STR_TS_FILTER, STR_L_TS_FILTER, STR_CR_FILTER);
221 
222   private static FilterList L_FILTER_LIST = new FilterList(
223       Arrays.asList((Filter) TS_FILTER, L_TS_FILTER, CR_FILTER, COL_PRE_FILTER,
224           CCG_FILTER, CP_FILTER, PREFIX_FILTER, PAGE_FILTER));
225   private static String STR_L_FILTER_LIST = String.format(
226       "%s AND (5/8): [%s, %s, %s, %s, %s, %s]",
227       L_FILTER_LIST.getClass().getSimpleName(), STR_TS_FILTER, STR_L_TS_FILTER,
228       STR_CR_FILTER, STR_COL_PRE_FILTER, STR_CCG_FILTER, STR_CP_FILTER);
229 
230   private static Filter[] FILTERS = {
231     TS_FILTER,             // TimestampsFilter
232     L_TS_FILTER,           // TimestampsFilter
233     COL_PRE_FILTER,        // ColumnPrefixFilter
234     CP_FILTER,             // ColumnPaginationFilter
235     CR_FILTER,             // ColumnRangeFilter
236     CCG_FILTER,            // ColumnCountGetFilter
237     IS_FILTER,             // InclusiveStopFilter
238     PREFIX_FILTER,         // PrefixFilter
239     PAGE_FILTER,           // PageFilter
240     SKIP_FILTER,           // SkipFilter
241     WHILE_FILTER,          // WhileMatchFilter
242     KEY_ONLY_FILTER,       // KeyOnlyFilter
243     FIRST_KEY_ONLY_FILTER, // FirstKeyOnlyFilter
244     MCP_FILTER,            // MultipleColumnPrefixFilter
245     L_MCP_FILTER,          // MultipleColumnPrefixFilter
246     DC_FILTER,             // DependentColumnFilter
247     FAMILY_FILTER,         // FamilyFilter
248     QUALIFIER_FILTER,      // QualifierFilter
249     ROW_FILTER,            // RowFilter
250     VALUE_FILTER,          // ValueFilter
251     SCV_FILTER,            // SingleColumnValueFilter
252     SCVE_FILTER,           // SingleColumnValueExcludeFilter
253     AND_FILTER_LIST,       // FilterList
254     OR_FILTER_LIST,        // FilterList
255     L_FILTER_LIST,         // FilterList
256   };
257 
258   private static String[] FILTERS_INFO = {
259     STR_TS_FILTER,             // TimestampsFilter
260     STR_L_TS_FILTER,           // TimestampsFilter
261     STR_COL_PRE_FILTER,        // ColumnPrefixFilter
262     STR_CP_FILTER,             // ColumnPaginationFilter
263     STR_CR_FILTER,             // ColumnRangeFilter
264     STR_CCG_FILTER,            // ColumnCountGetFilter
265     STR_IS_FILTER,             // InclusiveStopFilter
266     STR_PREFIX_FILTER,         // PrefixFilter
267     STR_PAGE_FILTER,           // PageFilter
268     STR_SKIP_FILTER,           // SkipFilter
269     STR_WHILE_FILTER,          // WhileMatchFilter
270     STR_KEY_ONLY_FILTER,       // KeyOnlyFilter
271     STR_FIRST_KEY_ONLY_FILTER, // FirstKeyOnlyFilter
272     STR_MCP_FILTER,            // MultipleColumnPrefixFilter
273     STR_L_MCP_FILTER,          // MultipleColumnPrefixFilter
274     STR_DC_FILTER,             // DependentColumnFilter
275     STR_FAMILY_FILTER,         // FamilyFilter
276     STR_QUALIFIER_FILTER,      // QualifierFilter
277     STR_ROW_FILTER,            // RowFilter
278     STR_VALUE_FILTER,          // ValueFilter
279     STR_SCV_FILTER,            // SingleColumnValueFilter
280     STR_SCVE_FILTER,           // SingleColumnValueExcludeFilter
281     STR_AND_FILTER_LIST,       // FilterList
282     STR_OR_FILTER_LIST,        // FilterList
283     STR_L_FILTER_LIST,         // FilterList
284   };
285 
286   static {
287     assertEquals("The sizes of static arrays do not match: "
288         + "[FILTERS: %d <=> FILTERS_INFO: %d]",
289         FILTERS.length, FILTERS_INFO.length);
290   }
291 
292   /**
293    * Test the client Operations' JSON encoding to ensure that produced JSON is
294    * parseable and that the details are present and not corrupted.
295    * @throws IOException
296    */
297   @Test
testOperationJSON()298   public void testOperationJSON()
299       throws IOException {
300     // produce a Scan Operation
301     Scan scan = new Scan(ROW);
302     scan.addColumn(FAMILY, QUALIFIER);
303     // get its JSON representation, and parse it
304     String json = scan.toJSON();
305     Map<String, Object> parsedJSON = mapper.readValue(json, HashMap.class);
306     // check for the row
307     assertEquals("startRow incorrect in Scan.toJSON()",
308         Bytes.toStringBinary(ROW), parsedJSON.get("startRow"));
309     // check for the family and the qualifier.
310     List familyInfo = (List) ((Map) parsedJSON.get("families")).get(
311         Bytes.toStringBinary(FAMILY));
312     assertNotNull("Family absent in Scan.toJSON()", familyInfo);
313     assertEquals("Qualifier absent in Scan.toJSON()", 1, familyInfo.size());
314     assertEquals("Qualifier incorrect in Scan.toJSON()",
315         Bytes.toStringBinary(QUALIFIER),
316         familyInfo.get(0));
317 
318     // produce a Get Operation
319     Get get = new Get(ROW);
320     get.addColumn(FAMILY, QUALIFIER);
321     // get its JSON representation, and parse it
322     json = get.toJSON();
323     parsedJSON = mapper.readValue(json, HashMap.class);
324     // check for the row
325     assertEquals("row incorrect in Get.toJSON()",
326         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
327     // check for the family and the qualifier.
328     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
329         Bytes.toStringBinary(FAMILY));
330     assertNotNull("Family absent in Get.toJSON()", familyInfo);
331     assertEquals("Qualifier absent in Get.toJSON()", 1, familyInfo.size());
332     assertEquals("Qualifier incorrect in Get.toJSON()",
333         Bytes.toStringBinary(QUALIFIER),
334         familyInfo.get(0));
335 
336     // produce a Put operation
337     Put put = new Put(ROW);
338     put.add(FAMILY, QUALIFIER, VALUE);
339     // get its JSON representation, and parse it
340     json = put.toJSON();
341     parsedJSON = mapper.readValue(json, HashMap.class);
342     // check for the row
343     assertEquals("row absent in Put.toJSON()",
344         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
345     // check for the family and the qualifier.
346     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
347         Bytes.toStringBinary(FAMILY));
348     assertNotNull("Family absent in Put.toJSON()", familyInfo);
349     assertEquals("KeyValue absent in Put.toJSON()", 1, familyInfo.size());
350     Map kvMap = (Map) familyInfo.get(0);
351     assertEquals("Qualifier incorrect in Put.toJSON()",
352         Bytes.toStringBinary(QUALIFIER),
353         kvMap.get("qualifier"));
354     assertEquals("Value length incorrect in Put.toJSON()",
355         VALUE.length, kvMap.get("vlen"));
356 
357     // produce a Delete operation
358     Delete delete = new Delete(ROW);
359     delete.deleteColumn(FAMILY, QUALIFIER);
360     // get its JSON representation, and parse it
361     json = delete.toJSON();
362     parsedJSON = mapper.readValue(json, HashMap.class);
363     // check for the row
364     assertEquals("row absent in Delete.toJSON()",
365         Bytes.toStringBinary(ROW), parsedJSON.get("row"));
366     // check for the family and the qualifier.
367     familyInfo = (List) ((Map) parsedJSON.get("families")).get(
368         Bytes.toStringBinary(FAMILY));
369     assertNotNull("Family absent in Delete.toJSON()", familyInfo);
370     assertEquals("KeyValue absent in Delete.toJSON()", 1, familyInfo.size());
371     kvMap = (Map) familyInfo.get(0);
372     assertEquals("Qualifier incorrect in Delete.toJSON()",
373         Bytes.toStringBinary(QUALIFIER), kvMap.get("qualifier"));
374   }
375 
376   @Test
testPutCreationWithByteBuffer()377   public void testPutCreationWithByteBuffer() {
378     Put p = new Put(ROW);
379     List<Cell> c = p.get(FAMILY, QUALIFIER);
380     Assert.assertEquals(0, c.size());
381     Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
382 
383     p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 1984L, ByteBuffer.wrap(VALUE));
384     c = p.get(FAMILY, QUALIFIER);
385     Assert.assertEquals(1, c.size());
386     Assert.assertEquals(1984L, c.get(0).getTimestamp());
387     Assert.assertArrayEquals(VALUE, CellUtil.cloneValue(c.get(0)));
388     Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
389     Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
390 
391     p = new Put(ROW);
392     p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 2013L, null);
393     c = p.get(FAMILY, QUALIFIER);
394     Assert.assertEquals(1, c.size());
395     Assert.assertEquals(2013L, c.get(0).getTimestamp());
396     Assert.assertArrayEquals(new byte[]{}, CellUtil.cloneValue(c.get(0)));
397     Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
398     Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
399 
400     p = new Put(ByteBuffer.wrap(ROW));
401     p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null);
402     c = p.get(FAMILY, QUALIFIER);
403     Assert.assertEquals(1, c.size());
404     Assert.assertEquals(2001L, c.get(0).getTimestamp());
405     Assert.assertArrayEquals(new byte[]{}, CellUtil.cloneValue(c.get(0)));
406     Assert.assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0)));
407     Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
408     Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
409 
410     p = new Put(ByteBuffer.wrap(ROW), 1970L);
411     p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null);
412     c = p.get(FAMILY, QUALIFIER);
413     Assert.assertEquals(1, c.size());
414     Assert.assertEquals(2001L, c.get(0).getTimestamp());
415     Assert.assertArrayEquals(new byte[]{}, CellUtil.cloneValue(c.get(0)));
416     Assert.assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0)));
417     Assert.assertEquals(1970L, p.getTimeStamp());
418     Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
419   }
420 
421   @Test
422   @SuppressWarnings("rawtypes")
testOperationSubClassMethodsAreBuilderStyle()423   public void testOperationSubClassMethodsAreBuilderStyle() {
424     /* All Operation subclasses should have a builder style setup where setXXX/addXXX methods
425      * can be chainable together:
426      * . For example:
427      * Scan scan = new Scan()
428      *     .setFoo(foo)
429      *     .setBar(bar)
430      *     .setBuz(buz)
431      *
432      * This test ensures that all methods starting with "set" returns the declaring object
433      */
434 
435     // TODO: We should ensure all subclasses of Operation is checked.
436     Class[] classes = new Class[] {
437         Operation.class,
438         OperationWithAttributes.class,
439         Mutation.class,
440         Query.class,
441         Delete.class,
442         Increment.class,
443         Append.class,
444         Put.class,
445         Get.class,
446         Scan.class};
447 
448     BuilderStyleTest.assertClassesAreBuilderStyle(classes);
449   }
450 
451 }
452 
453