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.model;
019
020import static org.apache.hadoop.hbase.rest.model.CellModel.MAGIC_LENGTH;
021
022import java.io.IOException;
023import java.io.Serializable;
024import java.util.ArrayList;
025import java.util.List;
026import javax.xml.bind.annotation.XmlAccessType;
027import javax.xml.bind.annotation.XmlAccessorType;
028import javax.xml.bind.annotation.XmlElement;
029import javax.xml.bind.annotation.XmlRootElement;
030import org.apache.hadoop.hbase.HConstants;
031import org.apache.hadoop.hbase.rest.ProtobufMessageHandler;
032import org.apache.hadoop.hbase.rest.RestUtil;
033import org.apache.hadoop.hbase.rest.protobuf.generated.CellMessage.Cell;
034import org.apache.hadoop.hbase.rest.protobuf.generated.CellSetMessage.CellSet;
035import org.apache.yetus.audience.InterfaceAudience;
036
037import org.apache.hbase.thirdparty.com.google.protobuf.CodedInputStream;
038import org.apache.hbase.thirdparty.com.google.protobuf.Message;
039import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;
040
041/**
042 * Representation of a grouping of cells. May contain cells from more than one row. Encapsulates
043 * RowModel and CellModel models.
044 *
045 * <pre>
046 * &lt;complexType name="CellSet"&gt;
047 *   &lt;sequence&gt;
048 *     &lt;element name="row" type="tns:Row" maxOccurs="unbounded"
049 *       minOccurs="1"&gt;&lt;/element&gt;
050 *   &lt;/sequence&gt;
051 * &lt;/complexType&gt;
052 *
053 * &lt;complexType name="Row"&gt;
054 *   &lt;sequence&gt;
055 *     &lt;element name="key" type="base64Binary"&gt;&lt;/element&gt;
056 *     &lt;element name="cell" type="tns:Cell"
057 *       maxOccurs="unbounded" minOccurs="1"&gt;&lt;/element&gt;
058 *   &lt;/sequence&gt;
059 * &lt;/complexType&gt;
060 *
061 * &lt;complexType name="Cell"&gt;
062 *   &lt;sequence&gt;
063 *     &lt;element name="value" maxOccurs="1" minOccurs="1"&gt;
064 *       &lt;simpleType&gt;
065 *         &lt;restriction base="base64Binary"/&gt;
066 *       &lt;/simpleType&gt;
067 *     &lt;/element&gt;
068 *   &lt;/sequence&gt;
069 *   &lt;attribute name="column" type="base64Binary" /&gt;
070 *   &lt;attribute name="timestamp" type="int" /&gt;
071 * &lt;/complexType&gt;
072 * </pre>
073 */
074@XmlRootElement(name = "CellSet")
075@XmlAccessorType(XmlAccessType.NONE)
076@InterfaceAudience.Private
077public class CellSetModel implements Serializable, ProtobufMessageHandler {
078  private static final long serialVersionUID = 1L;
079
080  @XmlElement(name = "Row")
081  private List<RowModel> rows;
082
083  /**
084   * Constructor
085   */
086  public CellSetModel() {
087    this.rows = new ArrayList<>();
088  }
089
090  /**
091   * @param rows the rows
092   */
093  public CellSetModel(List<RowModel> rows) {
094    super();
095    this.rows = rows;
096  }
097
098  /**
099   * Add a row to this cell set
100   * @param row the row
101   */
102  public void addRow(RowModel row) {
103    rows.add(row);
104  }
105
106  /** Returns the rows */
107  public List<RowModel> getRows() {
108    return rows;
109  }
110
111  @Override
112  public Message messageFromObject() {
113    CellSet.Builder builder = CellSet.newBuilder();
114    for (RowModel row : getRows()) {
115      CellSet.Row.Builder rowBuilder = CellSet.Row.newBuilder();
116      if (row.getKeyLength() == MAGIC_LENGTH) {
117        rowBuilder.setKey(UnsafeByteOperations.unsafeWrap(row.getKey()));
118      } else {
119        rowBuilder.setKey(UnsafeByteOperations.unsafeWrap(row.getKeyArray(), row.getKeyOffset(),
120          row.getKeyLength()));
121      }
122      for (CellModel cell : row.getCells()) {
123        Cell.Builder cellBuilder = Cell.newBuilder();
124        cellBuilder.setColumn(UnsafeByteOperations.unsafeWrap(cell.getColumn()));
125        if (cell.getValueLength() == MAGIC_LENGTH) {
126          cellBuilder.setData(UnsafeByteOperations.unsafeWrap(cell.getValue()));
127        } else {
128          cellBuilder.setData(UnsafeByteOperations.unsafeWrap(cell.getValueArray(),
129            cell.getValueOffset(), cell.getValueLength()));
130        }
131        if (cell.hasUserTimestamp()) {
132          cellBuilder.setTimestamp(cell.getTimestamp());
133        }
134        rowBuilder.addValues(cellBuilder);
135      }
136      builder.addRows(rowBuilder);
137    }
138    return builder.build();
139  }
140
141  @Override
142  public ProtobufMessageHandler getObjectFromMessage(CodedInputStream cis) throws IOException {
143    CellSet.Builder builder = CellSet.newBuilder();
144    RestUtil.mergeFrom(builder, cis);
145    for (CellSet.Row row : builder.getRowsList()) {
146      RowModel rowModel = new RowModel(row.getKey().toByteArray());
147      for (Cell cell : row.getValuesList()) {
148        long timestamp = HConstants.LATEST_TIMESTAMP;
149        if (cell.hasTimestamp()) {
150          timestamp = cell.getTimestamp();
151        }
152        rowModel.addCell(
153          new CellModel(cell.getColumn().toByteArray(), timestamp, cell.getData().toByteArray()));
154      }
155      addRow(rowModel);
156    }
157    return this;
158  }
159}