blob: 2ea0a3ada30b4de3c9089c078ead9614496e6039 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2008 Akos Horvath, Gergely Varro and Daniel Varro
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Akos Horvath, Gergely Varro - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.algorithms;
import java.util.Vector;
import org.eclipse.viatra2.core.IModelElement;
import org.eclipse.viatra2.core.IModelManager;
import org.eclipse.viatra2.gtasm.patternmatcher.exceptions.PatternMatcherRuntimeException;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.EdgeType;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.MatchingFrame;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.PatternMatcherErrorStrings;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.AllEntitiesOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.AllRelationsOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.BoundToBoundCheckOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.BoundToConstantCheckOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.ConstantToBoundCheckOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.ConstantToConstantCheckOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.CopyValueOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.ExtendBoundNodeOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.ExtendConstantNodeOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.IsEntityorRelationCheckOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.PatternCallOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.SearchPlanOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.operation.VariableAssignmentCheckOperation;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.searchgraph.ConstantSearchGraphNode;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.searchgraph.PatternCallSearchGraphNode;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.searchgraph.SearchGraphEdge;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.searchgraph.SearchGraphNode;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.searchgraph.VariableSearchGraphNode;
/**Generates the operations base on the search plan.
* @author Akos Horvath
*
*/
public class VPMPatternOperationGenerator {
public static Vector<SearchPlanOperation> evaluateVPMOperationPlan(SearchGraphNode[] searchPlan,
MatchingFrame template,
IModelManager manager) throws PatternMatcherRuntimeException{
Vector<SearchPlanOperation> searchOperations = new Vector<SearchPlanOperation>();
SearchPlanOperation operation = null;
for(SearchGraphNode node : searchPlan){
if(node instanceof ConstantSearchGraphNode)
node.setChecked(true);
//tree edge evaluation
if(node.getTreeEdge() != null && (!node.isChecked()))
{operation = VPMPatternOperationGenerator.treeEdgeSearchOperation(node.getTreeEdge(), template,manager);
if(operation!= null)
{ //operation.debug();
searchOperations.add(operation);
}
}
//check operation evaluation
for(SearchGraphEdge edge : node.getSources()){
if(edge.getSourceNode().isChecked() && edge.getTargetNode().isChecked())
{operation = VPMPatternOperationGenerator.evaluateEdgeSearchPlanOperation(edge, template,manager);
if(operation != null)
{//operation.debug();
searchOperations.add(operation);
}
}
}
}
// have to check if there are any edges left
for(SearchGraphNode node : searchPlan)
for(SearchGraphEdge edge : node.getSources())
if(!edge.isChecked())
{
//oldVersion operation = checkSearchOperation(edge, template);
operation= VPMPatternOperationGenerator.evaluateEdgeSearchPlanOperation(edge,template,manager);
//operation.debug();
if(operation != null)
searchOperations.add(operation);
//searchOperations.add(checkSearchOperation(edge));
}
return searchOperations;
}
/** Returns the corresponding search plan operation equivalent to the input search graph edge
* @param edge The edge to process
* @param template the Matching frame with the bound variables
* @param manager Model manager of the actual model space
* @return the generated operation
*/
public static SearchPlanOperation evaluateEdgeSearchPlanOperation(
SearchGraphEdge edge,
MatchingFrame template,
IModelManager manager) throws PatternMatcherRuntimeException
{SearchPlanOperation operation = null;
if(edge.isChecked()) return null;
//checking the type of the edge, for debugging
if(edge.getVPMEdgeType() == EdgeType.BELOW
|| edge.getVPMEdgeType() == EdgeType.IN
|| edge.getVPMEdgeType() == EdgeType.INSTANCEOF
|| edge.getVPMEdgeType() == EdgeType.SOURCE
|| edge.getVPMEdgeType() == EdgeType.TARGET
|| edge.getVPMEdgeType() == EdgeType.SUPERTYPEOF
|| edge.getVPMEdgeType() == EdgeType.PATTERN_CALL_PARAMETER
|| edge.getVPMEdgeType() == EdgeType.VARIABLE_ASSIGNMENT) //TODO: new edge types has to be added to this check
{
operation = checkSearchOperation(edge, template,manager);
}
else
{
String[] context = {edge.getVPMEdgeType().toString(), edge.getName()};
throw new PatternMatcherRuntimeException(PatternMatcherErrorStrings.INTERNAL_EDGETYPE_NOT_SUPPORTED
,context
,template.getPattern().getGTASMRepresentation(edge));
}
return operation;
}
/** Returns the corresponding search plan operation equivalent of the input search graph edge (CHECK OPERATIONS)
* @param edge The edge whose operation is generated
* @param template template the Matching frame with the bound variables
* @param manager model manager
* @return the operation itself
*/
private static SearchPlanOperation checkSearchOperation(
SearchGraphEdge edge,
MatchingFrame template,
IModelManager manager)
throws PatternMatcherRuntimeException{
SearchPlanOperation operation = null;
//some of the check operations have to be skipped as they does not represent any additional constraints
if( edge.getSourceNode() instanceof VariableSearchGraphNode
&& edge.getVPMEdgeType().equals(EdgeType.BELOW) //default Scope value
&& (template.getValue(((VariableSearchGraphNode)edge.getSourceNode()).getId()) != null) //default Scope value
&& ((IModelElement)template.getValue(((VariableSearchGraphNode)edge.getSourceNode()).getId())).equals(manager.getRoot()))
{
edge.setChecked(true);
return null;
}
// in case the source is an entity or a relation a special check operation is required
if( edge.getSourceNode() instanceof ConstantSearchGraphNode
&& edge.getVPMEdgeType().equals(EdgeType.INSTANCEOF)
&& ( ((ConstantSearchGraphNode)edge.getSourceNode()).getElement().equals(ISearchGraph.VPM_RELATION_FQN)
|| ((ConstantSearchGraphNode)edge.getSourceNode()).getElement().equals(ISearchGraph.VPM_ENTITY_FQN) ))
{
//TODO: Can an entity have an instance relation to an entity?
//If yes, then can be tricked out as an entity can have an instance relation to a relation and it is not checked
operation = new IsEntityorRelationCheckOperation(((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge,
((ConstantSearchGraphNode)edge.getSourceNode()).getElement());
edge.setChecked(true);
return operation;
}
/************complex operations******************/
//pattern call operation
if(edge.getTargetNode() instanceof PatternCallSearchGraphNode)
{
String[] context = {edge.getTargetNode().getName()};
throw new PatternMatcherRuntimeException(
PatternMatcherErrorStrings.INTERNAL_PATTERNCALLNODE_EXCEPTION
,context
,template.getPattern().getGTASMRepresentation(edge));
}
/**************simple operations*******************/
if(edge.getVPMEdgeType().equals(EdgeType.VARIABLE_ASSIGNMENT))
operation = new VariableAssignmentCheckOperation(((VariableSearchGraphNode)edge.getSourceNode()).getId(),
((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge); //TODO: does the direction counts? (inverse or not)
else
if(edge.getSourceNode() instanceof VariableSearchGraphNode && edge.getTargetNode() instanceof VariableSearchGraphNode)
operation = new BoundToBoundCheckOperation(((VariableSearchGraphNode)edge.getSourceNode()).getId()
,((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge);
else
if(edge.getSourceNode() instanceof VariableSearchGraphNode && edge.getTargetNode() instanceof ConstantSearchGraphNode )
operation = new BoundToConstantCheckOperation(((VariableSearchGraphNode)edge.getSourceNode()).getId()
,manager.getElementByName(((ConstantSearchGraphNode)edge.getTargetNode()).getElement())
,edge);
else
if(edge.getSourceNode() instanceof ConstantSearchGraphNode && edge.getTargetNode() instanceof VariableSearchGraphNode)
operation = new ConstantToBoundCheckOperation(manager.getElementByName(((ConstantSearchGraphNode)edge.getSourceNode()).getElement())
,((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge);
else
if(edge.getSourceNode() instanceof ConstantSearchGraphNode && edge.getTargetNode() instanceof ConstantSearchGraphNode)
operation = new ConstantToConstantCheckOperation(manager.getElementByName(((ConstantSearchGraphNode)edge.getSourceNode()).getElement())
,manager.getElementByName(((ConstantSearchGraphNode)edge.getTargetNode()).getElement())
,edge);
if(operation != null)
edge.setChecked(true);
return operation;
}
private static int getPatternCallParameterId(Integer id,
PatternCallSearchGraphNode callNode, MatchingFrame frame
) throws PatternMatcherRuntimeException {
Integer[] inputParameterMapping = callNode.getInputParameterMapping();
for(int i =0; i< inputParameterMapping.length; i++)
if(id == inputParameterMapping[i])
return i;
String[] context = {callNode.getName()};
throw new PatternMatcherRuntimeException(
PatternMatcherErrorStrings.INTERNAL_PATTERNCALLNODE_WRONGPARAMETER_ORDER
,context
,frame.getPattern().getGTASMRepresentation(callNode));
}
/** Returns the corresponding search plan operation equivalent of the input search graph TREE edge (EXTEND OPERATIONS)
* @param edge
* @param Matchingframe containing the bound variables
* @param manager model manager
* @return
*/
public static SearchPlanOperation treeEdgeSearchOperation(SearchGraphEdge edge, MatchingFrame template, IModelManager manager) throws PatternMatcherRuntimeException{
SearchPlanOperation operation = null;
if(edge.getSourceNode().isChecked() && edge.getTargetNode().isChecked())
//the source and the target are already checked, simple checks the edge
operation = checkSearchOperation(edge, template,manager);
else//not a check type operation
/**********complex operations**********/
if(edge.getVPMEdgeType().equals(EdgeType.PATTERN_CALL_PARAMETER)
|| edge.getVPMEdgeType().equals(EdgeType.PATTERN_CALL_STORAGE))
{
if(edge.isSource()) //the edge is the tree edge of the pattern call node
{
PatternCallSearchGraphNode callNode = (PatternCallSearchGraphNode) edge.getTargetNode();
Boolean[] boundParameters = new Boolean[callNode.getPatternNode().getPattern().getSymParameters().size()];
for (SearchGraphEdge callEdge:callNode.getSources())
{
//[DEBUG] error in the algorithm, one edge of the PatternCall node is already checked
//if(!callEdge.isChecked())
// System.out.println("[ERROR] One edge of a PatternCallNode is already traversed before the PatternNode was traversed");
//if it is a bound input parameter
if(callEdge.getVPMEdgeType().equals(EdgeType.PATTERN_CALL_PARAMETER))
{ if(callEdge.getSourceNode().isChecked())
{
boundParameters[getPatternCallParameterId(((VariableSearchGraphNode)callEdge.getSourceNode()).getId()
,callNode,template)] = true;
}
else//the pattern call will bound the variable
{ if(callEdge.getSourceNode().getTreeEdge().getSourceNode().equals(callNode))
{
boundParameters[getPatternCallParameterId(((VariableSearchGraphNode)callEdge.getSourceNode()).getId()
,callNode,template)] = false;
callEdge.getSourceNode().setChecked(true);
}
else//Error the recursive call is not the tree edge for an unbound parameter
{
String[] context = {callEdge.getSourceNode().getName(),callNode.getName()};
throw new PatternMatcherRuntimeException(
PatternMatcherErrorStrings.INTERNAL_PATTERNCALLNODE_EDGE_EXCEPTION
,context
,template.getPattern().getGTASMRepresentation(callNode));
}
}
}
//else // it is an incrementally matched pattern call -> not part of the invocation context
callEdge.setChecked(true);
}
return //PatternCallOperation patternOperation =
new PatternCallOperation(callNode.getPatternNode()
,callNode.getInputParameterMapping(),boundParameters);
}
else//the edge is an outgoing edge from a pattern call node
{
//edge.getTargetNode().setChecked(true);
PatternCallSearchGraphNode callNode = (PatternCallSearchGraphNode) edge.getSourceNode();
String[] context = {edge.getName(),callNode.getName()};
throw new PatternMatcherRuntimeException(
PatternMatcherErrorStrings.INTERNAL_PATTERNCALLNODE_EDGE_TRAVERSAL_EXCEPTION
,context
,template.getPattern().getGTASMRepresentation(callNode));
}
}
/**************simple operations ******************/
else
if(edge.getSourceNode().isChecked())
{
//simple operation
if(edge.getVPMEdgeType().equals(EdgeType.VARIABLE_ASSIGNMENT))
{operation = new CopyValueOperation(((VariableSearchGraphNode)edge.getSourceNode()).getId()
,((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge);
}
else
if(edge.getSourceNode() instanceof ConstantSearchGraphNode &&
((ConstantSearchGraphNode)edge.getSourceNode()).getElement().equals(ISearchGraph.VPM_ENTITY_FQN))
{
operation = new AllEntitiesOperation(((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge, manager);
}
else
if(edge.getSourceNode() instanceof ConstantSearchGraphNode &&
((ConstantSearchGraphNode)edge.getSourceNode()).getElement().equals(ISearchGraph.VPM_RELATION_FQN))
{
operation = new AllRelationsOperation(((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge, manager);
}
else
if(edge.getSourceNode() instanceof VariableSearchGraphNode && edge.getTargetNode() instanceof VariableSearchGraphNode)
{operation = new ExtendBoundNodeOperation(((VariableSearchGraphNode)edge.getSourceNode()).getId()
,((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge);
}
else
if(edge.getSourceNode() instanceof ConstantSearchGraphNode && edge.getTargetNode() instanceof VariableSearchGraphNode)
{operation = new ExtendConstantNodeOperation(manager.getElementByName(((ConstantSearchGraphNode)edge.getSourceNode()).getElement())
,((VariableSearchGraphNode)edge.getTargetNode()).getId()
,edge);
}
}
else
if(edge.getTargetNode().isChecked())
{
//simple operation
if(edge.getVPMEdgeType().equals(EdgeType.VARIABLE_ASSIGNMENT))
{operation = new CopyValueOperation(((VariableSearchGraphNode)edge.getTargetNode()).getId()
,((VariableSearchGraphNode)edge.getSourceNode()).getId()
,edge);
}
if(edge.getTargetNode() instanceof ConstantSearchGraphNode &&
((ConstantSearchGraphNode)edge.getTargetNode()).getElement().equals(ISearchGraph.VPM_ENTITY_FQN))
{
operation = new AllEntitiesOperation(((VariableSearchGraphNode)edge.getSourceNode()).getId()
,edge, manager);
}
else
if(edge.getTargetNode() instanceof ConstantSearchGraphNode &&
((ConstantSearchGraphNode)edge.getTargetNode()).getElement().equals(ISearchGraph.VPM_RELATION_FQN))
{
operation = new AllRelationsOperation(((VariableSearchGraphNode)edge.getSourceNode()).getId()
,edge, manager);
}
else
if(edge.getSourceNode() instanceof VariableSearchGraphNode && edge.getTargetNode() instanceof VariableSearchGraphNode)
{operation = new ExtendBoundNodeOperation(((VariableSearchGraphNode)edge.getTargetNode()).getId()
,((VariableSearchGraphNode)edge.getSourceNode()).getId()
,edge);
}
else
if(edge.getSourceNode() instanceof ConstantSearchGraphNode && edge.getTargetNode() instanceof VariableSearchGraphNode)
{operation = new ExtendConstantNodeOperation(manager.getElementByName(((ConstantSearchGraphNode)edge.getTargetNode()).getElement())
,((VariableSearchGraphNode)edge.getSourceNode()).getId()
,edge);
}
}
if(operation != null)
{
edge.getSourceNode().setChecked(true);
edge.getTargetNode().setChecked(true);
edge.setChecked(true);
}
return operation;
}
}