001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.rest;
019
020import static org.junit.Assert.assertEquals;
021
022import java.io.ByteArrayInputStream;
023import java.io.IOException;
024import java.io.StringWriter;
025
026import java.util.HashMap;
027import java.util.Map;
028import javax.ws.rs.core.MediaType;
029import javax.xml.bind.JAXBContext;
030import javax.xml.bind.JAXBException;
031import javax.xml.bind.Marshaller;
032import javax.xml.bind.Unmarshaller;
033
034import com.fasterxml.jackson.databind.ObjectMapper;
035import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
036import org.apache.hadoop.conf.Configuration;
037import org.apache.hadoop.hbase.HBaseTestingUtility;
038import org.apache.hadoop.hbase.HColumnDescriptor;
039import org.apache.hadoop.hbase.HTableDescriptor;
040import org.apache.hadoop.hbase.TableName;
041import org.apache.hadoop.hbase.client.Admin;
042import org.apache.hadoop.hbase.rest.client.Client;
043import org.apache.hadoop.hbase.rest.client.Cluster;
044import org.apache.hadoop.hbase.rest.client.Response;
045import org.apache.hadoop.hbase.rest.model.CellModel;
046import org.apache.hadoop.hbase.rest.model.CellSetModel;
047import org.apache.hadoop.hbase.rest.model.RowModel;
048import org.apache.hadoop.hbase.util.Bytes;
049import org.junit.After;
050import org.junit.AfterClass;
051import org.junit.Before;
052import org.junit.BeforeClass;
053
054public class RowResourceBase {
055
056  protected static final String TABLE = "TestRowResource";
057
058  protected static final TableName TABLE_NAME = TableName.valueOf(TABLE);
059
060  protected static final String CFA = "a";
061  protected static final String CFB = "b";
062  protected static final String COLUMN_1 = CFA + ":1";
063  protected static final String COLUMN_2 = CFB + ":2";
064  protected static final String COLUMN_3 = CFA + ":";
065  protected static final String ROW_1 = "testrow1";
066  protected static final String VALUE_1 = "testvalue1";
067  protected static final String ROW_2 = "testrow2";
068  protected static final String VALUE_2 = "testvalue2";
069  protected static final String ROW_3 = "testrow3";
070  protected static final String VALUE_3 = "testvalue3";
071  protected static final String ROW_4 = "testrow4";
072  protected static final String VALUE_4 = "testvalue4";
073  protected static final String VALUE_5 = "5";
074  protected static final String VALUE_6 = "6";
075
076  protected static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
077  protected static final HBaseRESTTestingUtility REST_TEST_UTIL =
078    new HBaseRESTTestingUtility();
079  protected static Client client;
080  protected static JAXBContext context;
081  protected static Marshaller xmlMarshaller;
082  protected static Unmarshaller xmlUnmarshaller;
083  protected static Configuration conf;
084  protected static ObjectMapper jsonMapper;
085
086
087  @BeforeClass
088  public static void setUpBeforeClass() throws Exception {
089    conf = TEST_UTIL.getConfiguration();
090    TEST_UTIL.startMiniCluster(3);
091    REST_TEST_UTIL.startServletContainer(conf);
092    context = JAXBContext.newInstance(
093        CellModel.class,
094        CellSetModel.class,
095        RowModel.class);
096    xmlMarshaller = context.createMarshaller();
097    xmlUnmarshaller = context.createUnmarshaller();
098    jsonMapper = new JacksonJaxbJsonProvider()
099    .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
100    client = new Client(new Cluster().add("localhost",
101      REST_TEST_UTIL.getServletPort()));
102  }
103
104  @AfterClass
105  public static void tearDownAfterClass() throws Exception {
106    REST_TEST_UTIL.shutdownServletContainer();
107    TEST_UTIL.shutdownMiniCluster();
108  }
109
110  @Before
111  public void beforeMethod() throws Exception {
112    Admin admin = TEST_UTIL.getAdmin();
113    if (admin.tableExists(TABLE_NAME)) {
114      TEST_UTIL.deleteTable(TABLE_NAME);
115    }
116    HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(TABLE));
117    htd.addFamily(new HColumnDescriptor(CFA));
118    htd.addFamily(new HColumnDescriptor(CFB));
119    admin.createTable(htd);
120  }
121
122  @After
123  public void afterMethod() throws Exception {
124    Admin admin = TEST_UTIL.getAdmin();
125    if (admin.tableExists(TABLE_NAME)) {
126      TEST_UTIL.deleteTable(TABLE_NAME);
127    }
128  }
129
130  static Response putValuePB(String table, String row, String column,
131      String value) throws IOException {
132    StringBuilder path = new StringBuilder();
133    path.append('/');
134    path.append(table);
135    path.append('/');
136    path.append(row);
137    path.append('/');
138    path.append(column);
139    return putValuePB(path.toString(), table, row, column, value);
140  }
141
142  static Response putValuePB(String url, String table, String row,
143      String column, String value) throws IOException {
144    RowModel rowModel = new RowModel(row);
145    rowModel.addCell(new CellModel(Bytes.toBytes(column),
146      Bytes.toBytes(value)));
147    CellSetModel cellSetModel = new CellSetModel();
148    cellSetModel.addRow(rowModel);
149    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
150      cellSetModel.createProtobufOutput());
151    Thread.yield();
152    return response;
153  }
154
155  protected static void checkValueXML(String url, String table, String row,
156      String column, String value) throws IOException, JAXBException {
157    Response response = getValueXML(url);
158    assertEquals(200, response.getCode());
159    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
160    CellSetModel cellSet = (CellSetModel)
161      xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
162    RowModel rowModel = cellSet.getRows().get(0);
163    CellModel cell = rowModel.getCells().get(0);
164    assertEquals(Bytes.toString(cell.getColumn()), column);
165    assertEquals(Bytes.toString(cell.getValue()), value);
166  }
167
168  protected static void checkValueXML(String table, String row, String column,
169      String value) throws IOException, JAXBException {
170    Response response = getValueXML(table, row, column);
171    assertEquals(200, response.getCode());
172    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
173    CellSetModel cellSet = (CellSetModel)
174      xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
175    RowModel rowModel = cellSet.getRows().get(0);
176    CellModel cell = rowModel.getCells().get(0);
177    assertEquals(Bytes.toString(cell.getColumn()), column);
178    assertEquals(Bytes.toString(cell.getValue()), value);
179  }
180
181  protected static void checkIncrementValueXML(String table, String row, String column,
182                                      long value) throws IOException, JAXBException {
183    Response response1 = getValueXML(table, row, column);
184    assertEquals(200, response1.getCode());
185    assertEquals(Constants.MIMETYPE_XML, response1.getHeader("content-type"));
186    CellSetModel cellSet = (CellSetModel)
187            xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response1.getBody()));
188    RowModel rowModel = cellSet.getRows().get(0);
189    CellModel cell = rowModel.getCells().get(0);
190    assertEquals(Bytes.toString(cell.getColumn()), column);
191    assertEquals(Bytes.toLong(cell.getValue()), value);
192  }
193
194  protected static Response getValuePB(String url) throws IOException {
195    Response response = client.get(url, Constants.MIMETYPE_PROTOBUF); 
196    return response;
197  }
198
199  protected static Response putValueXML(String table, String row, String column,
200      String value) throws IOException, JAXBException {
201    StringBuilder path = new StringBuilder();
202    path.append('/');
203    path.append(table);
204    path.append('/');
205    path.append(row);
206    path.append('/');
207    path.append(column);
208    return putValueXML(path.toString(), table, row, column, value);
209  }
210
211  protected static Response putValueXML(String url, String table, String row,
212      String column, String value) throws IOException, JAXBException {
213    RowModel rowModel = new RowModel(row);
214    rowModel.addCell(new CellModel(Bytes.toBytes(column),
215      Bytes.toBytes(value)));
216    CellSetModel cellSetModel = new CellSetModel();
217    cellSetModel.addRow(rowModel);
218    StringWriter writer = new StringWriter();
219    xmlMarshaller.marshal(cellSetModel, writer);
220    Response response = client.put(url, Constants.MIMETYPE_XML,
221      Bytes.toBytes(writer.toString()));
222    Thread.yield();
223    return response;
224  }
225
226  protected static Response getValuePB(String table, String row, String column)
227      throws IOException {
228    StringBuilder path = new StringBuilder();
229    path.append('/');
230    path.append(table);
231    path.append('/');
232    path.append(row);
233    path.append('/');
234    path.append(column);
235    return getValuePB(path.toString());
236  }
237
238  protected static void checkValuePB(String table, String row, String column,
239      String value) throws IOException {
240    Response response = getValuePB(table, row, column);
241    assertEquals(200, response.getCode());
242    assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
243    CellSetModel cellSet = new CellSetModel();
244    cellSet.getObjectFromMessage(response.getBody());
245    RowModel rowModel = cellSet.getRows().get(0);
246    CellModel cell = rowModel.getCells().get(0);
247    assertEquals(Bytes.toString(cell.getColumn()), column);
248    assertEquals(Bytes.toString(cell.getValue()), value);
249  }
250
251  protected static void checkIncrementValuePB(String table, String row, String column,
252      long value) throws IOException {
253    Response response = getValuePB(table, row, column);
254    assertEquals(200, response.getCode());
255    assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
256    CellSetModel cellSet = new CellSetModel();
257    cellSet.getObjectFromMessage(response.getBody());
258    RowModel rowModel = cellSet.getRows().get(0);
259    CellModel cell = rowModel.getCells().get(0);
260    assertEquals(Bytes.toString(cell.getColumn()), column);
261    assertEquals(Bytes.toLong(cell.getValue()), value);
262  }
263
264  protected static Response checkAndPutValuePB(String url, String table,
265      String row, String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
266        throws IOException {
267    RowModel rowModel = new RowModel(row);
268    rowModel.addCell(new CellModel(Bytes.toBytes(column),
269      Bytes.toBytes(valueToPut)));
270
271    if(otherCells != null) {
272      for (Map.Entry<String,String> entry :otherCells.entrySet()) {
273        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
274      }
275    }
276
277    // This Cell need to be added as last cell.
278    rowModel.addCell(new CellModel(Bytes.toBytes(column),
279      Bytes.toBytes(valueToCheck)));
280
281    CellSetModel cellSetModel = new CellSetModel();
282    cellSetModel.addRow(rowModel);
283    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
284      cellSetModel.createProtobufOutput());
285    Thread.yield();
286    return response;
287  }
288
289  protected static Response checkAndPutValuePB(String table, String row,
290      String column, String valueToCheck, String valueToPut) throws IOException {
291    return checkAndPutValuePB(table,row,column,valueToCheck,valueToPut,null);
292  }
293    protected static Response checkAndPutValuePB(String table, String row,
294      String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells) throws IOException {
295    StringBuilder path = new StringBuilder();
296    path.append('/');
297    path.append(table);
298    path.append('/');
299    path.append(row);
300    path.append("?check=put");
301    return checkAndPutValuePB(path.toString(), table, row, column,
302      valueToCheck, valueToPut, otherCells);
303  }
304
305  protected static Response checkAndPutValueXML(String url, String table,
306      String row, String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
307        throws IOException, JAXBException {
308    RowModel rowModel = new RowModel(row);
309    rowModel.addCell(new CellModel(Bytes.toBytes(column),
310      Bytes.toBytes(valueToPut)));
311
312    if(otherCells != null) {
313      for (Map.Entry<String,String> entry :otherCells.entrySet()) {
314        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
315      }
316    }
317
318    // This Cell need to be added as last cell.
319    rowModel.addCell(new CellModel(Bytes.toBytes(column),
320      Bytes.toBytes(valueToCheck)));
321    CellSetModel cellSetModel = new CellSetModel();
322    cellSetModel.addRow(rowModel);
323    StringWriter writer = new StringWriter();
324    xmlMarshaller.marshal(cellSetModel, writer);
325    Response response = client.put(url, Constants.MIMETYPE_XML,
326      Bytes.toBytes(writer.toString()));
327    Thread.yield();
328    return response;
329  }
330
331  protected static Response checkAndPutValueXML(String table, String row,
332                                                String column, String valueToCheck, String valueToPut)
333          throws IOException, JAXBException {
334    return checkAndPutValueXML(table,row,column,valueToCheck,valueToPut, null);
335  }
336
337  protected static Response checkAndPutValueXML(String table, String row,
338      String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
339        throws IOException, JAXBException {
340    StringBuilder path = new StringBuilder();
341    path.append('/');
342    path.append(table);
343    path.append('/');
344    path.append(row);
345    path.append("?check=put");
346    return checkAndPutValueXML(path.toString(), table, row, column,
347      valueToCheck, valueToPut, otherCells);
348  }
349
350  protected static Response checkAndDeleteXML(String url, String table,
351      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
352        throws IOException, JAXBException {
353    RowModel rowModel = new RowModel(row);
354
355    if(cellsToDelete != null) {
356      for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
357        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
358      }
359    }
360    // Add this at the end
361    rowModel.addCell(new CellModel(Bytes.toBytes(column),
362      Bytes.toBytes(valueToCheck)));
363    CellSetModel cellSetModel = new CellSetModel();
364    cellSetModel.addRow(rowModel);
365    StringWriter writer = new StringWriter();
366    xmlMarshaller.marshal(cellSetModel, writer);
367    Response response = client.put(url, Constants.MIMETYPE_XML,
368      Bytes.toBytes(writer.toString()));
369    Thread.yield();
370    return response;
371  }
372
373  protected static Response checkAndDeleteXML(String table, String row,
374      String column, String valueToCheck) throws IOException, JAXBException {
375    return checkAndDeleteXML(table, row, column, valueToCheck, null);
376  }
377  protected static Response checkAndDeleteXML(String table, String row,
378      String column, String valueToCheck, HashMap<String,String> cellsToDelete) throws IOException, JAXBException {
379    StringBuilder path = new StringBuilder();
380    path.append('/');
381    path.append(table);
382    path.append('/');
383    path.append(row);
384    path.append("?check=delete");
385    return checkAndDeleteXML(path.toString(), table, row, column, valueToCheck, cellsToDelete);
386  }
387
388  protected static Response checkAndDeleteJson(String table, String row,
389      String column, String valueToCheck) throws IOException, JAXBException {
390    return checkAndDeleteJson(table, row, column, valueToCheck, null);
391  }
392
393  protected static Response checkAndDeleteJson(String table, String row,
394      String column, String valueToCheck, HashMap<String,String> cellsToDelete) throws IOException, JAXBException {
395    StringBuilder path = new StringBuilder();
396    path.append('/');
397    path.append(table);
398    path.append('/');
399    path.append(row);
400    path.append("?check=delete");
401    return checkAndDeleteJson(path.toString(), table, row, column, valueToCheck, cellsToDelete);
402  }
403
404  protected static Response checkAndDeleteJson(String url, String table,
405      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
406        throws IOException, JAXBException {
407    RowModel rowModel = new RowModel(row);
408
409    if(cellsToDelete != null) {
410      for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
411        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
412      }
413    }
414    // Add this at the end
415    rowModel.addCell(new CellModel(Bytes.toBytes(column),
416      Bytes.toBytes(valueToCheck)));
417    CellSetModel cellSetModel = new CellSetModel();
418    cellSetModel.addRow(rowModel);
419    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
420    Response response = client.put(url, Constants.MIMETYPE_JSON,
421      Bytes.toBytes(jsonString));
422    Thread.yield();
423    return response;
424  }
425
426  protected static Response checkAndDeletePB(String table, String row,
427      String column, String value) throws IOException {
428
429    return checkAndDeletePB(table, row, column, value, null);
430  }
431
432  protected static Response checkAndDeletePB(String table, String row,
433      String column, String value, HashMap<String,String> cellsToDelete) throws IOException {
434    StringBuilder path = new StringBuilder();
435    path.append('/');
436    path.append(table);
437    path.append('/');
438    path.append(row);
439    path.append("?check=delete");
440    return checkAndDeleteValuePB(path.toString(), table, row, column, value, cellsToDelete);
441  }
442  protected static Response checkAndDeleteValuePB(String url, String table,
443      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
444      throws IOException {
445    RowModel rowModel = new RowModel(row);
446
447    if(cellsToDelete != null) {
448      for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
449        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
450      }
451    }
452    // Add this at the end
453    rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes
454        .toBytes(valueToCheck)));
455    CellSetModel cellSetModel = new CellSetModel();
456    cellSetModel.addRow(rowModel);
457    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
458        cellSetModel.createProtobufOutput());
459    Thread.yield();
460    return response;
461  }
462
463  protected static Response getValueXML(String table, String startRow,
464      String endRow, String column) throws IOException {
465    StringBuilder path = new StringBuilder();
466    path.append('/');
467    path.append(table);
468    path.append('/');
469    path.append(startRow);
470    path.append(",");
471    path.append(endRow);
472    path.append('/');
473    path.append(column);
474    return getValueXML(path.toString());
475  }
476
477  protected static Response getValueXML(String url) throws IOException {
478    Response response = client.get(url, Constants.MIMETYPE_XML);
479    return response;
480  }
481
482  protected static Response getValueJson(String url) throws IOException {
483    Response response = client.get(url, Constants.MIMETYPE_JSON);
484    return response;
485  }
486
487  protected static Response deleteValue(String table, String row, String column)
488      throws IOException {
489    StringBuilder path = new StringBuilder();
490    path.append('/');
491    path.append(table);
492    path.append('/');
493    path.append(row);
494    path.append('/');
495    path.append(column);
496    Response response = client.delete(path.toString());
497    Thread.yield();
498    return response;
499  }
500
501  protected static Response getValueXML(String table, String row, String column)
502      throws IOException {
503    StringBuilder path = new StringBuilder();
504    path.append('/');
505    path.append(table);
506    path.append('/');
507    path.append(row);
508    path.append('/');
509    path.append(column);
510    return getValueXML(path.toString());
511  }
512
513  protected static Response deleteRow(String table, String row)
514      throws IOException {
515    StringBuilder path = new StringBuilder();
516    path.append('/');
517    path.append(table);
518    path.append('/');
519    path.append(row);
520    Response response = client.delete(path.toString());
521    Thread.yield();
522    return response;
523  }
524
525  protected static Response getValueJson(String table, String row,
526      String column) throws IOException {
527    StringBuilder path = new StringBuilder();
528    path.append('/');
529    path.append(table);
530    path.append('/');
531    path.append(row);
532    path.append('/');
533    path.append(column);
534    return getValueJson(path.toString());
535  }
536
537  protected static void checkValueJSON(String table, String row, String column,
538      String value) throws IOException, JAXBException {
539    Response response = getValueJson(table, row, column);
540    assertEquals(200, response.getCode());
541    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
542    ObjectMapper mapper = new JacksonJaxbJsonProvider()
543    .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
544    CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
545    RowModel rowModel = cellSet.getRows().get(0);
546    CellModel cell = rowModel.getCells().get(0);
547    assertEquals(Bytes.toString(cell.getColumn()), column);
548    assertEquals(Bytes.toString(cell.getValue()), value);
549  }
550
551  protected static void checkIncrementValueJSON(String table, String row, String column,
552      long value) throws IOException, JAXBException {
553    Response response = getValueJson(table, row, column);
554    assertEquals(200, response.getCode());
555    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
556    ObjectMapper mapper = new JacksonJaxbJsonProvider()
557            .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
558    CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
559    RowModel rowModel = cellSet.getRows().get(0);
560    CellModel cell = rowModel.getCells().get(0);
561    assertEquals(Bytes.toString(cell.getColumn()), column);
562    assertEquals(Bytes.toLong(cell.getValue()), value);
563  }
564
565  protected static Response putValueJson(String table, String row, String column,
566      String value) throws IOException, JAXBException {
567    StringBuilder path = new StringBuilder();
568    path.append('/');
569    path.append(table);
570    path.append('/');
571    path.append(row);
572    path.append('/');
573    path.append(column);
574    return putValueJson(path.toString(), table, row, column, value);
575  }
576
577  protected static Response putValueJson(String url, String table, String row, String column,
578      String value) throws IOException, JAXBException {
579    RowModel rowModel = new RowModel(row);
580    rowModel.addCell(new CellModel(Bytes.toBytes(column),
581      Bytes.toBytes(value)));
582    CellSetModel cellSetModel = new CellSetModel();
583    cellSetModel.addRow(rowModel);
584    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
585    Response response = client.put(url, Constants.MIMETYPE_JSON,
586      Bytes.toBytes(jsonString));
587    Thread.yield();
588    return response;
589  }
590
591  protected static Response appendValueXML(String table, String row, String column,
592      String value) throws IOException, JAXBException {
593    StringBuilder path = new StringBuilder();
594    path.append('/');
595    path.append(table);
596    path.append('/');
597    path.append(row);
598    path.append("?check=append");
599    return putValueXML(path.toString(), table, row, column, value);
600  }
601
602  protected static Response appendValuePB(String table, String row, String column,
603      String value) throws IOException, JAXBException {
604    StringBuilder path = new StringBuilder();
605    path.append('/');
606    path.append(table);
607    path.append('/');
608    path.append(row);
609    path.append("?check=append");
610    return putValuePB(path.toString(), table, row, column, value);
611  }
612
613  protected static Response appendValueJson(String table, String row, String column,
614      String value) throws IOException, JAXBException {
615    StringBuilder path = new StringBuilder();
616    path.append('/');
617    path.append(table);
618    path.append('/');
619    path.append(row);
620    path.append("?check=append");
621    return putValueJson(path.toString(), table, row, column, value);
622  }
623
624  protected static Response incrementValueXML(String table, String row, String column,
625      String value) throws IOException, JAXBException {
626    StringBuilder path = new StringBuilder();
627    path.append('/');
628    path.append(table);
629    path.append('/');
630    path.append(row);
631    path.append("?check=increment");
632    return putValueXML(path.toString(), table, row, column, value);
633  }
634
635  protected static Response incrementValuePB(String table, String row, String column,
636      String value) throws IOException, JAXBException {
637    StringBuilder path = new StringBuilder();
638    path.append('/');
639    path.append(table);
640    path.append('/');
641    path.append(row);
642    path.append("?check=increment");
643    return putValuePB(path.toString(), table, row, column, value);
644  }
645
646  protected static Response incrementValueJson(String table, String row, String column,
647      String value) throws IOException, JAXBException {
648    StringBuilder path = new StringBuilder();
649    path.append('/');
650    path.append(table);
651    path.append('/');
652    path.append(row);
653    path.append("?check=increment");
654    return putValueJson(path.toString(), table, row, column, value);
655  }
656}