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