package org.ggp.base.util.gdl.model; import java.util.List; import java.util.Map; import org.ggp.base.util.gdl.grammar.GdlConstant; import org.ggp.base.util.gdl.grammar.GdlFunction; import org.ggp.base.util.gdl.grammar.GdlPool; import org.ggp.base.util.gdl.grammar.GdlSentence; import org.ggp.base.util.gdl.grammar.GdlTerm; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; public class SimpleSentenceForm extends AbstractSentenceForm { private final GdlConstant name; //The arity is the same as the arity of the GdlSentence object, i.e. //how many terms there are at the first level (including functions). private final int arity; //We cheat a little by reusing sentence forms as function forms. //Map from the index (< arity) to the function definition. private final ImmutableMap<Integer, SimpleSentenceForm> functions; //The tuple size is the total number of constants and/or variables //within the entire sentence, including inside functions. private final int tupleSize; public static SimpleSentenceForm create(GdlSentence sentence) { GdlConstant name = sentence.getName(); int arity = sentence.arity(); int tupleSize = 0; Map<Integer, SimpleSentenceForm> functions = Maps.newHashMap(); for (int i = 0; i < arity; i++) { GdlTerm term = sentence.get(i); if (term instanceof GdlFunction) { SimpleSentenceForm functionForm = create((GdlFunction) term); functions.put(i, functionForm); tupleSize += functionForm.getTupleSize(); } else { tupleSize++; } } return new SimpleSentenceForm(name, arity, ImmutableMap.copyOf(functions), tupleSize); } private static SimpleSentenceForm create(GdlFunction function) { GdlConstant name = function.getName(); int arity = function.arity(); int tupleSize = 0; Map<Integer, SimpleSentenceForm> functions = Maps.newHashMap(); for (int i = 0; i < arity; i++) { GdlTerm term = function.get(i); if (term instanceof GdlFunction) { SimpleSentenceForm functionForm = create((GdlFunction) term); functions.put(i, functionForm); tupleSize += functionForm.getTupleSize(); } else { tupleSize++; } } return new SimpleSentenceForm(name, arity, ImmutableMap.copyOf(functions), tupleSize); } public SimpleSentenceForm(GdlConstant name, int arity, ImmutableMap<Integer, SimpleSentenceForm> functions, int tupleSize) { this.name = name; this.arity = arity; this.functions = functions; this.tupleSize = tupleSize; } @Override public GdlConstant getName() { return name; } @Override public SentenceForm withName(GdlConstant newName) { return new SimpleSentenceForm( newName, arity, functions, tupleSize); } @Override public boolean matches(GdlSentence sentence) { if (!sentence.getName().equals(name)) { return false; } if (sentence.arity() != arity) { return false; } for (int i = 0; i < sentence.arity(); i++) { GdlTerm term = sentence.get(i); if (functions.containsKey(i) && !(term instanceof GdlFunction)) { return false; } else if (term instanceof GdlFunction) { if (!functions.containsKey(i)) { return false; } GdlFunction function = (GdlFunction) term; SimpleSentenceForm functionForm = functions.get(i); if (!functionForm.matches(function)) { return false; } } } return true; } private boolean matches(GdlFunction function) { if (!function.getName().equals(name)) { return false; } if (function.arity() != arity) { return false; } for (int i = 0; i < function.arity(); i++) { GdlTerm term = function.get(i); if (functions.containsKey(i) && !(term instanceof GdlFunction)) { return false; } else if (term instanceof GdlFunction) { if (!functions.containsKey(i)) { return false; } GdlFunction innerFunction = (GdlFunction) term; SimpleSentenceForm functionForm = functions.get(i); if (!functionForm.matches(innerFunction)) { return false; } } } return true; } @Override public int getTupleSize() { return tupleSize; } @Override public GdlSentence getSentenceFromTuple(List<? extends GdlTerm> tuple) { if (tuple.size() != tupleSize) { throw new IllegalArgumentException("Passed tuple of the wrong size to a sentence form: " + "tuple was " + tuple + ", sentence form is " + this); } if (tuple.size() < arity) { throw new IllegalStateException ("Something is very wrong, probably fixable by the GdlCleaner; name: " + name + "; arity: " + arity + "; tupleSize: " + tupleSize); } List<GdlTerm> sentenceBody = Lists.newArrayList(); int curIndex = 0; for (int i = 0; i < arity; i++) { GdlTerm term = tuple.get(curIndex); Preconditions.checkArgument(!(term instanceof GdlFunction)); if (functions.containsKey(i)) { SimpleSentenceForm functionForm = functions.get(i); sentenceBody.add(functionForm.getFunctionFromTuple(tuple, curIndex)); curIndex += functionForm.getTupleSize(); } else { sentenceBody.add(term); curIndex++; } } if (arity == 0) { return GdlPool.getProposition(name); } else { return GdlPool.getRelation(name, sentenceBody); } } private GdlFunction getFunctionFromTuple(List<? extends GdlTerm> tuple, int curIndex) { List<GdlTerm> functionBody = Lists.newArrayList(); for (int i = 0; i < arity; i++) { GdlTerm term = tuple.get(curIndex); Preconditions.checkArgument(!(term instanceof GdlFunction)); if (functions.containsKey(i)) { SimpleSentenceForm functionForm = functions.get(i); functionBody.add(functionForm.getFunctionFromTuple(tuple, curIndex)); curIndex += functionForm.getTupleSize(); } else { functionBody.add(term); curIndex++; } } return GdlPool.getFunction(name, functionBody); } }