org.kitesdk.data.hbase.avro.AvroEntitySchema Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kite-data-hbase Show documentation
Show all versions of kite-data-hbase Show documentation
The Kite Data HBase module provides integration with HBase.
/**
* Copyright 2013 Cloudera Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kitesdk.data.hbase.avro;
import com.google.common.base.Objects;
import org.apache.avro.Schema;
import org.apache.avro.Schema.Field;
import org.kitesdk.data.ColumnMapping;
import org.kitesdk.data.hbase.impl.EntitySchema;
import org.kitesdk.data.FieldMapping;
import org.kitesdk.data.spi.SchemaUtil;
import org.kitesdk.data.spi.SchemaValidationUtil;
/**
* An EntitySchema implementation powered by Avro.
*/
public class AvroEntitySchema extends EntitySchema {
private final Schema schema;
/**
* Constructor for the AvroEntitySchema.
*
* @param schema
* The Avro Schema that underlies this EntitySchema implementation
* @param rawSchema
* The Avro Schema as a string that underlies the EntitySchema
* implementation
* @param columnMapping
* The list of FieldMappings that specify how each field maps to an
* HBase row
*/
public AvroEntitySchema(Schema schema, String rawSchema,
ColumnMapping columnMapping) {
super(schema.getName(), rawSchema, columnMapping);
this.schema = schema;
}
/**
* Get the Avro Schema that underlies this EntitySchema implementation.
*
* @return The Avro Schema
*/
public Schema getAvroSchema() {
return schema;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((schema == null) ? 0 : schema.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AvroEntitySchema other = (AvroEntitySchema) obj;
if (schema == null) {
if (other.schema != null)
return false;
} else {
if (schema.getFields().size() != other.getAvroSchema().getFields().size()) {
return false;
}
for (Field field : schema.getFields()) {
Field entitySchemaField = other.getAvroSchema().getFields()
.get(field.pos());
if (!fieldsEqual(
field,
this.getColumnMappingDescriptor().getFieldMapping(field.name()),
entitySchemaField,
other.getColumnMappingDescriptor().getFieldMapping(
entitySchemaField.name()))) {
return false;
}
}
}
return true;
}
@Override
public boolean compatible(EntitySchema entitySchema) {
if (!mappingCompatible(this, entitySchema)) {
return false;
}
AvroEntitySchema avroEntitySchema = (AvroEntitySchema) entitySchema;
if (!SchemaValidationUtil.canRead(schema,
avroEntitySchema.getAvroSchema())) {
return false;
}
if (!SchemaValidationUtil.canRead(avroEntitySchema.getAvroSchema(),
schema)) {
return false;
}
return true;
}
/**
* Ensure that the column mappings for the shared fields between the old and
* new schema haven't changed.
*
* @param oldSchema
* @param newSchema
* @return true if the mappings are compatible, false if not.
*/
private static boolean mappingCompatible(EntitySchema oldSchema,
EntitySchema newSchema) {
for (FieldMapping oldFieldMapping : oldSchema.getColumnMappingDescriptor()
.getFieldMappings()) {
FieldMapping newFieldMapping = newSchema.getColumnMappingDescriptor()
.getFieldMapping(oldFieldMapping.getFieldName());
if (newFieldMapping != null) {
if (!oldFieldMapping.equals(newFieldMapping)) {
return false;
}
}
}
return true;
}
private static boolean fieldsEqual(Field field1, FieldMapping field1Mapping,
Field field2, FieldMapping field2Mapping) {
// if names aren't equal, return false
if (!field1.name().equals(field2.name())) {
return false;
}
// if schemas aren't equal, return false
if (!AvroUtils.avroSchemaTypesEqual(field1.schema(), field2.schema())) {
return false;
}
// if field mappings aren't equal, return false
if (!Objects.equal(field1Mapping, field2Mapping)) {
return false;
}
// if one default value is null and the other isn't, return false
if ((field1.defaultValue() != null && field2.defaultValue() == null)
|| (field1.defaultValue() == null && field2.defaultValue() != null)) {
return false;
}
// if both default values are not null, and the default values are not
// equal, return false
if ((field1.defaultValue() != null && field2.defaultValue() != null)
&& !field1.defaultValue().equals(field2.defaultValue())) {
return false;
}
// Fields are equal, return true
return true;
}
}