package models.terms.meta;
import com.google.common.collect.TreeMultiset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import exceptions.SyntaxException;
import models.algebra.Variable;
import models.terms.RDLTerm;
public class MetaDynaimcDependencyTerm extends MetaDependencyTerm implements MetaDynamicTerm{
private final MetaTermGenerator generator;
public MetaDynaimcDependencyTerm (MetaTermGenerator generator) {
this.generator = generator;
}
public MetaDynaimcDependencyTerm(MetaTermGenerator generator, List<? extends RDLTerm> terms) {
this.generator = generator;
if (terms.size() != 0 && terms.size() % 2 != 1) {
throw new SyntaxException("");
}
this.dependingTerm = terms.size() > 0 ? terms.get(0) : null;
for (int i = 0; i < (terms.size() - 1) / 2; i++) {
RDLTerm dependedTerm = terms.get(i * 2 + 1);
RDLTerm argTerm = terms.get(i * 2 + 2);
this.termPairs.computeIfAbsent(dependedTerm, k -> TreeMultiset.create()).add(argTerm);
addChild(dependedTerm);
addChild(argTerm);
}
}
@Override
public MetaRDLTerm generate(int depth, Map<Variable, Object> context) {
// TODO 自動生成されたメソッド・スタブ
return null;
}
public MetaRDLTerm generate(int maxIndex, int maxDepth, Map<Variable, Object> context) {
return generate(1, maxIndex, maxDepth, context);
}
@Override
public MetaRDLTerm generate(int depth, int maxIndex, int maxDepth, Map<Variable, Object> context) {
if (maxIndex % 2 == 0 && maxIndex <= 2) return null;
RDLTerm dependingTerm;
List<RDLTerm> termPairs = new ArrayList<>();
if (this.dependingTerm != null) {
dependingTerm = this.dependingTerm;
} else {
dependingTerm = generator.generate(0, depth, maxIndex, maxDepth, context);
}
while (dependingTerm instanceof MetaDynamicTerm dynamicTerm) {
dependingTerm = dynamicTerm.generate(depth + 1, maxIndex, maxDepth, context);
}
int index = 1;
for (RDLTerm dependedTerm : this.termPairs.keySet()) {
for (RDLTerm argTerm : this.termPairs.get(dependedTerm)) {
while (dependedTerm instanceof MetaDynamicTerm dynamicTerm) {
dependedTerm = dynamicTerm.generate(depth + 1, maxIndex, maxDepth, context);
}
while (argTerm instanceof MetaDynamicTerm dynamicTerm) {
argTerm = dynamicTerm.generate(depth + 1, maxIndex, maxDepth, context);
}
termPairs.add(dependedTerm);
termPairs.add(argTerm);
index+=2;
}
}
for (int i = 0; i < (maxIndex - index) / 2; i++) {
RDLTerm dependedTerm = generator.generate(i * 2 + 1, depth, maxIndex, maxDepth, context);
RDLTerm argTerm = generator.generate(i * 2 + 2, depth, maxIndex, maxDepth, context);
while (dependedTerm instanceof MetaDynamicTerm dynamicTerm) {
dependedTerm = dynamicTerm.generate(depth + 1, maxIndex, maxDepth, context);
}
while (argTerm instanceof MetaDynamicTerm dynamicTerm) {
argTerm = dynamicTerm.generate(depth + 1, maxIndex, maxDepth, context);
}
termPairs.add(dependedTerm);
termPairs.add(argTerm);
}
return new MetaDependencyTerm(dependingTerm, termPairs);
}
@Override
protected Set<MatchConstraint> isMatchedBy(RDLTerm another, Set<MatchConstraint> constraint, int depth) {
int maxIndex = another.getMaxIndex();
int maxDepth = another.getMaxDepth();
MetaRDLTerm metaTerm = generate(maxIndex, maxDepth, new HashMap<>());
return metaTerm.isMatchedBy(another, constraint, depth);
}
@Override
protected RDLTerm substitute(Map<Variable, RDLTerm> binding, int depth) {
// TODO 自動生成されたメソッド・スタブ
return null;
}
@Override
public String toString() {
if (dependingTerm != null) {
return "[" + getChild(0).toString() + " : " + IntStream.range(0, (getChildren().size() - 1) / 2)
.mapToObj(i -> getChild(i * 2 + 1).toString() + " -> " + getChild(i * 2 + 2)).collect(Collectors.joining(", ")) + " ...? ]";
}
return "[ ...? ]";
}
}