blob: 383955b285eb81910ac5737d405d419fdbf02cf1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2011 Akos Horvath 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 - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.gtasm.interpreter.impl.rules;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.viatra2.core.IEntity;
import org.eclipse.viatra2.core.IModelElement;
import org.eclipse.viatra2.gtasm.interpreter.exception.ASMInterpreterErrorStrings;
import org.eclipse.viatra2.gtasm.interpreter.exception.ViatraTransformationException;
import org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment;
import org.eclipse.viatra2.gtasm.interpreter.impl.executionEnvironment.BlockRuleExecutionEnvironment;
import org.eclipse.viatra2.gtasm.interpreter.impl.machine.ASMInterpreterException;
import org.eclipse.viatra2.gtasm.interpreter.term.rules.TermEvaluator;
import org.eclipse.viatra2.gtasm.patternmatcher.ExecutionMode;
import org.eclipse.viatra2.gtasm.patternmatcher.IMatching;
import org.eclipse.viatra2.gtasm.patternmatcher.ParameterMode;
import org.eclipse.viatra2.gtasm.patternmatcher.PatternCallSignature;
import org.eclipse.viatra2.gtasm.patternmatcher.PatternMatcherParameters;
import org.eclipse.viatra2.gtasm.patternmatcher.Scope;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.compoundRules.BlockRule;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.compoundRules.CollectionIteratorRule;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.compoundRules.ForallRule;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.core.RuntimeAnnotation;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.core.RuntimeAnnotationElement;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.SymbolicRuleParameter;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Variable;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.DirectionKind;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ValueKind;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.GTRuleInvocation;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.GTPatternCall;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Term;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.VariableReference;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.ContainmentConstraint;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTRule;
import org.eclipse.viatra2.interpreters.IProgressReport;
/** Contains all the helper methods for the Block rule interpretation
* @author Akos Horvath
*
*/
public abstract class BlockRuleInterpreterHelper {
/** Returns the transformed scope constraints of a GT pattern or GT rule invocation
* @param executionEnvironment The execution environment on which the elements are evaluated
* @param containmentConstraints The constraints of the invocations
* @return The variable and the corresponding Scope in a HashMap
* @throws ViatraTransformationException
*/
static HashMap<Variable,Scope> getScopesFromContainmentConstraints(IExecutionEnvironment executionEnvironment
,CollectionIteratorRule rule) throws ViatraTransformationException
{
EList<ContainmentConstraint> containmentConstraints = rule.getContainmentConstraints();
HashMap<Variable,Scope> parameterScopes = new HashMap<Variable,Scope>();
for (Object cC: containmentConstraints) {
ContainmentConstraint containmentConstraint = (ContainmentConstraint) cC;
if(containmentConstraint.getParent()!=null)
{
Object constraintParent = TermEvaluator.getInstance().evaluate(executionEnvironment, containmentConstraint.getParent());
if(constraintParent instanceof IEntity)
{
parameterScopes .put((containmentConstraint).getVariable(),
new Scope( containmentConstraint.getMode().getValue(),
(IModelElement)(TermEvaluator.getInstance().evaluate(executionEnvironment, containmentConstraint.getParent() ))));
}
else
{
// Scope parent!= ENTITY, the element the scope references does not exist
String[] context = {containmentConstraint.getVariable().getName()};
ViatraTransformationException e = new ASMInterpreterException(ASMInterpreterErrorStrings.SCOPE_NOT_AN_ENTITY
,context
,containmentConstraint.getVariable());
throw e.addNewStackElement(rule);
}
}
else
parameterScopes .put(containmentConstraint.getVariable(), new Scope());
}
return parameterScopes;
}
/** Evaluates the do part of the GT Rule if it exists
* @param gtRule The GTRule invoked
* @param match The matching produced by the application of the GT rule
* @param blockRule the block rule representing the DO part
* @param blockRuleExecutionEnvironment the corresponding execution environment on which we the TERMS evaluated
* @param ruleInvocation the actual gtRule invocation
* @return true if it is successfully evaluated (or no DO part) else false
* @throws ViatraTransformationException
*/
static boolean evaulateDoPartofGTRuleInvocation(GTRule gtRule
, Object[] match
, BlockRule blockRule
, IExecutionEnvironment blockRuleExecutionEnvironment
, GTRuleInvocation ruleInvocation
, IProgressReport pr)
throws ViatraTransformationException
{
// the block rule does not have a do part
if(blockRule.getBody() == null)
return Boolean.TRUE;
GTRuleInvocation gtRuleInvocation = ((CollectionIteratorRule) blockRule).getGtrule();
for (int i=0;i<gtRule.getSymParameters().size();i++) {
//Only OUT and INOUT parameters have to be updated
if(!(gtRule.getSymParameters().get(i)).getDirection().equals(DirectionKind.IN_LITERAL) )
{
if(match[i].equals(ValueKind.UNDEF_LITERAL))
//have to check that it is not a quantified variable
{
Object ActualTerm = ruleInvocation.getActualParameters().get(i);
if(!(ActualTerm instanceof VariableReference
// the CollectionIterator rule's actual parameter
&& ((CollectionIteratorRule)blockRule).getLocalVariables().contains(((VariableReference)ActualTerm).getVariable())))
{
String[] context = {(gtRule.getSymParameters().get(i)).getName(), gtRule.getName()};
throw new ASMInterpreterException(ASMInterpreterErrorStrings.GTOUTPUT_IN_INOUT_NOT_BOUND
,context
,blockRule);
}
}
// else
// throw new ASMInterpreterException(((SymbolicRuleParameter)gtRule.getSymParameters().get(i)).getName()+ASMInterpreterErrorStrings.GTOUTPUT_IN_INOUT_NOT_BOUND+gtRule.getName(),blockRule);
// //have to check that an input parameter is not changed during the execution of the GTRule
// if(!match[i]
// .equals(
// blockRuleExecutionEnvironment.getTermEvaluator().evaluate(blockRuleExecutionEnvironment
// ,(Term)((CollectionIteratorRule)blockRule).getGtrule().getActualParameters().get(i))) )
// {
// ViatraTransformationException e = new ASMInterpreterException(ASMInterpreterErrorStrings.GTIN_OUTDIFFERENCE,(GTASMElement)chooseBlockRule.getGtrule().getActualParameters().get(i));
// e.addNewStackElement(blockRule);
// throw e;
// }
}
// else
//INOUT or OUT parameter has to be changed
// if(!((SymbolicRuleParameter)gtRule.getSymParameters().get(i)).getDirection().equals(DirectionKind.IN_LITERAL))
// {
try {
if(gtRuleInvocation.getActualParameters().get(i) instanceof VariableReference)
{
Variable variable = ((VariableReference)(gtRuleInvocation).getActualParameters().get(i)).getVariable();
blockRuleExecutionEnvironment.
setVariableValue(
variable,
match[i]);
}
} catch (ViatraTransformationException e) {
String n = "";
if(gtRuleInvocation.getActualParameters().get(i) instanceof VariableReference)
n = ((VariableReference)(gtRuleInvocation).getActualParameters().get(i)).getVariable().getName();
String[] context = {n,e.getMessage()};
throw new ASMInterpreterException(
blockRule instanceof ForallRule?ASMInterpreterErrorStrings.RULE_INIT_VAR_FORALL:ASMInterpreterErrorStrings.RULE_INIT_VAR_CHOOSE
,context
,blockRule);
}
// }
}
return RuleInterpreter.getInstance().interpretRule(blockRuleExecutionEnvironment,blockRule.getBody(),pr);
}
/** Returns the appropriate parameters for the GTRUleMatcher invocation.
* @param executionEnvironment The environment in which the terms will be evaluated
* @param ruleToBeInterpreted the Block rule containing the GT rule invocation
* @param parameterScopes Scope parameters for the quantified variables
* @param gtRule the invoked GT rule
* @param invocation the GT rule invocation rule
* @return
* @throws ViatraTransformationException
*/
static PatternMatcherParameters getGTRuleMatchParameters(IExecutionEnvironment executionEnvironment
, CollectionIteratorRule ruleToBeInterpreted
, Map<Variable,Scope> parameterScopes
, GTRule gtRule
, GTRuleInvocation invocation)
throws ViatraTransformationException
{
Object[] patternParams = new Object[invocation.getActualParameters().size()];
Integer[] quantificationOrder=new Integer[invocation.getActualParameters().size()];
PatternCallSignature[] patternCallSignatures=new PatternCallSignature[invocation.getActualParameters().size()];
// quantification order in case of forall rule
int outerVariableCounterForQuantificationOrder=(ruleToBeInterpreted).getLocalVariables().size();
int localVariableCounterForQuantificationOrder=0;
for (int i = 0 ; i< invocation.getActualParameters().size(); i++) {
Object ActualTerm = invocation.getActualParameters().get(i);
SymbolicRuleParameter symParam = gtRule.getSymParameters().get(i);
PatternCallSignature pcs=new PatternCallSignature();
// the value of the actual parameter
patternParams[i] = TermEvaluator.getInstance().evaluate(executionEnvironment , (Term)ActualTerm);
/************* Execution mode handling*********************/
if( ActualTerm instanceof VariableReference
// the CollectionIterator rule's actual parameter
&& (ruleToBeInterpreted).getLocalVariables().contains(((VariableReference)ActualTerm).getVariable()))
{
if( ruleToBeInterpreted instanceof ForallRule)
pcs.setExecutionMode(ExecutionMode.MULTIPLE_RESULTS);
else
pcs.setExecutionMode(ExecutionMode.SINGLE_RESULT);
// pcs.setParameterMode(ParameterMode.OUTPUT); //the variable is quantified by the BlockRule
// checks that the quantified variable is a parameter of the LHS, if not exception
boolean isQuantifiedVariableinLHS = false;
for(int j = 0; j< gtRule.getPrecondition().getActualParameters().size(); j++){
if(((VariableReference)gtRule.getPrecondition().getActualParameters().get(j)).getVariable().equals(symParam.getVariable()))
isQuantifiedVariableinLHS = true;
}
if(!isQuantifiedVariableinLHS)
{
String[] context = {((VariableReference)ActualTerm).getVariable().getName(),gtRule.getName()};
ViatraTransformationException e = new ASMInterpreterException(
ASMInterpreterErrorStrings.GTINPUT_QUANTIFIED_NOTIN_LHS
,context
,gtRule);
throw e.addNewStackElement(ruleToBeInterpreted);
}
}
else
{
pcs.setExecutionMode(ExecutionMode.SINGLE_RESULT);
}
/************* Input / Output parameter handling*********************/
if(symParam.getDirection().equals(DirectionKind.IN_LITERAL)) //INPUT
{ if((patternParams[i]==null
|| ValueKind.UNDEF_LITERAL.equals(patternParams[i])))
{
String[] context = {symParam.getVariable().getName(),gtRule.getName()};
ViatraTransformationException e = new ASMInterpreterException(ASMInterpreterErrorStrings.GTINPUT_IN
,context
,gtRule);
throw e.addNewStackElement(ruleToBeInterpreted);
}
else
pcs.setParameterMode(ParameterMode.INPUT);
}
else
if(symParam.getDirection().equals(DirectionKind.OUT_LITERAL)) //OUTPUT
{
if(ActualTerm instanceof VariableReference)
{ pcs.setParameterMode(ParameterMode.OUTPUT);
patternParams[i] = ValueKind.UNDEF_LITERAL;
}
else // an OUT parameter is not a Vairable -> throws exception as it is not allowed
{
String[] context = {symParam.getVariable().getName(),gtRule.getName()};
ViatraTransformationException e = new ASMInterpreterException(ASMInterpreterErrorStrings.GTINPUT_OUT
,context
,gtRule);
throw e.addNewStackElement(ruleToBeInterpreted);
}
//if((patternParams[i]==null
// || ValueKind.UNDEF_LITERAL.equals(patternParams[i])))
//else
// {
//if(pcs.getParameterMode() == null) // Its is a quantificated variable if paramterMode != null
// {
//log.warning(symParam.getName()+" is an OUTPUT parameter but has a value at the invocation of the ");
//GTASMException e = new ASMInterpreterException(symParam.getVariable().getName()+ASMInterpreterErrorStrings.GTINPUT_OUT+gtRule.getName()+" gt rule.",gtRule);
//throw e.addNewStackElement(ruleToBeInterpreted);
// }
// }
}
else
//if(symParam.getDirection().equals(DirectionKind.INOUT_LITERAL)) //INOUT
{
// in and inout parameter has to have an input value!
if((patternParams[i]==null
|| ValueKind.UNDEF_LITERAL.equals(patternParams[i])))
{
String[] context = {symParam.getVariable().getName(),gtRule.getName()};
ViatraTransformationException e = new ASMInterpreterException(ASMInterpreterErrorStrings.GTINPUT_IN
,context
,gtRule);
throw e.addNewStackElement(ruleToBeInterpreted);
}
else
pcs.setParameterMode(ParameterMode.INPUT);
}
/************* Scope of the parameters handling*********************/
if(ActualTerm instanceof VariableReference) // variable type element can be in the scope order
{
if(parameterScopes.containsKey(((VariableReference)ActualTerm).getVariable()))
pcs.setParameterScope(parameterScopes.get(((VariableReference)ActualTerm).getVariable()));
else
pcs.setParameterScope(new Scope());
}
else //node varibaleReference type input parameter
{
pcs.setParameterScope(new Scope());
}
/************* Quantification order in case of forall rule*********************/
if(ruleToBeInterpreted instanceof ForallRule)
if(ActualTerm instanceof VariableReference)
{
if(((ruleToBeInterpreted).getLocalVariables().indexOf(((VariableReference)ActualTerm).getVariable()))==-1)
{
// an error occured, there is a variable which is quanitified by the BlockRule but not used in the GT rule
if(invocation.getActualParameters().size() == outerVariableCounterForQuantificationOrder)
getNoneUsedVariable(ruleToBeInterpreted);
quantificationOrder[outerVariableCounterForQuantificationOrder]=i;
outerVariableCounterForQuantificationOrder++;
}
else
{
quantificationOrder[((ruleToBeInterpreted).getLocalVariables().indexOf(((VariableReference)ActualTerm).getVariable()))]= i;
localVariableCounterForQuantificationOrder++;
}
}
else
{
//error a variable is not quantified varibale
if(invocation.getActualParameters().size() == outerVariableCounterForQuantificationOrder)
getNoneUsedVariable(ruleToBeInterpreted);
quantificationOrder[outerVariableCounterForQuantificationOrder]=i;
outerVariableCounterForQuantificationOrder++;
}
// the signature is assigned to the array
patternCallSignatures[i]=pcs;
}
return new PatternMatcherParameters(patternCallSignatures,patternParams,quantificationOrder);
}
/** Evaluates which parameter is quantified but not used in the (GT rule or pattern) invocation
* @param ruleToBeInterpreted the Block rule which invokes the Pattern or GT rule
* @throws ViatraTransformationException
*/
static void getNoneUsedVariable(CollectionIteratorRule ruleToBeInterpreted)
throws ViatraTransformationException{
//Called from a gtPattern or a gtRule
String name = (ruleToBeInterpreted).getCondition() instanceof GTPatternCall?
((GTPatternCall)(ruleToBeInterpreted).getCondition()).getCalledPattern().getName()+ " pattern"
:(ruleToBeInterpreted).getGtrule().getRule().getName() + " GT Rule";
EList<Term> actualParamater = (ruleToBeInterpreted).getCondition() instanceof GTPatternCall?
((GTPatternCall)(ruleToBeInterpreted).getCondition()).getActualParameters()
:(ruleToBeInterpreted).getGtrule().getActualParameters();
for(int j=0; j< ruleToBeInterpreted.getLocalVariables().size(); j++)
{// search for the errorfull variable
Variable locVar = ruleToBeInterpreted.getLocalVariables().get(j);
boolean usedInRule = false;
for(int k = 0; k < actualParamater.size(); k++)
{//if it is used in the gtRule then the usedInRule is set to true
if(actualParamater.get(k) instanceof VariableReference
&& ((VariableReference)actualParamater.get(k)).getVariable().equals(locVar))
usedInRule = true;
}
if(!usedInRule) //we have the errorful variable
{
String[] context = {locVar.getName(),name };
throw new ASMInterpreterException(ASMInterpreterErrorStrings.BLOCKRULE_PARAMS_NOT_USED
,context
,ruleToBeInterpreted);
}
}
String[] context = {name};
throw new ASMInterpreterException(ASMInterpreterErrorStrings.FATAL_ERROR
,context
,ruleToBeInterpreted);
}
/** Returns the appropriate parameters for the PatternMatcher invocation
* @param executionEnvironment the execution environment of the invocation context
* @param ruleToBeInterpreted the choose/forall rule that is invoked
* @param parameterScopes the scope of the parameters
* @return the parameters of the rule
* @throws ViatraTransformationException
*/
static PatternMatcherParameters getMatchParameters(IExecutionEnvironment executionEnvironment
, CollectionIteratorRule ruleToBeInterpreted
, Map<Variable,Scope> parameterScopes)
throws ViatraTransformationException
{
CollectionIteratorRule iteratorBlockRule = (ruleToBeInterpreted);
int paramSize = ((GTPatternCall)iteratorBlockRule.getCondition()).getActualParameters().size();
//a quantified variable is not used
if(paramSize < iteratorBlockRule.getLocalVariables().size())
getNoneUsedVariable(ruleToBeInterpreted);
Object[] patternParams = new Object[paramSize];
Integer[] quantificationOrder=new Integer[paramSize];
PatternCallSignature[] patternCallSignatures=new PatternCallSignature[paramSize];
int outerVariableCounterForQuantificationOrder=iteratorBlockRule.getLocalVariables().size();
int localVariableCounterForQuantificationOrder=0;
//for (Object term : ((GTPatternCall)((CollectionIteratorRule)ruleToBeInterpreted).getCondition()).getActualParameters()) {
for (int i = 0 ; i< paramSize; i++) {
Object ActualTerm = ((GTPatternCall)iteratorBlockRule.getCondition()).getActualParameters().get(i);
PatternCallSignature pcs=new PatternCallSignature();
patternParams[i] = TermEvaluator.getInstance().evaluate(executionEnvironment , (Term)ActualTerm);
/************* Execution mode handling*********************/
if((Term)ActualTerm instanceof VariableReference
&& ruleToBeInterpreted instanceof ForallRule
&& iteratorBlockRule.getLocalVariables().contains(((VariableReference)ActualTerm).getVariable()))
pcs.setExecutionMode(ExecutionMode.MULTIPLE_RESULTS);
else
pcs.setExecutionMode(ExecutionMode.SINGLE_RESULT);
/************* Input / Output parameter handling*********************/
if(patternParams[i]==null||ValueKind.UNDEF_LITERAL.equals(patternParams[i]))
{
if((Term)ActualTerm instanceof VariableReference
&& iteratorBlockRule.getLocalVariables().contains(((VariableReference)ActualTerm).getVariable()))
pcs.setParameterMode(ParameterMode.OUTPUT);
else
{
String[] context = {""+i};
throw new ASMInterpreterException(ASMInterpreterErrorStrings.BLOCKRULE_PARAM_NOT_QUANTIFIED
,context
,iteratorBlockRule);
}
}
else
pcs.setParameterMode(ParameterMode.INPUT);
/************* Scope of the parameters handling*********************/
if(ActualTerm instanceof VariableReference)
{ Variable variable = ((VariableReference)ActualTerm).getVariable();
if(parameterScopes.containsKey(variable))
pcs.setParameterScope(parameterScopes.get(variable));
else
pcs.setParameterScope(new Scope());
}
else
{
pcs.setParameterScope(new Scope());
}
patternCallSignatures[i]=pcs;
/************* Quantification order in case of forall rule*********************/
if(ruleToBeInterpreted instanceof ForallRule)
if(ActualTerm instanceof VariableReference)
{ Variable variable = ((VariableReference)ActualTerm).getVariable();
//is it a variable which is quantified
if(iteratorBlockRule.getLocalVariables().indexOf(variable)==-1)
{
//an error occured, there is a variable which is quanitificated by the BlockRule but not used in the GT pattern. Throws ViatraTransformationException
if(paramSize == outerVariableCounterForQuantificationOrder)
getNoneUsedVariable(ruleToBeInterpreted);
quantificationOrder[outerVariableCounterForQuantificationOrder]=i;
outerVariableCounterForQuantificationOrder++;
}
else
{
quantificationOrder[iteratorBlockRule .getLocalVariables().indexOf(variable)]= i;
localVariableCounterForQuantificationOrder++;
}
}
else
{
quantificationOrder[outerVariableCounterForQuantificationOrder]=i;
outerVariableCounterForQuantificationOrder++;
}
}// end of for cycle
return new PatternMatcherParameters(patternCallSignatures,patternParams,quantificationOrder);
}
/** Creates a new execution environment for a CollectionIterator rule
* @param executionEnvironment the parent execution environment
* @param ruleToBeInterpreted the CollectionIterator rule
* @return new execution environment, where parent = executionEnviroment
*/
static BlockRuleExecutionEnvironment getNewExecutionEnvironment(IExecutionEnvironment executionEnvironment,CollectionIteratorRule ruleToBeInterpreted)
{
// Needs a new Exec.env. for the new Variables.
BlockRuleExecutionEnvironment forallRuleExecutionEnvironment =
new BlockRuleExecutionEnvironment(executionEnvironment.getFramework(),ruleToBeInterpreted.getBody());
Map<Variable, Object> variables = new Hashtable<Variable, Object>(executionEnvironment.getVariableValues());
for (Object variable : ruleToBeInterpreted.getLocalVariables()) {
variables.put((Variable)variable, ValueKind.UNDEF_LITERAL);
}
forallRuleExecutionEnvironment.onBegin(variables);
return forallRuleExecutionEnvironment;
}
/**
* Reorders the matches of the pattern according to the ordering settings, if specified.
*
* @param gtPattern the pattern that was matched
* @param matches the already retrieved matches of the pattern
* @return the reordered matches, or the original collection if no ordering was specified
*/
@SuppressWarnings("unchecked")
static Collection<IMatching> reorder(GTPattern gtPattern, Collection<IMatching> matches) {
// is ordering required?
Integer orderColoumn = null;
boolean orderDesc = false;
String orderType = "string";
for (Object annot : gtPattern.getRuntimeAnnotations()) {
RuntimeAnnotation annot2 = (RuntimeAnnotation) annot;
if ("@orderby".equals(annot2.getAnnotationName().toLowerCase())) {
for (Object oRel: annot2.getElements()) {
RuntimeAnnotationElement rel = (RuntimeAnnotationElement)oRel;
if ("col".equals(rel.getKey().toLowerCase())) {
try {
orderColoumn = Integer.parseInt(rel.getValue());
} catch (NumberFormatException ex) {
//throw new ASMInterpreterException("", , forallGTPatternCall);
}
}
else if ("order".equals(rel.getKey().toLowerCase()) && "desc".equals(rel.getValue().toLowerCase()))
orderDesc = true;
else if ("type".equals(rel.getKey().toLowerCase()))
orderType = rel.getValue().toLowerCase();
}
break;
}
}
// if yes, do the ordering
if (orderColoumn !=null)
{
final boolean desc = orderDesc;
final Map<IMatching, Comparable> keys = new HashMap<IMatching, Comparable>();
for (IMatching match : matches) {
Object col = match.lookup(orderColoumn);
Comparable key = null;
if (col!=null) {
if (col instanceof IEntity) {
if ("name".equals(orderType)) key = ((IModelElement)col).getName();
else if ("name-nocase".equals(orderType)) key = ((IModelElement)col).getName().toLowerCase();
else if ("fqn".equals(orderType)) key = ((IModelElement)col).getFullyQualifiedName();
else if ("fqn-nocase".equals(orderType)) key = ((IModelElement)col).getFullyQualifiedName().toLowerCase();
else {
String value = ((IEntity)col).getValue();
if ("double".equals(orderType)) key = Double.parseDouble(value);
else if ("integer".equals(orderType)) key = Integer.parseInt(value);
else if ("nocase".equals(orderType)) key = value.toLowerCase();
else if ("value-nocase".equals(orderType)) key = value.toLowerCase();
else key = value;
}
} else if (col instanceof Comparable)
key = (Comparable) col;
else key = col.toString();
}
keys.put(match, key);
}
ArrayList<IMatching> matchList = new ArrayList<IMatching>(matches);
Collections.sort(matchList, new Comparator<IMatching>() {
@Override
public int compare(IMatching o1, IMatching o2) {
int compareResult = keys.get(o1).compareTo(keys.get(o2));
return desc ? -compareResult : compareResult;
}
});
matches = matchList;
}
return matches;
}
}