All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cloudgraph.hbase.key.CompositeRowKeyFactory Maven / Gradle / Ivy

/**
 *        CloudGraph Community Edition (CE) License
 * 
 * This is a community release of CloudGraph, a dual-license suite of
 * Service Data Object (SDO) 2.1 services designed for relational and 
 * big-table style "cloud" databases, such as HBase and others. 
 * This particular copy of the software is released under the 
 * version 2 of the GNU General Public License. CloudGraph was developed by 
 * TerraMeta Software, Inc.
 * 
 * Copyright (c) 2013, TerraMeta Software, Inc. All rights reserved.
 * 
 * General License information can be found below.
 * 
 * This distribution may include materials developed by third
 * parties. For license and attribution notices for these
 * materials, please refer to the documentation that accompanies
 * this distribution (see the "Licenses for Third-Party Components"
 * appendix) or view the online documentation at 
 * . 
 */
package org.cloudgraph.hbase.key;

import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudgraph.config.KeyFieldConfig;
import org.cloudgraph.config.PreDefinedKeyFieldConfig;
import org.cloudgraph.config.UserDefinedRowKeyFieldConfig;
import org.cloudgraph.store.key.GraphRowKeyFactory;
import org.cloudgraph.store.key.KeyFieldOverflowException;
import org.cloudgraph.store.key.KeyValue;
import org.plasma.sdo.DataFlavor;
import org.plasma.sdo.PlasmaProperty;
import org.plasma.sdo.PlasmaType;

import commonj.sdo.DataGraph;
import commonj.sdo.DataObject;
import commonj.sdo.Type;

/**
 * Generates an HBase row key based on the configured CloudGraph {@link org.cloudgraph.config.RowKeyModel Row Key
 * Model} for a specific {@link org.cloudgraph.config.Table HTable Configuration}. 
 * 

* The initial creation and subsequent reconstitution for query retrieval * purposes of both row and column keys in CloudGraph™ is efficient, * as it leverages byte array level API in both Java and the current * underlying SDO 2.1 implementation, PlasmaSDO™. Both composite row and * column keys are composed in part of structural metadata, and the * lightweight metadata API within PlasmaSDO™ contains byte-array level, * cached lookup of all basic metadata elements including logical and * physical type and property names. *

* @author Scott Cinnamond * @since 0.5 */ public class CompositeRowKeyFactory extends ByteBufferKeyFactory implements GraphRowKeyFactory { private static final Log log = LogFactory.getLog(CompositeRowKeyFactory.class); protected Padding padding; public CompositeRowKeyFactory(PlasmaType rootType) { super(rootType); this.padding = new Padding(this.charset); } /** * Creates a row key using only the given type information. The * key is therefore composed of only "metadata" fields which are * pre-defined. * @param type the data object type * @return the row key */ public String createRowKey(Type type) { StringBuilder result = new StringBuilder(); PlasmaType plasmaType = (PlasmaType)type; List preDefinedFields = graph.getPreDefinedRowKeyFields(); for (int i = 0; i < preDefinedFields.size(); i++) { PreDefinedKeyFieldConfig preDefinedField = preDefinedFields.get(i); if (i > 0) result.append(graph.getRowKeyFieldDelimiter()); String tokenValue = this.keySupport.getPredefinedFieldValue(plasmaType, this.hashing, preDefinedField); String padded = this.padding.pad(tokenValue, preDefinedField.getMaxLength(), preDefinedField.getDataFlavor()); result.append(padded); } return result.toString(); } @Override public byte[] createRowKeyBytes(Type type) { PlasmaType plasmaType = (PlasmaType)type; this.buf.clear(); try { create(plasmaType); } catch (BufferOverflowException e) { this.bufsize = this.bufsize * 2; this.buf = ByteBuffer.allocate(this.bufsize); create(plasmaType); } return this.buf.array(); } private void create(PlasmaType type) { List preDefinedFields = this.graph.getPreDefinedRowKeyFields(); for (int i = 0; i < preDefinedFields.size(); i++) { PreDefinedKeyFieldConfig preDefinedField = preDefinedFields.get(i); if (i > 0) this.buf.put(this.graph.getRowKeyFieldDelimiterBytes()); byte[] tokenValue = this.keySupport.getPredefinedFieldValueBytes(type, this.hashing, preDefinedField); if (preDefinedField.isHash()) { tokenValue = padding.pad(tokenValue, preDefinedField.getMaxLength(), DataFlavor.integral); } else { tokenValue = padding.pad(tokenValue, preDefinedField.getMaxLength(), preDefinedField.getDataFlavor()); } this.buf.put(tokenValue); } } @Override public byte[] createRowKeyBytes(DataGraph dataGraph) { return createRowKeyBytes(dataGraph.getRootObject()); } @Override public byte[] createRowKeyBytes(DataObject rootDataObject) { this.buf.clear(); int i = 0; for (KeyFieldConfig fieldConfig : this.graph.getRowKeyFields()) { if (i > 0) this.buf.put(graph.getRowKeyFieldDelimiterBytes()); byte[] keyValue = fieldConfig.getKeyBytes(rootDataObject); byte[] paddedKeyValue = null; if (fieldConfig.isHash()) { keyValue = this.hashing.toStringBytes(keyValue); paddedKeyValue = padding.pad(keyValue, fieldConfig.getMaxLength(), DataFlavor.integral); } else { if (fieldConfig instanceof UserDefinedRowKeyFieldConfig) { UserDefinedRowKeyFieldConfig userField = (UserDefinedRowKeyFieldConfig)fieldConfig; PlasmaProperty endpointProp = userField.getEndpointProperty(); int delta = userField.getMaxLength() - keyValue.length; if (delta < 0) throw new KeyFieldOverflowException("user-defined field value '" + new String(keyValue, this.charset) + "' for path endpoint (property), " + endpointProp + ", with dataflavor, " + endpointProp.getDataFlavor() + ", exceeded max length (" + String.valueOf(userField.getMaxLength()) + ")"); paddedKeyValue = padding.pad(keyValue, userField.getMaxLength(), endpointProp.getDataFlavor()); } else { paddedKeyValue = padding.pad(keyValue, fieldConfig.getMaxLength(), fieldConfig.getDataFlavor()); } } this.buf.put(paddedKeyValue); i++; } // ByteBuffer.array() returns unsized array so don't sent that back to clients // to misuse. // Use native arraycopy() method as it uses native memcopy to create result array // and because and // ByteBuffer.get(byte[] dst,int offset, int length) is not native byte [] result = new byte[this.buf.position()]; System.arraycopy(this.buf.array(), this.buf.arrayOffset(), result, 0, this.buf.position()); return result; } @Override public byte[] createRowKeyBytes(List values) { this.buf.clear(); byte[] fieldValue = null; int i = 0; for (KeyFieldConfig fieldConfig : this.graph.getRowKeyFields()) { if (i > 0) this.buf.put(graph.getRowKeyFieldDelimiterBytes()); if (fieldConfig instanceof PreDefinedKeyFieldConfig) { PreDefinedKeyFieldConfig predefinedConfig = (PreDefinedKeyFieldConfig)fieldConfig; fieldValue = predefinedConfig.getKeyBytes(this.rootType); } else { UserDefinedRowKeyFieldConfig userFieldConfig = (UserDefinedRowKeyFieldConfig)fieldConfig; KeyValue keyValue = this.keySupport.findKeyValue(userFieldConfig, values); if (keyValue != null) { // FIXME: do we want to invoke a converter here? // FIXME: do we want to transform this value somehow? String stringValue = String.valueOf(keyValue.getValue()); fieldValue = stringValue.getBytes(this.charset); } else { continue; // could be a partial row key scan } } byte[] paddedKeyValue = null; if (fieldConfig.isHash()) { fieldValue = this.hashing.toStringBytes(fieldValue); paddedKeyValue = padding.pad(fieldValue, fieldConfig.getMaxLength(), DataFlavor.integral); } else { if (fieldConfig instanceof UserDefinedRowKeyFieldConfig) { UserDefinedRowKeyFieldConfig userField = (UserDefinedRowKeyFieldConfig)fieldConfig; PlasmaProperty endpointProp = userField.getEndpointProperty(); int delta = userField.getMaxLength() - fieldValue.length; if (delta < 0) throw new KeyFieldOverflowException("user-defined field value '" + new String(fieldValue, this.charset) + "' for path endpoint (property), " + endpointProp + ", with dataflavor, " + endpointProp.getDataFlavor() + ", exceeded max length (" + String.valueOf(userField.getMaxLength()) + ")"); paddedKeyValue = padding.pad(fieldValue, userField.getMaxLength(), userField.getEndpointProperty().getDataFlavor()); } else { paddedKeyValue = padding.pad(fieldValue, fieldConfig.getMaxLength(), fieldConfig.getDataFlavor()); } } this.buf.put(paddedKeyValue); i++; } // ByteBuffer.array() returns unsized array so don't sent that back to clients // to misuse. // Use native arraycopy() method as it uses native memcopy to create result array // and because and // ByteBuffer.get(byte[] dst,int offset, int length) is not native byte [] result = new byte[this.buf.position()]; System.arraycopy(this.buf.array(), this.buf.arrayOffset(), result, 0, this.buf.position()); return result; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy