package org.ggp.base.util.gdl.transforms;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.ggp.base.util.gdl.grammar.Gdl;
import org.ggp.base.util.gdl.grammar.GdlConstant;
import org.ggp.base.util.gdl.grammar.GdlDistinct;
import org.ggp.base.util.gdl.grammar.GdlFunction;
import org.ggp.base.util.gdl.grammar.GdlLiteral;
import org.ggp.base.util.gdl.grammar.GdlNot;
import org.ggp.base.util.gdl.grammar.GdlOr;
import org.ggp.base.util.gdl.grammar.GdlPool;
import org.ggp.base.util.gdl.grammar.GdlProposition;
import org.ggp.base.util.gdl.grammar.GdlRelation;
import org.ggp.base.util.gdl.grammar.GdlRule;
import org.ggp.base.util.gdl.grammar.GdlSentence;
import org.ggp.base.util.gdl.grammar.GdlTerm;
import org.ggp.base.util.gdl.grammar.GdlVariable;
import com.google.common.collect.Lists;
/**
* @author Sam Schreiber
*/
public class CommonTransforms {
//We can avoid lots of client-side casts by providing these functions for the more specific cases -AL
public static GdlRule replaceVariable(GdlRule rule, GdlVariable toSubstitute, GdlTerm theReplacement) {
return (GdlRule) replaceVariableInternal(rule, toSubstitute, theReplacement);
}
public static GdlLiteral replaceVariable(GdlLiteral literal, GdlVariable toSubstitute, GdlTerm theReplacement) {
return (GdlLiteral) replaceVariableInternal(literal, toSubstitute, theReplacement);
}
public static GdlSentence replaceVariable(GdlSentence sentence, GdlVariable toSubstitute, GdlTerm theReplacement) {
return (GdlSentence) replaceVariableInternal(sentence, toSubstitute, theReplacement);
}
private static Gdl replaceVariableInternal(Gdl gdl, GdlVariable toSubstitute, GdlTerm theReplacement) {
if(gdl instanceof GdlDistinct) {
return GdlPool.getDistinct((GdlTerm) replaceVariableInternal(((GdlDistinct) gdl).getArg1(), toSubstitute, theReplacement), (GdlTerm) replaceVariableInternal(((GdlDistinct) gdl).getArg2(), toSubstitute, theReplacement));
} else if(gdl instanceof GdlNot) {
return GdlPool.getNot((GdlLiteral) replaceVariableInternal(((GdlNot) gdl).getBody(), toSubstitute, theReplacement));
} else if(gdl instanceof GdlOr) {
GdlOr or = (GdlOr)gdl;
List<GdlLiteral> rval = new ArrayList<GdlLiteral>();
for(int i=0; i<or.arity(); i++)
{
rval.add((GdlLiteral) replaceVariableInternal(or.get(i), toSubstitute, theReplacement));
}
return GdlPool.getOr(rval);
} else if(gdl instanceof GdlProposition) {
return gdl;
} else if(gdl instanceof GdlRelation) {
GdlRelation rel = (GdlRelation)gdl;
List<GdlTerm> rval = new ArrayList<GdlTerm>();
for(int i=0; i<rel.arity(); i++)
{
rval.add((GdlTerm) replaceVariableInternal(rel.get(i), toSubstitute, theReplacement));
}
return GdlPool.getRelation(rel.getName(), rval);
} else if(gdl instanceof GdlRule) {
GdlRule rule = (GdlRule)gdl;
List<GdlLiteral> rval = new ArrayList<GdlLiteral>();
for(int i=0; i<rule.arity(); i++)
{
rval.add((GdlLiteral) replaceVariableInternal(rule.get(i), toSubstitute, theReplacement));
}
return GdlPool.getRule((GdlSentence) replaceVariableInternal(rule.getHead(), toSubstitute, theReplacement), rval);
} else if(gdl instanceof GdlConstant) {
return gdl;
} else if(gdl instanceof GdlFunction) {
GdlFunction func = (GdlFunction)gdl;
List<GdlTerm> rval = new ArrayList<GdlTerm>();
for(int i=0; i<func.arity(); i++)
{
rval.add((GdlTerm) replaceVariableInternal(func.get(i), toSubstitute, theReplacement));
}
return GdlPool.getFunction(func.getName(), rval);
} else if(gdl instanceof GdlVariable) {
if(gdl == toSubstitute) {
return theReplacement;
} else {
return gdl;
}
} else {
throw new RuntimeException("Uh oh, gdl hierarchy must have been extended without updating this code.");
}
}
//Apply a variable assignment to a Gdl object
public static GdlSentence replaceVariables(GdlSentence sentence,
Map<GdlVariable, ? extends GdlTerm> assignment) {
return (GdlSentence) replaceVariablesInternal(sentence, assignment);
}
public static GdlTerm replaceVariables(GdlTerm term,
Map<GdlVariable, ? extends GdlTerm> assignment) {
return (GdlTerm) replaceVariablesInternal(term, assignment);
}
public static GdlLiteral replaceVariables(GdlLiteral literal,
Map<GdlVariable, ? extends GdlTerm> assignment) {
return (GdlLiteral) replaceVariablesInternal(literal, assignment);
}
public static GdlDistinct replaceVariables(GdlDistinct distinct,
Map<GdlVariable, ? extends GdlTerm> assignment) {
return (GdlDistinct) replaceVariablesInternal(distinct, assignment);
}
public static GdlRule replaceVariables(GdlRule rule,
Map<GdlVariable, ? extends GdlTerm> assignment) {
return (GdlRule) replaceVariablesInternal(rule, assignment);
}
private static Gdl replaceVariablesInternal(Gdl gdl,
Map<GdlVariable, ? extends GdlTerm> assignment) {
if (gdl instanceof GdlProposition) {
return gdl;
} else if (gdl instanceof GdlRelation) {
GdlRelation relation = (GdlRelation) gdl;
GdlConstant name = relation.getName();
List<GdlTerm> newBody = new ArrayList<GdlTerm>(relation.arity());
for(GdlTerm term : relation.getBody()) {
newBody.add(replaceVariables(term, assignment));
}
return GdlPool.getRelation(name, newBody);
} else if (gdl instanceof GdlConstant) {
return gdl;
} else if (gdl instanceof GdlVariable) {
if(assignment.containsKey(gdl))
return assignment.get(gdl);
else
return gdl;
} else if (gdl instanceof GdlFunction) {
GdlFunction function = (GdlFunction) gdl;
GdlConstant name = function.getName();
List<GdlTerm> newBody = new ArrayList<GdlTerm>(function.arity());
for (GdlTerm term : function.getBody()) {
newBody.add(replaceVariables(term, assignment));
}
return GdlPool.getFunction(name, newBody);
} else if (gdl instanceof GdlDistinct) {
GdlDistinct distinct = (GdlDistinct) gdl;
GdlTerm arg1 = replaceVariables(distinct.getArg1(), assignment);
GdlTerm arg2 = replaceVariables(distinct.getArg2(), assignment);
return GdlPool.getDistinct(arg1, arg2);
} else if (gdl instanceof GdlNot) {
GdlLiteral internal = ((GdlNot) gdl).getBody();
return GdlPool.getNot(replaceVariables(internal, assignment));
} else if (gdl instanceof GdlOr) {
GdlOr or = (GdlOr) gdl;
List<GdlLiteral> newInternals = new ArrayList<GdlLiteral>(or.arity());
for (int i = 0; i < or.arity(); i++) {
newInternals.add(replaceVariables(or.get(i), assignment));
}
return GdlPool.getOr(newInternals);
} else if (gdl instanceof GdlRule) {
GdlRule rule = (GdlRule) gdl;
GdlSentence newHead = replaceVariables(rule.getHead(), assignment);
List<GdlLiteral> newBody = Lists.newArrayList();
for (GdlLiteral conjunct : rule.getBody()) {
newBody.add(replaceVariables(conjunct, assignment));
}
return GdlPool.getRule(newHead, newBody);
} else {
throw new RuntimeException("Unforeseen Gdl subtype " + gdl.getClass().getSimpleName());
}
}
public static GdlRelation replaceHead(GdlRelation sentence, GdlConstant newHead) {
return GdlPool.getRelation(newHead, sentence.getBody());
}
}