package org.ggp.base.util.gdl.model.assignments;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.ggp.base.util.gdl.GdlUtils;
import org.ggp.base.util.gdl.grammar.GdlConstant;
import org.ggp.base.util.gdl.grammar.GdlSentence;
import org.ggp.base.util.gdl.grammar.GdlVariable;
import org.ggp.base.util.gdl.model.SentenceForm;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
/**
* Defines a {@link FunctionInfo} that can have values added to it (but
* not removed from it) over time. This allows the functional
* info to stay correct as new values are added with minimal
* additional computation.
*
* Not thread-safe.
*/
public class MutableFunctionInfo implements AddibleFunctionInfo {
private final SentenceForm form;
private final List<Boolean> dependentSlots = new ArrayList<Boolean>();
private final List<Map<ImmutableList<GdlConstant>, GdlConstant>> valueMaps = Lists.newArrayList();
private MutableFunctionInfo(SentenceForm form) {
this.form = form;
for (int i = 0; i < form.getTupleSize(); i++) {
dependentSlots.add(true);
valueMaps.add(Maps.<ImmutableList<GdlConstant>, GdlConstant>newHashMap());
}
}
public static MutableFunctionInfo create(SentenceForm form) {
return create(form, ImmutableSet.<GdlSentence>of());
}
public static MutableFunctionInfo create(SentenceForm form, Collection<GdlSentence> initialSentences) {
MutableFunctionInfo functionInfo = new MutableFunctionInfo(form);
for (GdlSentence sentence : initialSentences) {
functionInfo.addTuple(GdlUtils.getTupleFromGroundSentence(sentence));
}
return functionInfo;
}
@Override
public SentenceForm getSentenceForm() {
return form;
}
@Override
public void addTuple(List<GdlConstant> sentenceTuple) {
if (sentenceTuple.size() != form.getTupleSize()) {
throw new IllegalArgumentException();
}
//For each slot...
for (int i = 0; i < sentenceTuple.size(); i++) {
if (dependentSlots.get(i)) {
//Either add to that entry, or invalidate the slot
Map<ImmutableList<GdlConstant>, GdlConstant> valueMap = valueMaps.get(i);
List<GdlConstant> lookupTuple = Lists.newArrayList(sentenceTuple);
lookupTuple.remove(i);
GdlConstant curValue = valueMap.get(lookupTuple);
GdlConstant newValue = sentenceTuple.get(i);
if (curValue == null) {
//Just add to the map
valueMap.put(ImmutableList.copyOf(lookupTuple), newValue);
} else {
//If this isn't the existing sentence, invalidate this slot
if (curValue != newValue) {
dependentSlots.set(i, false);
valueMaps.set(i, ImmutableMap.<ImmutableList<GdlConstant>, GdlConstant>of());
}
}
}
}
}
@Override
public List<Boolean> getDependentSlots() {
return Collections.unmodifiableList(dependentSlots);
}
@Override
public Set<GdlVariable> getProducibleVars(GdlSentence sentence) {
return FunctionInfos.getProducibleVars(this, sentence);
}
@Override
public Map<ImmutableList<GdlConstant>, GdlConstant> getValueMap(int varIndex) {
return Collections.unmodifiableMap(valueMaps.get(varIndex));
}
@Override
public void addSentence(GdlSentence sentence) {
addTuple(GdlUtils.getTupleFromGroundSentence(sentence));
}
@Override
public String toString() {
return "MutableFunctionInfo [form=" + form + ", dependentSlots="
+ dependentSlots + ", valueMaps=" + valueMaps + "]";
}
}