/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
licenses@blazegraph.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on June 22, 2015
*/
package com.bigdata.rdf.sparql.ast.optimizers;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.bigdata.rdf.sparql.ast.IGroupMemberNode;
/**
* Classification of {@link IGroupMemberNode}s along a set of specified
* types. For nodes matching a given type, lookup is possible (returning
* an ordered list of nodes), all other nodes are stored in a dedicated list.
*
* There is an additional method to inject custom constraints for the individual
* classes. In case a constraint is set for a class, the node is only added
* to the type cluster if the
* {@link ASTTypeBasedNodeClassifierConstraint#applies()}
* returns true for the node of the given type.
*
* @author <a href="mailto:ms@metaphacts.com">Michael Schmidt</a>
*/
class ASTTypeBasedNodeClassifier {
Class<?>[] clazzez;
Map<Class<?>,ASTTypeBasedNodeClassifierConstraint> clazzConstraints;
List<IGroupMemberNode> unclassifiedNodes;
Map<Class<?>,List<IGroupMemberNode>> classifiedNodes;
/**
* Constructor, receiving as an argument a list of types based on
* which classification is done.
*
* @param types
*/
public ASTTypeBasedNodeClassifier(final Class<?>[] clazzez) {
this.clazzez = clazzez;
unclassifiedNodes = new LinkedList<IGroupMemberNode>();
classifiedNodes = new HashMap<Class<?>, List<IGroupMemberNode>>();
clazzConstraints = new HashMap<Class<?>,ASTTypeBasedNodeClassifierConstraint>();
}
/**
* Constructor, receiving as an argument a list of types based on
* which classification is done, and a list of nodes to be classified.
*
* @param types
*/
public ASTTypeBasedNodeClassifier(
final Class<?>[] clazzez, final List<IGroupMemberNode> nodeList) {
this(clazzez);
registerNodes(nodeList);
}
/**
* Register the set of nodes to the classifier, making them available for
* lookup.
*
* @param nodeList
*/
public void registerNodes(final Iterable<IGroupMemberNode> nodeList) {
// initialize map with empty arrays
for (Class<?> clazz : clazzez) {
classifiedNodes.put(clazz, new LinkedList<IGroupMemberNode>());
}
// and popuplate it
for (IGroupMemberNode node : nodeList) {
boolean classified = false;
for (int i=0; i<clazzez.length && !classified; i++) {
Class<?> clazz = clazzez[i];
if (clazz.isInstance(node)) {
final ASTTypeBasedNodeClassifierConstraint constraint =
clazzConstraints.get(clazz);
if (constraint==null || constraint.appliesTo(node)) {
classifiedNodes.get(clazz).add(node);
classified = true;
}
}
}
if (!classified) {
unclassifiedNodes.add(node);
}
}
}
/**
* Return all those nodes for which classification failed.
*/
public List<IGroupMemberNode> getUnclassifiedNodes() {
return unclassifiedNodes;
}
/**
* Returns the list of nodes that are classified with the given type.
* If the type was passed when constructing the object, the result
* is the (possibly empty) list of nodes with the given type. If the
* type was not provided, null is returned.
*/
@SuppressWarnings("unchecked")
public <T> List<T> get(Class<T> clazz) {
return (List<T>)(List<?>)classifiedNodes.get(clazz);
}
public void addConstraintForType(
final Class<?> clazz, final ASTTypeBasedNodeClassifierConstraint c) {
clazzConstraints.put(clazz, c);
}
}