/**
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 18, 2015
*/
package com.bigdata.rdf.sparql.ast.optimizers;
import java.util.LinkedList;
import java.util.List;
import com.bigdata.rdf.sparql.ast.ArbitraryLengthPathNode;
import com.bigdata.rdf.sparql.ast.GraphPatternGroup;
import com.bigdata.rdf.sparql.ast.IGroupMemberNode;
import com.bigdata.rdf.sparql.ast.NamedSubqueryInclude;
import com.bigdata.rdf.sparql.ast.PropertyPathUnionNode;
import com.bigdata.rdf.sparql.ast.StatementPatternNode;
import com.bigdata.rdf.sparql.ast.SubqueryRoot;
import com.bigdata.rdf.sparql.ast.ZeroLengthPathNode;
import com.bigdata.rdf.sparql.ast.service.ServiceNode;
/**
* Reorders nodes based on their types.
*
* The heuristics is as follows:
*
* 1. Named subquery includes (given that subqueries are typically used to enforce order)
* 2. Statement patterns
* 3. Subgroups
* 4. ALP nodes
* 5. Subqueries
* 6. SERVICE calls
* 7. OTHER
*/
@SuppressWarnings("deprecation")
public class TypeBasedASTJoinGroupPartitionReorderer
implements IASTJoinGroupPartitionReorderer {
/**
* Reorders the given partition in a semantics-preserving way.
*/
@Override
public void reorderNodes(ASTJoinGroupPartition partition) {
final ASTTypeBasedNodeClassifier nodeClassifier =
new ASTTypeBasedNodeClassifier(
new Class<?>[]{
NamedSubqueryInclude.class,
StatementPatternNode.class,
ZeroLengthPathNode.class,
PropertyPathUnionNode.class,
ArbitraryLengthPathNode.class,
SubqueryRoot.class,
ServiceNode.class,
GraphPatternGroup.class
},
partition.nonOptionalNonMinusNodes);
// split service nodes into runFirst and runLast service nodes
final List<ServiceNode> runFirstSNs = new LinkedList<ServiceNode>();
final List<ServiceNode> runLastSNs = new LinkedList<ServiceNode>();
for (ServiceNode sn : nodeClassifier.get(ServiceNode.class)) {
if (sn.getResponsibleServiceFactory().getServiceOptions().isRunFirst()) {
runFirstSNs.add(sn);
} else {
runLastSNs.add(sn);
}
}
// order the nodes based on their types
final List<IGroupMemberNode> ordered = new LinkedList<IGroupMemberNode>();
ordered.addAll(runFirstSNs);
ordered.addAll(nodeClassifier.get(NamedSubqueryInclude.class));
ordered.addAll(nodeClassifier.get(StatementPatternNode.class));
ordered.addAll(nodeClassifier.get(GraphPatternGroup.class));
ordered.addAll(nodeClassifier.get(ZeroLengthPathNode.class));
ordered.addAll(nodeClassifier.get(PropertyPathUnionNode.class));
ordered.addAll(nodeClassifier.get(ArbitraryLengthPathNode.class));
ordered.addAll(nodeClassifier.get(SubqueryRoot.class));
ordered.addAll(runLastSNs);
ordered.addAll(nodeClassifier.getUnclassifiedNodes());
// just replace the order in the partition
partition.replaceNonOptionalNonMinusNodesWith(ordered, false);
}
}