package models.meta;
import java.util.Map;
import exceptions.IllegalTypeException;
import lombok.Getter;
import models.Dependency;
import models.DependencyTerm;
import models.EvaluatableTerm;
import models.RDLTerm;
import models.ResourceVariable;
import models.algebra.Symbol;
import models.algebra.Variable;
@Getter
public class MetaRDLTerm extends RDLTerm {
protected static enum TermType {
META_DEPENDENCY(Dependency.class),
META_DEPENDENCY_LIST(Dependency.class),
META_DEPENDENCY_VARIABLE(Dependency.class),
META_DEPENDENCY_TERM(DependencyTerm.class),
META_DEPENDENCY_TERM_VARIABLE(DependencyTerm.class),
META_EVALUATABLE_TERM_VARIABLE(EvaluatableTerm.class),
META_RESOURCE_VARIABLE(ResourceVariable.class);
private Class<?> clazz;
TermType(Class<?> clazz) {
this.clazz = clazz;
}
public Class<?> getClazz() {
return this.clazz;
}
}
protected TermType termType;
protected MetaRDLTerm(Symbol symbol, TermType termType) {
super(symbol, -1);
this.termType = termType;
}
//dependency
public MetaRDLTerm(RDLTerm dependingTerm, MetaResourceVariable dependedVariable) {
super(new Symbol(":", 2), dependedVariable.getOrder());
addChild(dependingTerm);
addChild(dependedVariable);
this.termType = TermType.META_DEPENDENCY;
}
public MetaRDLTerm(MetaRDLTerm dependingTerm, ResourceVariable dependedVariable) {
super(new Symbol(":", 2), dependedVariable.getOrder());
addChild(dependingTerm);
addChild(dependedVariable);
this.termType = TermType.META_DEPENDENCY;
}
public MetaRDLTerm(MetaRDLTerm dependingTerm, MetaResourceVariable dependedVariable) {
super(new Symbol(":", 2), dependedVariable.getOrder());
addChild(dependingTerm);
addChild(dependedVariable);
this.termType = TermType.META_DEPENDENCY;
}
//list type dependency
public MetaRDLTerm(MetaRDLTerm dependency) {
super(new Symbol(":", 1), dependency.getOrder() - 1);
addChild(dependency);
this.termType = TermType.META_DEPENDENCY_LIST;
}
//dependency term
public MetaRDLTerm(Dependency dependency, MetaRDLTerm argumentTerm) {
super(
new Symbol(":", 3),
dependency.getDependedVariable().getOrder() == argumentTerm.getOrder()
? dependency.getDependedVariable().getOrder()
: dependency.getDependedVariable().getOrder() - 1
);
if(! dependency.isDependeingTermEvaluatable()) {
throw new IllegalTypeException();
}
addChild(dependency.getDependingTerm());
addChild(dependency.getDependedVariable());
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public MetaRDLTerm(MetaRDLTerm dependency, EvaluatableTerm argumentTerm) {
super(
new Symbol(":", 3),
((RDLTerm) dependency.getChild(1)).getOrder() == argumentTerm.getOrder()
? ((RDLTerm) dependency.getChild(1)).getOrder()
: ((RDLTerm) dependency.getChild(1)).getOrder() - 1
);
var firstTerm = (RDLTerm) dependency.getChild(0);
if(firstTerm instanceof MetaRDLTerm) {
var firtTerm2 = (MetaRDLTerm) firstTerm;
if(firtTerm2.getTermType() == TermType.META_DEPENDENCY || firtTerm2.getTermType() == TermType.META_DEPENDENCY_TERM) {
throw new IllegalTypeException();
}
} else {
if(! (firstTerm instanceof EvaluatableTerm)) {
throw new IllegalTypeException();
}
}
addChild(dependency.getChild(0));
addChild(dependency.getChild(1));
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public MetaRDLTerm(MetaRDLTerm dependency, MetaRDLTerm argumentTerm) {
super(
new Symbol(":", 3),
((RDLTerm) dependency.getChild(1)).getOrder() == argumentTerm.getOrder()
? ((RDLTerm) dependency.getChild(1)).getOrder()
: ((RDLTerm) dependency.getChild(1)).getOrder() - 1
);
var firstTerm = (RDLTerm) dependency.getChild(0);
if(firstTerm instanceof MetaRDLTerm) {
var firtTerm2 = (MetaRDLTerm) firstTerm;
if(firtTerm2.getTermType() == TermType.META_DEPENDENCY || firtTerm2.getTermType() == TermType.META_DEPENDENCY_TERM) {
throw new IllegalTypeException();
}
} else {
if(! (firstTerm instanceof EvaluatableTerm)) {
throw new IllegalTypeException();
}
}
addChild(dependency.getChild(0));
addChild(dependency.getChild(1));
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public boolean isVariable() {
return false;
}
public boolean isMatchedBy(RDLTerm another, Map<Variable, RDLTerm> binding, Map<Variable, OrderVariableConstraint> orderConstraint) {
if (! another.getClass().isAssignableFrom(this.termType.getClazz())) {
return false;
}
if (this.getChildren().size() != another.getChildren().size()) {
return false;
}
for (int i = 0; i < this.getChildren().size(); i++) {
RDLTerm child = (RDLTerm) this.getChild(i);
RDLTerm anotherChild = (RDLTerm) another.getChild(i);
if (child instanceof MetaRDLTerm) {
MetaRDLTerm metaChild = (MetaRDLTerm) child;
if (! metaChild.isMatchedBy(anotherChild, binding, orderConstraint)) {
return false;
}
} else {
if (!(child.equals(anotherChild))) {
return false;
}
}
}
return true;
}
@Override
public String toString() {
switch(termType) {
case META_DEPENDENCY:
return "[" + getChild(0).toString() + " : " + getChild(1).toString() + "]";
case META_DEPENDENCY_LIST:
return "[" + getChild(0).toString() + "]";
case META_DEPENDENCY_TERM:
return "[" + getChild(0).toString() + " : " + getChild(1).toString() + " -> " + getChild(2).toString() + "]";
default:
return "";
}
}
@Override
public String toStringWithOrder() {
switch(termType) {
case META_DEPENDENCY:
return "[" + ((RDLTerm) getChild(0)).toStringWithOrder() + " : " + ((RDLTerm) getChild(1)).toStringWithOrder() + "]";
case META_DEPENDENCY_LIST:
return "[" + ((RDLTerm) getChild(0)).toStringWithOrder() + "]";
case META_DEPENDENCY_TERM:
return "[" + ((RDLTerm) getChild(0)).toStringWithOrder() + " : "
+ ((RDLTerm) getChild(1)).toStringWithOrder() + " -> " + ((RDLTerm) getChild(2)).toStringWithOrder() + "]";
default:
return "";
}
}
@Override
public boolean equals(Object another) {
if(! (another instanceof MetaRDLTerm)) {
return false;
}
MetaRDLTerm anotherTerm = (MetaRDLTerm) another;
return super.equals(another) && termType == anotherTerm.getTermType();
}
@Override
public int hashCode() {
return (termType.toString() + toStringWithOrder()).hashCode();
}
@Override
public Object clone() {
return null;
}
}