package org.gbif.occurrence.persistence.hbase; import org.gbif.api.vocabulary.Country; import org.gbif.api.vocabulary.Extension; import org.gbif.dwc.terms.Term; import java.io.IOException; import java.math.BigDecimal; import java.net.URI; import java.util.Date; import java.util.UUID; import javax.annotation.Nullable; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.RowMutations; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.util.Bytes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Convenient update of a single HBase row wrapping a RowMutations object internally. * Type conversions are handled in the many overloaded setField methods. * Setting null values will be translated as internal deletes. * Use setInterpreted for all internal and gbif terms, there should be no verbatim version! */ public class RowUpdate { private static final Logger LOG = LoggerFactory.getLogger(RowUpdate.class); private final byte[] key; private final RowMutations rowMutations; /** * Creates a new instance with an HBase RowMutations object. * * @param key the row key */ public RowUpdate(int key) { this.key = Bytes.toBytes(key); rowMutations = new RowMutations(this.key); } public byte[] getKey() { return key; } public RowMutations getRowMutations() { return rowMutations; } /** * Executes the put and delete on a given hbase table, finally flushing the commit. */ public void execute(Table table) throws IOException { LOG.debug("Executing [{}] mutations", rowMutations.getMutations().size()); table.mutateRow(rowMutations); } public void setField(String column, @Nullable byte[] value) throws IOException { if (value != null) { Put put = new Put(key); put.addColumn(Columns.CF, Bytes.toBytes(column), value); rowMutations.add(put); } else { Delete del = new Delete(key); del.addColumn(Columns.CF, Bytes.toBytes(column)); rowMutations.add(del); } } public void deleteField(String column) throws IOException { Delete del = new Delete(this.key); del.addColumn(Columns.CF, Bytes.toBytes(column)); rowMutations.add(del); } public void deleteField(byte[] columnQualifier) throws IOException { Delete del = new Delete(this.key); del.addColumn(Columns.CF, columnQualifier); rowMutations.add(del); } public void deleteVerbatimField(Term term) throws IOException { setField(Columns.verbatimColumn(term), null); } public void deleteInterpretedField(Term term) throws IOException { setField(Columns.column(term), null); } public void setVerbatimField(Term term, @Nullable byte[] value) throws IOException { setField(Columns.verbatimColumn(term), value); } public void setInterpretedField(Term term, @Nullable byte[] value) throws IOException { setField(Columns.column(term), value); } public void setVerbatimField(Term term, @Nullable String value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable String value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setVerbatimField(Term term, @Nullable Long value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable Long value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setVerbatimField(Term term, @Nullable Double value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable Double value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setVerbatimField(Term term, @Nullable Integer value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable Integer value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setVerbatimField(Term term, @Nullable Date value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable Date value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setVerbatimField(Term term, @Nullable Country value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable Country value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setVerbatimField(Term term, @Nullable UUID value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable UUID value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable URI value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setVerbatimField(Term term, @Nullable Enum<?> value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable Enum<?> value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setVerbatimField(Term term, @Nullable BigDecimal value) throws IOException { setField(Columns.verbatimColumn(term), nullSafeBytes(value)); } public void setInterpretedField(Term term, @Nullable BigDecimal value) throws IOException { setField(Columns.column(term), nullSafeBytes(value)); } public void setInterpretedExtension(Extension extension, @Nullable String value) throws IOException { setField(Columns.column(extension), nullSafeBytes(value)); } public void setVerbatimExtension(Extension extension, @Nullable String value) throws IOException { setField(Columns.verbatimColumn(extension), nullSafeBytes(value)); } private static byte[] nullSafeBytes(String value) { return value == null ? null : Bytes.toBytes(value); } private static byte[] nullSafeBytes(Double value) { return value == null ? null : Bytes.toBytes(value); } private static byte[] nullSafeBytes(Integer value) { return value == null ? null : Bytes.toBytes(value); } private static byte[] nullSafeBytes(Long value) { return value == null ? null : Bytes.toBytes(value); } private static byte[] nullSafeBytes(Date value) { return value == null ? null : Bytes.toBytes(value.getTime()); } private static byte[] nullSafeBytes(Country value) { return value == null ? null : Bytes.toBytes(value.getIso2LetterCode()); } private static byte[] nullSafeBytes(Enum<?> value) { return value == null ? null : Bytes.toBytes(value.name()); } private static byte[] nullSafeBytes(UUID value) { return value == null ? null : Bytes.toBytes(value.toString()); } private static byte[] nullSafeBytes(URI value) { return value == null ? null : Bytes.toBytes(value.toString()); } private static byte[] nullSafeBytes(BigDecimal value) { return value == null ? null : Bytes.toBytes(value); } }