/** * 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 com.cloudera.cdk.data.hbase.avro; import java.io.InputStream; import org.apache.avro.generic.GenericRecord; import org.apache.hadoop.hbase.client.HTablePool; import com.cloudera.cdk.data.hbase.impl.BaseDao; import com.cloudera.cdk.data.hbase.impl.BaseEntityMapper; import com.cloudera.cdk.data.hbase.impl.SchemaManager; /** * A Dao for Avro's GenericRecords. In this Dao implementation, both the * underlying key record type, and the entity type are GenericRecords. This Dao * allows us to persist and fetch these GenericRecords to and from HBase. */ public class GenericAvroDao extends BaseDao<GenericRecord> { private static final AvroKeyEntitySchemaParser parser = new AvroKeyEntitySchemaParser(); /** * Construct a GenericAvroDao. * * @param tablePool * An HTablePool instance to use for connecting to HBase. * @param tableName * The name of the table this Dao will read from and write to in * HBase. * @param keySchemaStr * The Avro schema that represents the StorageKey structure for row keys in * this table. * @param entitySchemaString * The json string representing the special avro record schema, that * contains metadata in annotations of the Avro record fields. See * {@link AvroEntityMapper} for details. */ public GenericAvroDao(HTablePool tablePool, String tableName, String entitySchemaString) { super(tablePool, tableName, buildEntityMapper(entitySchemaString)); } /** * Construct a GenericAvroDao. * * @param tablePool * An HTablePool instance to use for connecting to HBase. * @param tableName * The name of the table this Dao will read from and write to in * HBase. * @param keySchemaStr * The Avro schema that represents the StorageKey structure for row keys in * this table. * @param entitySchemaStream * The InputStream that contains a json string representing the * special avro record schema, that contains metadata in annotations * of the Avro record fields. See {@link AvroEntityMapper} for * details. */ public GenericAvroDao(HTablePool tablePool, String tableName, InputStream entitySchemaStream) { super(tablePool, tableName, buildEntityMapper(AvroUtils .inputStreamToString(entitySchemaStream))); } /** * Construct the GenericAvroDao with an EntityManager, which will provide the * entity mapper to this Dao that knows how to map the different entity schema * versions defined by the managed schema. The entitySchemaString parameter * represents the schema to use for writes. * * @param tablePool * An HTabePool instance to use for connecting to HBase. * @param tableName * The table name of the managed schema. * @param entityName * The entity name of the managed schema. * @param schemaManager * The EntityManager which will create the entity mapper that will * power this dao. * @param entitySchemaString * The schema as a string representing the schema version that this * DAO should use for writes. */ public GenericAvroDao(HTablePool tablePool, String tableName, String entityName, SchemaManager schemaManager, String entitySchemaString) { super(tablePool, tableName, new VersionedAvroEntityMapper.Builder() .setSchemaManager(schemaManager).setTableName(tableName) .setEntityName(entityName).setSpecific(false) .setGenericSchemaString(entitySchemaString).<GenericRecord> build()); } /** * Construct the GenericAvroDao with an EntityManager, which will provide the * entity mapper to this Dao that knows how to map the different entity schema * versions defined by the managed schema. The newest schema version available * at the time of this dao's creation will be used for writes. * * @param tablePool * An HTabePool instance to use for connecting to HBase. * @param tableName * The table name of the managed schema. * @param entityName * The entity name of the managed schema. * @param schemaManager * The SchemaManager which will create the entity mapper that will * power this dao. */ public GenericAvroDao(HTablePool tablePool, String tableName, String entityName, SchemaManager schemaManager) { super(tablePool, tableName, new VersionedAvroEntityMapper.Builder() .setSchemaManager(schemaManager).setTableName(tableName) .setEntityName(entityName).setSpecific(false).<GenericRecord> build()); } private static BaseEntityMapper<GenericRecord> buildEntityMapper( String readerSchemaStr) { return buildEntityMapper(readerSchemaStr, readerSchemaStr); } private static BaseEntityMapper<GenericRecord> buildEntityMapper( String readerSchemaStr, String writtenSchemaStr) { AvroEntitySchema readerSchema = parser.parseEntitySchema(readerSchemaStr); AvroEntitySchema writtenSchema = parser.parseEntitySchema(writtenSchemaStr); AvroEntityComposer<GenericRecord> entityComposer = new AvroEntityComposer<GenericRecord>( readerSchema, false); AvroEntitySerDe<GenericRecord> entitySerDe = new AvroEntitySerDe<GenericRecord>( entityComposer, readerSchema, writtenSchema, false); AvroKeySchema keySchema = parser.parseKeySchema(readerSchemaStr); AvroKeySerDe keySerDe = new AvroKeySerDe(keySchema.getAvroSchema(), keySchema.getPartitionStrategy()); return new BaseEntityMapper<GenericRecord>(keySchema, readerSchema, keySerDe, entitySerDe); } }