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 com.fasterxml.jackson.annotation.JsonProperty;
021import java.io.IOException;
022import java.io.Serializable;
023import javax.xml.bind.annotation.XmlAccessType;
024import javax.xml.bind.annotation.XmlAccessorType;
025import javax.xml.bind.annotation.XmlAttribute;
026import javax.xml.bind.annotation.XmlRootElement;
027import javax.xml.bind.annotation.XmlValue;
028import org.apache.commons.lang3.builder.EqualsBuilder;
029import org.apache.commons.lang3.builder.HashCodeBuilder;
030import org.apache.commons.lang3.builder.ToStringBuilder;
031import org.apache.hadoop.hbase.CellUtil;
032import org.apache.hadoop.hbase.HConstants;
033import org.apache.hadoop.hbase.rest.ProtobufMessageHandler;
034import org.apache.yetus.audience.InterfaceAudience;
035
036import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;
037
038import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
039import org.apache.hadoop.hbase.shaded.rest.protobuf.generated.CellMessage.Cell;
040
041/**
042 * Representation of a cell. A cell is a single value associated a column and optional qualifier,
043 * and either the timestamp when it was stored or the user- provided timestamp if one was explicitly
044 * supplied.
045 *
046 * <pre>
047 * &lt;complexType name="Cell"&gt;
048 *   &lt;sequence&gt;
049 *     &lt;element name="value" maxOccurs="1" minOccurs="1"&gt;
050 *       &lt;simpleType&gt;
051 *         &lt;restriction base="base64Binary"/&gt;
052 *       &lt;/simpleType&gt;
053 *     &lt;/element&gt;
054 *   &lt;/sequence&gt;
055 *   &lt;attribute name="column" type="base64Binary" /&gt;
056 *   &lt;attribute name="timestamp" type="int" /&gt;
057 * &lt;/complexType&gt;
058 * </pre>
059 */
060@XmlRootElement(name = "Cell")
061@XmlAccessorType(XmlAccessType.FIELD)
062@InterfaceAudience.Private
063public class CellModel implements ProtobufMessageHandler, Serializable {
064  private static final long serialVersionUID = 1L;
065
066  @JsonProperty("column")
067  @XmlAttribute
068  private byte[] column;
069
070  @JsonProperty("timestamp")
071  @XmlAttribute
072  private long timestamp = HConstants.LATEST_TIMESTAMP;
073
074  @JsonProperty("$")
075  @XmlValue
076  private byte[] value;
077
078  /**
079   * Default constructor
080   */
081  public CellModel() {
082  }
083
084  /**
085   * Constructor
086   */
087  public CellModel(byte[] column, byte[] value) {
088    this(column, HConstants.LATEST_TIMESTAMP, value);
089  }
090
091  /**
092   * Constructor
093   */
094  public CellModel(byte[] column, byte[] qualifier, byte[] value) {
095    this(column, qualifier, HConstants.LATEST_TIMESTAMP, value);
096  }
097
098  /**
099   * Constructor from KeyValue
100   */
101  public CellModel(org.apache.hadoop.hbase.Cell cell) {
102    this(CellUtil.cloneFamily(cell), CellUtil.cloneQualifier(cell), cell.getTimestamp(),
103      CellUtil.cloneValue(cell));
104  }
105
106  /**
107   * Constructor
108   */
109  public CellModel(byte[] column, long timestamp, byte[] value) {
110    this.column = column;
111    this.timestamp = timestamp;
112    this.value = value;
113  }
114
115  /**
116   * Constructor
117   */
118  public CellModel(byte[] column, byte[] qualifier, long timestamp, byte[] value) {
119    this.column = CellUtil.makeColumn(column, qualifier);
120    this.timestamp = timestamp;
121    this.value = value;
122  }
123
124  /** Returns the column */
125  public byte[] getColumn() {
126    return column;
127  }
128
129  /**
130   * @param column the column to set
131   */
132  public void setColumn(byte[] column) {
133    this.column = column;
134  }
135
136  /** Returns true if the timestamp property has been specified by the user */
137  public boolean hasUserTimestamp() {
138    return timestamp != HConstants.LATEST_TIMESTAMP;
139  }
140
141  /** Returns the timestamp */
142  public long getTimestamp() {
143    return timestamp;
144  }
145
146  /**
147   * @param timestamp the timestamp to set
148   */
149  public void setTimestamp(long timestamp) {
150    this.timestamp = timestamp;
151  }
152
153  /** Returns the value */
154  public byte[] getValue() {
155    return value;
156  }
157
158  /**
159   * @param value the value to set
160   */
161  public void setValue(byte[] value) {
162    this.value = value;
163  }
164
165  @Override
166  public byte[] createProtobufOutput() {
167    Cell.Builder builder = Cell.newBuilder();
168    builder.setColumn(UnsafeByteOperations.unsafeWrap(getColumn()));
169    builder.setData(UnsafeByteOperations.unsafeWrap(getValue()));
170    if (hasUserTimestamp()) {
171      builder.setTimestamp(getTimestamp());
172    }
173    return builder.build().toByteArray();
174  }
175
176  @Override
177  public ProtobufMessageHandler getObjectFromMessage(byte[] message) throws IOException {
178    Cell.Builder builder = Cell.newBuilder();
179    ProtobufUtil.mergeFrom(builder, message);
180    setColumn(builder.getColumn().toByteArray());
181    setValue(builder.getData().toByteArray());
182    if (builder.hasTimestamp()) {
183      setTimestamp(builder.getTimestamp());
184    }
185    return this;
186  }
187
188  @Override
189  public boolean equals(Object obj) {
190    if (obj == null) {
191      return false;
192    }
193    if (obj == this) {
194      return true;
195    }
196    if (obj.getClass() != getClass()) {
197      return false;
198    }
199    CellModel cellModel = (CellModel) obj;
200    return new EqualsBuilder().append(column, cellModel.column)
201      .append(timestamp, cellModel.timestamp).append(value, cellModel.value).isEquals();
202  }
203
204  @Override
205  public int hashCode() {
206    return new HashCodeBuilder().append(column).append(timestamp).append(value).toHashCode();
207  }
208
209  @Override
210  public String toString() {
211    return new ToStringBuilder(this).append("column", column).append("timestamp", timestamp)
212      .append("value", value).toString();
213  }
214}