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

org.cloudgraph.hbase.scan.ScanLiterals 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.scan;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudgraph.config.DataGraphConfig;
import org.cloudgraph.config.PreDefinedKeyFieldConfig;
import org.cloudgraph.config.UserDefinedRowKeyFieldConfig;
import org.plasma.query.Wildcard;
import org.plasma.query.model.RelationalOperator;

/**
 * A collection of scan literals which provides various accessor methods which
 * indicate the applicability of the scan literal collection under various scan operations. Given that a query
 * may represent any number of scans or gets, clients should ensure that the collection is
 * populated with literals applicable for its query expression context. 
 * @see ScanLiteral
 * @author Scott Cinnamond
 * @since 0.5
 */
public class ScanLiterals {
    private static Log log = LogFactory.getLog(ScanLiterals.class);
	private Map> literalMap = new HashMap>();
	private List literalList = new ArrayList();
	private boolean hasWildcardLiterals = false;
	private boolean hasMultipleWildcardLiterals = false;
	private boolean hasOtherThanSingleTrailingWildcards = false;
	private boolean hasOnlyEqualityRelationalOperators = true;
	private Map hasContiguousPartialKeyScanFieldValuesMap;
	private Map hasContiguousKeyFieldValuesMap;

	public ScanLiterals() {}
	
    public List getLiterals() {    	
		return literalList;
	}
    
    public List getLiterals(
    		UserDefinedRowKeyFieldConfig fieldConfig) {
		return literalMap.get(fieldConfig.getSequenceNum());
	}
	
    public int size() {
    	return this.literalList.size();
    }
    
    public void addLiteral(ScanLiteral scanLiteral) {
    	if (scanLiteral instanceof WildcardStringLiteral) {
    		if (this.hasWildcardLiterals)
    			this.hasMultipleWildcardLiterals = true;
    		this.hasWildcardLiterals = true;
    		
    		WildcardStringLiteral wildcardStringLiteral = (WildcardStringLiteral)scanLiteral;
    		String content = wildcardStringLiteral.getContent().trim();
    		if (!content.endsWith(Wildcard.WILDCARD_CHAR))
    		{
    			this.hasOtherThanSingleTrailingWildcards = true;
    		}
    		else {
    			// it has another wildcard preceding the trailing one
    			if (content.indexOf(Wildcard.WILDCARD_CHAR) < content.length()-1) {
    				this.hasOtherThanSingleTrailingWildcards = true;
    			}
    		}
    	}
    	
    	RelationalOperator oper = scanLiteral.getRelationalOperator();
	    if (oper != null) {
	    	switch (oper.getValue()) {
	    	case EQUALS:
	    		break;
	    	default:
	    		this.hasOnlyEqualityRelationalOperators	= false;
	    	}
    	}
    	
    	UserDefinedRowKeyFieldConfig fieldConfig = scanLiteral.getFieldConfig();
		List list = this.literalMap.get(fieldConfig.getSequenceNum());
		if (list == null) {
			list = new ArrayList(4);
			this.literalMap.put(fieldConfig.getSequenceNum(), list);
		}
		list.add(scanLiteral);
		this.literalList.add(scanLiteral);    	
    }
    
    /**
     * Returns true if this set of literals can support
     * a partial row key scan for the given graph
     * @param graph the graph 
     * @return true if this set of literals can support
     * a partial row key scan for the given graph
     */
    public boolean supportPartialRowKeyScan(DataGraphConfig graph)
    {
    	if (this.hasMultipleWildcardLiterals || this.hasOtherThanSingleTrailingWildcards)
    		return false;
    	
    	// ensure if there is a wildcard literal that its the last literal
    	// in terms of sequence within the row key definition
    	if (this.hasWildcardLiterals) {
    		int maxLiteralSeq = 0;
    		int wildcardLiteralSeq = 0;
    		for (ScanLiteral literal : literalList) {
    			if (literal.getFieldConfig().getSeqNum() > maxLiteralSeq)
    				maxLiteralSeq = literal.getFieldConfig().getSeqNum();
    			if (literal instanceof WildcardStringLiteral) {
    				if (wildcardLiteralSeq > 0)
    					log.warn("detected multiple wildcard literals - ignoring");
    				wildcardLiteralSeq = literal.getFieldConfig().getSeqNum();
    			}
    		}
    		if (wildcardLiteralSeq != maxLiteralSeq)
    			return false;
		}
    	
    	if (hasContiguousPartialKeyScanFieldValuesMap == null)
    		hasContiguousPartialKeyScanFieldValuesMap = new HashMap();
    	
    	if (this.hasContiguousPartialKeyScanFieldValuesMap.get(graph) == null) {
    		boolean hasContiguousPartialKeyScanFieldValues = true;
    		
        	int size = graph.getUserDefinedRowKeyFields().size();
	    	int[] scanLiteralCount = initScanLiteralCount(graph);
	    	
	    	// If any field literal 'gap' found, i.e. if no literals found
	    	// for a field and where the next field DOES have literals
	    	for (int i = 0; i < size-1; i++)
	    		if (scanLiteralCount[i] == 0 && scanLiteralCount[i+1] > 0)
	    			hasContiguousPartialKeyScanFieldValues = false; 
	    	
	    	this.hasContiguousPartialKeyScanFieldValuesMap.put(graph, hasContiguousPartialKeyScanFieldValues);
    	}
    	
    	return this.hasContiguousPartialKeyScanFieldValuesMap.get(graph).booleanValue();
    }
 
    /**
     * Returns true if this set of literals can support
     * a partial row key scan for the given graph
     * @param graph the graph 
     * @return true if this set of literals can support
     * a partial row key scan for the given graph
     */
    public boolean supportCompleteRowKey(DataGraphConfig graph)
    {
    	if (this.hasWildcardLiterals)
    		return false;
    	
    	if (!this.hasOnlyEqualityRelationalOperators)
    		return false;

    	if (hasContiguousKeyFieldValuesMap == null)
    		hasContiguousKeyFieldValuesMap = new HashMap();
    	if (this.hasContiguousKeyFieldValuesMap.get(graph) == null) {
    		boolean hasContiguousFieldValues = true;
        	
    		
        	int size = graph.getUserDefinedRowKeyFields().size();
	    	int[] scanLiteralCount = initScanLiteralCount(graph);
	    	
	    	// If any field literal 'gap' found
	    	for (int i = 0; i < size; i++)
	    		if (scanLiteralCount[i] == 0)
	    			hasContiguousFieldValues = false;  
	    	
	    	for (PreDefinedKeyFieldConfig field : graph.getPreDefinedRowKeyFields()) {
	    		switch (field.getName()) {
	    		case URI: 
	    		case TYPE:
	    			break;
	    		case UUID:
	    			// Because the UUID predefined field exists in the row key definition
	    			// and the UUID cannot be used in a query, as it is an internal value for
	    			// a data object and has no accessor/mutator per se, this makes
	    			// a complete/get operation impossible
	    			hasContiguousFieldValues = false;  
	    			break;  
	    		default:
	    		}
	        }    	
	    	
	    	this.hasContiguousKeyFieldValuesMap.put(graph, hasContiguousFieldValues);
    	}
    
    	return this.hasContiguousKeyFieldValuesMap.get(graph).booleanValue();
    }
    
    private int[] initScanLiteralCount(DataGraphConfig graph) {
    	int size = graph.getUserDefinedRowKeyFields().size();
    	int[] scanLiteralCount = new int[size];
    	
    	for (int i = 0; i < size; i++) {
    		UserDefinedRowKeyFieldConfig fieldConfig = graph.getUserDefinedRowKeyFields().get(i); 
    		List list = this.getLiterals(fieldConfig);
    		if (list != null)
    		    scanLiteralCount[i] = list.size();
    		else
    			scanLiteralCount[i] = 0; 
    	}
    	
    	return scanLiteralCount;
   	
    }
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy