/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.hcatalog.hbase;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableInputFormat;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hive.cli.CliSessionState;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
import org.apache.hadoop.hive.metastore.MetaStoreUtils;
import org.apache.hadoop.hive.ql.processors.CommandProcessorResponse;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapred.RunningJob;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hcatalog.cli.HCatDriver;
import org.apache.hcatalog.cli.SemanticAnalysis.HCatSemanticAnalyzer;
import org.apache.hcatalog.common.HCatConstants;
import org.apache.hcatalog.common.HCatException;
import org.apache.hcatalog.common.HCatUtil;
import org.apache.hcatalog.data.HCatRecord;
import org.apache.hcatalog.data.schema.HCatFieldSchema;
import org.apache.hcatalog.data.schema.HCatSchema;
import org.apache.hcatalog.hbase.snapshot.RevisionManager;
import org.apache.hcatalog.hbase.snapshot.RevisionManagerConfiguration;
import org.apache.hcatalog.hbase.snapshot.Transaction;
import org.apache.hcatalog.mapreduce.HCatInputFormat;
import org.apache.hcatalog.mapreduce.InputJobInfo;
import org.apache.hcatalog.mapreduce.PartInfo;
import org.junit.Test;

public class TestHBaseInputFormat extends SkeletonHBaseTest {

    private static HiveConf   hcatConf;
    private static HCatDriver hcatDriver;
    private final byte[] FAMILY     = Bytes.toBytes("testFamily");
    private final byte[] QUALIFIER1 = Bytes.toBytes("testQualifier1");
    private final byte[] QUALIFIER2 = Bytes.toBytes("testQualifier2");

   public TestHBaseInputFormat() throws Exception {
        hcatConf = getHiveConf();
        hcatConf.set(ConfVars.SEMANTIC_ANALYZER_HOOK.varname,
                HCatSemanticAnalyzer.class.getName());
        URI fsuri = getFileSystem().getUri();
        Path whPath = new Path(fsuri.getScheme(), fsuri.getAuthority(),
                getTestDir());
        hcatConf.set(HiveConf.ConfVars.HADOOPFS.varname, fsuri.toString());
        hcatConf.set(ConfVars.METASTOREWAREHOUSE.varname, whPath.toString());

        //Add hbase properties

        for (Map.Entry<String, String> el : getHbaseConf()) {
            if (el.getKey().startsWith("hbase.")) {
                hcatConf.set(el.getKey(), el.getValue());
            }
        }
        HBaseConfiguration.merge(hcatConf,
               RevisionManagerConfiguration.create());


        SessionState.start(new CliSessionState(hcatConf));
        hcatDriver = new HCatDriver();

    }

    private List<Put> generatePuts(int num, String tableName) throws IOException {

        List<String> columnFamilies = Arrays.asList("testFamily");
        RevisionManager rm = null;
        List<Put> myPuts;
        try {
            rm = HBaseRevisionManagerUtil.getOpenedRevisionManager(hcatConf);
            rm.open();
            myPuts = new ArrayList<Put>();
            for (int i = 1; i <= num; i++) {
                Put put = new Put(Bytes.toBytes("testRow"));
                put.add(FAMILY, QUALIFIER1, i, Bytes.toBytes("textValue-" + i));
                put.add(FAMILY, QUALIFIER2, i, Bytes.toBytes("textValue-" + i));
                myPuts.add(put);
                Transaction tsx = rm.beginWriteTransaction(tableName,
                        columnFamilies);
                rm.commitWriteTransaction(tsx);
            }
        } finally {
            if (rm != null)
                rm.close();
        }

        return myPuts;
    }

   private void populateHBaseTable(String tName, int revisions) throws IOException {
        List<Put> myPuts = generatePuts(revisions, tName);
        HTable table = new HTable(getHbaseConf(), Bytes.toBytes(tName));
        table.put(myPuts);
    }

    private long populateHBaseTableQualifier1(String tName, int value, Boolean commit)
            throws IOException {
        List<String> columnFamilies = Arrays.asList("testFamily");
        RevisionManager rm = null;
        List<Put> myPuts = new ArrayList<Put>();
        long revision;
        try {
            rm = HBaseRevisionManagerUtil.getOpenedRevisionManager(hcatConf);
            rm.open();
            Transaction tsx = rm.beginWriteTransaction(tName, columnFamilies);

            Put put = new Put(Bytes.toBytes("testRow"));
            revision = tsx.getRevisionNumber();
            put.add(FAMILY, QUALIFIER1, revision,
                    Bytes.toBytes("textValue-" + value));
            myPuts.add(put);

            // If commit is null it is left as a running transaction
            if (commit != null) {
                if (commit) {
                    rm.commitWriteTransaction(tsx);
                } else {
                    rm.abortWriteTransaction(tsx);
                }
            }
        } finally {
            if (rm != null)
                rm.close();
        }
        HTable table = new HTable(getHbaseConf(), Bytes.toBytes(tName));
        table.put(myPuts);
        return revision;
    }

    @Test
    public void TestHBaseTableReadMR() throws Exception {
        String tableName = newTableName("MyTable");
        String databaseName = newTableName("MyDatabase");
        //Table name will be lower case unless specified by hbase.table.name property
        String hbaseTableName = (databaseName + "." + tableName).toLowerCase();
        String db_dir = getTestDir() + "/hbasedb";

        String dbquery = "CREATE DATABASE IF NOT EXISTS " + databaseName + " LOCATION '"
                            + db_dir + "'";
        String tableQuery = "CREATE TABLE " + databaseName + "." + tableName
                              + "(key string, testqualifier1 string, testqualifier2 string) STORED BY " +
                              "'org.apache.hcatalog.hbase.HBaseHCatStorageHandler'"
                              + "TBLPROPERTIES ('hbase.columns.mapping'=':key,testFamily:testQualifier1,testFamily:testQualifier2')" ;

        CommandProcessorResponse responseOne = hcatDriver.run(dbquery);
        assertEquals(0, responseOne.getResponseCode());
        CommandProcessorResponse responseTwo = hcatDriver.run(tableQuery);
        assertEquals(0, responseTwo.getResponseCode());

        HBaseAdmin hAdmin = new HBaseAdmin(getHbaseConf());
        boolean doesTableExist = hAdmin.tableExists(hbaseTableName);
        assertTrue(doesTableExist);

        populateHBaseTable(hbaseTableName, 5);
        Configuration conf = new Configuration(hcatConf);
        conf.set(HCatConstants.HCAT_KEY_HIVE_CONF,
                HCatUtil.serialize(getHiveConf().getAllProperties()));

        // output settings
        Path outputDir = new Path(getTestDir(), "mapred/testHbaseTableMRRead");
        FileSystem fs = getFileSystem();
        if (fs.exists(outputDir)) {
            fs.delete(outputDir, true);
        }
        // create job
        Job job = new Job(conf, "hbase-mr-read-test");
        job.setJarByClass(this.getClass());
        job.setMapperClass(MapReadHTable.class);
        MapReadHTable.resetCounters();

        job.setInputFormatClass(HCatInputFormat.class);
        InputJobInfo inputJobInfo = InputJobInfo.create(databaseName, tableName,
                null);
        HCatInputFormat.setInput(job, inputJobInfo);
        job.setOutputFormatClass(TextOutputFormat.class);
        TextOutputFormat.setOutputPath(job, outputDir);
        job.setMapOutputKeyClass(BytesWritable.class);
        job.setMapOutputValueClass(Text.class);
        job.setOutputKeyClass(BytesWritable.class);
        job.setOutputValueClass(Text.class);
        job.setNumReduceTasks(0);
        assertTrue(job.waitForCompletion(true));
        // Note: These asserts only works in case of LocalJobRunner as they run in same jvm.
        // If using MiniMRCluster, the tests will have to be modified.
        assertFalse(MapReadHTable.error);
        assertEquals(MapReadHTable.count, 1);

        String dropTableQuery = "DROP TABLE " + hbaseTableName ;
        CommandProcessorResponse responseThree = hcatDriver.run(dropTableQuery);
        assertEquals(0, responseThree.getResponseCode());

        boolean isHbaseTableThere = hAdmin.tableExists(hbaseTableName);
        assertFalse(isHbaseTableThere);

        String dropDB = "DROP DATABASE " + databaseName;
        CommandProcessorResponse responseFour = hcatDriver.run(dropDB);
        assertEquals(0, responseFour.getResponseCode());
    }

    @Test
    public void TestHBaseTableProjectionReadMR() throws Exception {

        String tableName = newTableName("MyTable");
        //Table name as specified by hbase.table.name property
        String hbaseTableName = "MyDB_" + tableName;
        String tableQuery = "CREATE TABLE " + tableName
                              + "(key string, testqualifier1 string, testqualifier2 string) STORED BY "
                              + "'org.apache.hcatalog.hbase.HBaseHCatStorageHandler'"
                              + "TBLPROPERTIES ('hbase.columns.mapping'="
                              + "':key,testFamily:testQualifier1,testFamily:testQualifier2',"
                              + "'hbase.table.name'='" + hbaseTableName+ "')" ;

        CommandProcessorResponse responseTwo = hcatDriver.run(tableQuery);
        assertEquals(0, responseTwo.getResponseCode());

        HBaseAdmin hAdmin = new HBaseAdmin(getHbaseConf());
        boolean doesTableExist = hAdmin.tableExists(hbaseTableName);
        assertTrue(doesTableExist);

        populateHBaseTable(hbaseTableName, 5);

        Configuration conf = new Configuration(hcatConf);
        conf.set(HCatConstants.HCAT_KEY_HIVE_CONF,
                HCatUtil.serialize(getHiveConf().getAllProperties()));

        // output settings
        Path outputDir = new Path(getTestDir(), "mapred/testHBaseTableProjectionReadMR");
        FileSystem fs = getFileSystem();
        if (fs.exists(outputDir)) {
            fs.delete(outputDir, true);
        }
        // create job
        Job job = new Job(conf, "hbase-column-projection");
        job.setJarByClass(this.getClass());
        job.setMapperClass(MapReadProjHTable.class);
        job.setInputFormatClass(HCatInputFormat.class);
        InputJobInfo inputJobInfo = InputJobInfo.create(
                MetaStoreUtils.DEFAULT_DATABASE_NAME, tableName, null);
        HCatInputFormat.setOutputSchema(job, getProjectionSchema());
        HCatInputFormat.setInput(job, inputJobInfo);
        job.setOutputFormatClass(TextOutputFormat.class);
        TextOutputFormat.setOutputPath(job, outputDir);
        job.setMapOutputKeyClass(BytesWritable.class);
        job.setMapOutputValueClass(Text.class);
        job.setOutputKeyClass(BytesWritable.class);
        job.setOutputValueClass(Text.class);
        job.setNumReduceTasks(0);
        assertTrue(job.waitForCompletion(true));
        assertFalse(MapReadProjHTable.error);
        assertEquals(MapReadProjHTable.count, 1);

        String dropTableQuery = "DROP TABLE " + tableName ;
        CommandProcessorResponse responseThree = hcatDriver.run(dropTableQuery);
        assertEquals(0, responseThree.getResponseCode());

        boolean isHbaseTableThere = hAdmin.tableExists(hbaseTableName);
        assertFalse(isHbaseTableThere);
    }

    @Test
    public void TestHBaseInputFormatProjectionReadMR() throws Exception {

        String tableName = newTableName("mytable");
        String tableQuery = "CREATE TABLE " + tableName
                              + "(key string, testqualifier1 string, testqualifier2 string) STORED BY " +
                              "'org.apache.hcatalog.hbase.HBaseHCatStorageHandler'"
                              + "TBLPROPERTIES ('hbase.columns.mapping'=':key," +
                                    "testFamily:testQualifier1,testFamily:testQualifier2')" ;

        CommandProcessorResponse responseTwo = hcatDriver.run(tableQuery);
        assertEquals(0, responseTwo.getResponseCode());

        HBaseAdmin hAdmin = new HBaseAdmin(getHbaseConf());
        boolean doesTableExist = hAdmin.tableExists(tableName);
        assertTrue(doesTableExist);

        populateHBaseTable(tableName, 5);

        Configuration conf = new Configuration(hcatConf);
        conf.set(HCatConstants.HCAT_KEY_HIVE_CONF,
                HCatUtil.serialize(getHiveConf().getAllProperties()));

        // output settings
        Path outputDir = new Path(getTestDir(), "mapred/testHBaseTableProjectionReadMR");
        FileSystem fs = getFileSystem();
        if (fs.exists(outputDir)) {
            fs.delete(outputDir, true);
        }
        // create job
        JobConf job = new JobConf(conf);
        job.setJobName("hbase-scan-column");
        job.setJarByClass(this.getClass());
        job.setMapperClass(MapReadProjectionHTable.class);
        job.setInputFormat(HBaseInputFormat.class);

        InputJobInfo inputJobInfo = InputJobInfo.create(
                MetaStoreUtils.DEFAULT_DATABASE_NAME, tableName, null);
        //Configure projection schema
        job.set(HCatConstants.HCAT_KEY_OUTPUT_SCHEMA, HCatUtil.serialize(getProjectionSchema()));
        Job newJob = new Job(job);
        HCatInputFormat.setInput(newJob, inputJobInfo);
        String inputJobString = newJob.getConfiguration().get(HCatConstants.HCAT_KEY_JOB_INFO);
        InputJobInfo info = (InputJobInfo) HCatUtil.deserialize(inputJobString);
        job.set(HCatConstants.HCAT_KEY_JOB_INFO, inputJobString);
        for (PartInfo partinfo : info.getPartitions()) {
            for (Entry<String, String> entry : partinfo.getJobProperties().entrySet())
                job.set(entry.getKey(), entry.getValue());
        }
        assertEquals("testFamily:testQualifier1", job.get(TableInputFormat.SCAN_COLUMNS));

        job.setOutputFormat(org.apache.hadoop.mapred.TextOutputFormat.class);
        org.apache.hadoop.mapred.TextOutputFormat.setOutputPath(job, outputDir);
        job.setMapOutputKeyClass(BytesWritable.class);
        job.setMapOutputValueClass(Text.class);
        job.setOutputKeyClass(BytesWritable.class);
        job.setOutputValueClass(Text.class);
        job.setNumReduceTasks(0);

        RunningJob runJob = JobClient.runJob(job);
        runJob.waitForCompletion();
        assertTrue(runJob.isSuccessful());
        assertFalse(MapReadProjHTable.error);
        assertEquals(MapReadProjHTable.count, 1);

        String dropTableQuery = "DROP TABLE " + tableName ;
        CommandProcessorResponse responseThree = hcatDriver.run(dropTableQuery);
        assertEquals(0, responseThree.getResponseCode());

        boolean isHbaseTableThere = hAdmin.tableExists(tableName);
        assertFalse(isHbaseTableThere);
    }

    @Test
    public void TestHBaseTableIgnoreAbortedTransactions() throws Exception {
        String tableName = newTableName("mytable");
        String tableQuery = "CREATE TABLE " + tableName
                              + "(key string, testqualifier1 string, testqualifier2 string) STORED BY " +
                              "'org.apache.hcatalog.hbase.HBaseHCatStorageHandler'"
                              + "TBLPROPERTIES ('hbase.columns.mapping'=':key," +
                                    "testFamily:testQualifier1,testFamily:testQualifier2')" ;

        CommandProcessorResponse responseTwo = hcatDriver.run(tableQuery);
        assertEquals(0, responseTwo.getResponseCode());

        HBaseAdmin hAdmin = new HBaseAdmin(getHbaseConf());
        boolean doesTableExist = hAdmin.tableExists(tableName);
        assertTrue(doesTableExist);

        populateHBaseTable(tableName, 5);
        populateHBaseTableQualifier1(tableName, 6, false);
        populateHBaseTableQualifier1(tableName, 7, false);

        Configuration conf = new Configuration(hcatConf);
        conf.set(HCatConstants.HCAT_KEY_HIVE_CONF,
                HCatUtil.serialize(getHiveConf().getAllProperties()));

        Path outputDir = new Path(getTestDir(), "mapred/testHBaseTableIgnoreAbortedTransactions");
        FileSystem fs = getFileSystem();
        if (fs.exists(outputDir)) {
            fs.delete(outputDir, true);
        }
        Job job = new Job(conf, "hbase-aborted-transaction");
        job.setJarByClass(this.getClass());
        job.setMapperClass(MapReadHTable.class);
        MapReadHTable.resetCounters();
        job.setInputFormatClass(HCatInputFormat.class);
        InputJobInfo inputJobInfo = InputJobInfo.create(
                MetaStoreUtils.DEFAULT_DATABASE_NAME, tableName, null);
        HCatInputFormat.setInput(job, inputJobInfo);
        job.setOutputFormatClass(TextOutputFormat.class);
        TextOutputFormat.setOutputPath(job, outputDir);
        job.setMapOutputKeyClass(BytesWritable.class);
        job.setMapOutputValueClass(Text.class);
        job.setOutputKeyClass(BytesWritable.class);
        job.setOutputValueClass(Text.class);
        job.setNumReduceTasks(0);
        assertTrue(job.waitForCompletion(true));
        // Verify that the records do not contain aborted transaction
        // revisions 6 and 7 for testFamily:testQualifier1 and
        // fetches revision 5 for both testQualifier1 and testQualifier2
        assertFalse(MapReadHTable.error);
        assertEquals(1, MapReadHTable.count);

        String dropTableQuery = "DROP TABLE " + tableName ;
        CommandProcessorResponse responseThree = hcatDriver.run(dropTableQuery);
        assertEquals(0, responseThree.getResponseCode());

        boolean isHbaseTableThere = hAdmin.tableExists(tableName);
        assertFalse(isHbaseTableThere);
    }

    @Test
    public void TestHBaseTableIgnoreAbortedAndRunningTransactions() throws Exception {
        String tableName = newTableName("mytable");
        String tableQuery = "CREATE TABLE " + tableName
                              + "(key string, testqualifier1 string, testqualifier2 string) STORED BY " +
                              "'org.apache.hcatalog.hbase.HBaseHCatStorageHandler'"
                              + "TBLPROPERTIES ('hbase.columns.mapping'=':key," +
                                    "testFamily:testQualifier1,testFamily:testQualifier2')" ;

        CommandProcessorResponse responseTwo = hcatDriver.run(tableQuery);
        assertEquals(0, responseTwo.getResponseCode());

        HBaseAdmin hAdmin = new HBaseAdmin(getHbaseConf());
        boolean doesTableExist = hAdmin.tableExists(tableName);
        assertTrue(doesTableExist);

        populateHBaseTable(tableName, 2);
        populateHBaseTableQualifier1(tableName, 3, Boolean.TRUE); //Committed transaction
        populateHBaseTableQualifier1(tableName, 4, null); //Running transaction
        populateHBaseTableQualifier1(tableName, 5, Boolean.FALSE);  //Aborted transaction
        populateHBaseTableQualifier1(tableName, 6, Boolean.TRUE); //Committed transaction
        populateHBaseTableQualifier1(tableName, 7, null); //Running Transaction
        populateHBaseTableQualifier1(tableName, 8, Boolean.FALSE); //Aborted Transaction

        Configuration conf = new Configuration(hcatConf);
        conf.set(HCatConstants.HCAT_KEY_HIVE_CONF,
                HCatUtil.serialize(getHiveConf().getAllProperties()));

        Path outputDir = new Path(getTestDir(), "mapred/testHBaseTableIgnoreAbortedTransactions");
        FileSystem fs = getFileSystem();
        if (fs.exists(outputDir)) {
            fs.delete(outputDir, true);
        }
        Job job = new Job(conf, "hbase-running-aborted-transaction");
        job.setJarByClass(this.getClass());
        job.setMapperClass(MapReadHTableRunningAbort.class);
        job.setInputFormatClass(HCatInputFormat.class);
        InputJobInfo inputJobInfo = InputJobInfo.create(
                MetaStoreUtils.DEFAULT_DATABASE_NAME, tableName, null);
        HCatInputFormat.setInput(job, inputJobInfo);
        job.setOutputFormatClass(TextOutputFormat.class);
        TextOutputFormat.setOutputPath(job, outputDir);
        job.setMapOutputKeyClass(BytesWritable.class);
        job.setMapOutputValueClass(Text.class);
        job.setOutputKeyClass(BytesWritable.class);
        job.setOutputValueClass(Text.class);
        job.setNumReduceTasks(0);
        assertTrue(job.waitForCompletion(true));
        // Verify that the records do not contain running and aborted transaction
        // and it fetches revision 2 for testQualifier1 and testQualifier2
        assertFalse(MapReadHTableRunningAbort.error);
        assertEquals(1, MapReadHTableRunningAbort.count);

        String dropTableQuery = "DROP TABLE " + tableName ;
        CommandProcessorResponse responseThree = hcatDriver.run(dropTableQuery);
        assertEquals(0, responseThree.getResponseCode());

        boolean isHbaseTableThere = hAdmin.tableExists(tableName);
        assertFalse(isHbaseTableThere);
    }


    static class MapReadHTable
            extends
            Mapper<ImmutableBytesWritable, HCatRecord, WritableComparable<?>, Text> {

        static boolean error = false;
        static int count = 0;

        @Override
        public void map(ImmutableBytesWritable key, HCatRecord value,
                Context context) throws IOException, InterruptedException {
            System.out.println("HCat record value" + value.toString());
            boolean correctValues = (value.size() == 3)
                    && (value.get(0).toString()).equalsIgnoreCase("testRow")
                    && (value.get(1).toString()).equalsIgnoreCase("textValue-5")
                    && (value.get(2).toString()).equalsIgnoreCase("textValue-5");

            if (correctValues == false) {
                error = true;
            }
            count++;
        }

        public static void resetCounters() {
            error = false;
            count = 0;
        }
    }

    static class MapReadProjHTable
            extends
            Mapper<ImmutableBytesWritable, HCatRecord, WritableComparable<?>, Text> {

        static boolean error = false;
        static int count = 0;
        @Override
        public void map(ImmutableBytesWritable key, HCatRecord value,
                Context context) throws IOException, InterruptedException {
            System.out.println("HCat record value" + value.toString());
            boolean correctValues = (value.size() == 2)
                    && (value.get(0).toString()).equalsIgnoreCase("testRow")
                    && (value.get(1).toString()).equalsIgnoreCase("textValue-5");

            if (correctValues == false) {
                error = true;
            }
            count++;
        }
    }

    static class MapReadProjectionHTable
            implements org.apache.hadoop.mapred.Mapper<ImmutableBytesWritable, Result, WritableComparable<?>, Text> {

        static boolean error = false;
        static int count = 0;

        @Override
        public void configure(JobConf job) {
        }

        @Override
        public void close() throws IOException {
        }

        @Override
        public void map(ImmutableBytesWritable key, Result result,
                OutputCollector<WritableComparable<?>, Text> output, Reporter reporter)
                throws IOException {
            System.out.println("Result " + result.toString());
            List<KeyValue> list = result.list();
            boolean correctValues = (list.size() == 1)
                    && (Bytes.toString(list.get(0).getRow())).equalsIgnoreCase("testRow")
                    && (Bytes.toString(list.get(0).getValue())).equalsIgnoreCase("textValue-5")
                    && (Bytes.toString(list.get(0).getFamily())).equalsIgnoreCase("testFamily")
                    && (Bytes.toString(list.get(0).getQualifier())).equalsIgnoreCase("testQualifier1");

            if (correctValues == false) {
                error = true;
            }
            count++;
        }
    }

    static class MapReadHTableRunningAbort
            extends
            Mapper<ImmutableBytesWritable, HCatRecord, WritableComparable<?>, Text> {

        static boolean error = false;
        static int count = 0;

        @Override
        public void map(ImmutableBytesWritable key, HCatRecord value,
                Context context) throws IOException, InterruptedException {
            System.out.println("HCat record value" + value.toString());
            boolean correctValues = (value.size() == 3)
                    && (value.get(0).toString()).equalsIgnoreCase("testRow")
                    && (value.get(1).toString()).equalsIgnoreCase("textValue-3")
                    && (value.get(2).toString()).equalsIgnoreCase("textValue-2");

            if (correctValues == false) {
                error = true;
            }
            count++;
        }
    }

    private HCatSchema getProjectionSchema() throws HCatException {

        HCatSchema schema = new HCatSchema(new ArrayList<HCatFieldSchema>());
        schema.append(new HCatFieldSchema("key", HCatFieldSchema.Type.STRING,
                ""));
        schema.append(new HCatFieldSchema("testqualifier1",
                HCatFieldSchema.Type.STRING, ""));
        return schema;
    }


}
