/*
* Copyright © 2014 Cask Data, 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 co.cask.cdap.examples.purchase;
import co.cask.cdap.api.data.batch.BatchWritable;
import co.cask.cdap.api.data.batch.RecordScannable;
import co.cask.cdap.api.data.batch.RecordScanner;
import co.cask.cdap.api.data.batch.Scannables;
import co.cask.cdap.api.data.batch.Split;
import co.cask.cdap.api.data.schema.UnsupportedTypeException;
import co.cask.cdap.api.dataset.DatasetProperties;
import co.cask.cdap.api.dataset.DatasetSpecification;
import co.cask.cdap.api.dataset.lib.AbstractDataset;
import co.cask.cdap.api.dataset.lib.ObjectStore;
import co.cask.cdap.api.dataset.lib.ObjectStores;
import co.cask.cdap.api.dataset.module.EmbeddedDataset;
import java.lang.reflect.Type;
import java.util.List;
/**
* This stores purchase histories in an embedded object store. Embedding the object store into this dataset
* ensures that the type parameter (the PurchaseHistory class) is bundled with this dataset's code when it is
* deployed. That means a PurchaseHistoryStore can be used outside of this application, particularly for
* querying the dataset with SQL.
*
* This class implements BatchWritable in order to be able to write to it from Map/Reduce, and RecordScannable
* in order to run ad-hoc queries against it.
*/
public class PurchaseHistoryStore
extends AbstractDataset
implements RecordScannable<PurchaseHistory>, BatchWritable<String, PurchaseHistory> {
// the embedded object store
private final ObjectStore<PurchaseHistory> store;
/**
* These properties will be required to create the object store. We provide them here through a static
* method such that application code that uses this dataset does not need to be aware of the detailed
* properties that are expected.
*
* @param description Dataset description
*
* @return the properties required to create an instance of this dataset
*/
public static DatasetProperties properties(String description) {
try {
return ObjectStores.objectStoreProperties(PurchaseHistory.class,
DatasetProperties.builder().setDescription(description).build());
} catch (UnsupportedTypeException e) {
throw new RuntimeException("This should never be thrown - PurchaseHistory is a supported type", e);
}
}
/**
* Constructor from a specification and the embedded object store. By convention,
* implementing this constructor allows to define this dataset type without an explicit DatasetDefinition.
*
* @param spec the specification
* @param objStore the embedded object store
*/
public PurchaseHistoryStore(DatasetSpecification spec,
@EmbeddedDataset("store") ObjectStore<PurchaseHistory> objStore) {
super(spec.getName(), objStore);
this.store = objStore;
}
@Override // RecordScannable
public Type getRecordType() {
return PurchaseHistory.class;
}
@Override // RecordScannable
public List<Split> getSplits() {
return store.getSplits();
}
@Override // RecordScannable
public RecordScanner<PurchaseHistory> createSplitRecordScanner(Split split) {
return Scannables.valueRecordScanner(store.createSplitReader(split));
}
@Override // BatchWritable
public void write(String key, PurchaseHistory history) {
store.write(key, history);
}
/**
* Write a purchase history to the store. Uses the customer field of the purchase history as the key.
*
* @param history The purchase history to store.
*/
public void write(PurchaseHistory history) {
store.write(history.getCustomer(), history);
}
/**
* @param customer the customer in question
* @return the purchase history of the given customer
*/
public PurchaseHistory read(String customer) {
return store.read(customer);
}
}