package models.terms.meta;
import java.util.HashMap;
import java.util.Map;
import exceptions.IllegalTypeException;
import lombok.Getter;
import models.algebra.Symbol;
import models.algebra.Variable;
import models.terms.Dependency;
import models.terms.DependencyTerm;
import models.terms.EvaluatableTerm;
import models.terms.RDLTerm;
import models.terms.ResourceVariable;
import models.terms.SetEvaluatableTerm;
@Getter
public class MetaRDLTerm extends RDLTerm {
protected static enum TermType {
META_RDL_TERM(RDLTerm.class),
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_EVALUATABLE_TERM_SET(SetEvaluatableTerm.class),
META_EVALUATABLE_TERM_SET_VARIABLE(SetEvaluatableTerm.class),
META_RESOURCE_VARIABLE(ResourceVariable.class);
@Getter
private Class<?> baseTermClass;
private TermType(Class<?> clazz) {
this.baseTermClass = 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 or set term
public MetaRDLTerm(MetaRDLTerm term) {
super(new Symbol(":", 1), term.getOrder() - 1);
if (term.isDependency()) {
this.termType = TermType.META_DEPENDENCY_LIST;
} else if (term.isEvaluatableTerm()) {
this.termType = TermType.META_EVALUATABLE_TERM_SET;
}
addChild(term);
}
//dependency term
public MetaRDLTerm(MetaRDLTerm dependingTerm, MetaResourceVariable dependedVariable, MetaRDLTerm argumentTerm) {
super(new Symbol(":", 3), -1);
if (! EvaluatableTerm.class.isAssignableFrom(dependingTerm.getTermType().getBaseTermClass())) {
throw new IllegalTypeException();
}
if(! EvaluatableTerm.class.isAssignableFrom(argumentTerm.getTermType().getBaseTermClass())) {
throw new IllegalTypeException();
}
addChild(dependingTerm);
addChild(dependedVariable);
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public MetaRDLTerm(EvaluatableTerm dependingTerm, MetaRDLTerm dependedVariable, MetaRDLTerm argumentTerm) {
super(new Symbol(":", 3), -1);
if(! EvaluatableTerm.class.isAssignableFrom(argumentTerm.getTermType().getBaseTermClass())) {
throw new IllegalTypeException();
}
addChild(dependingTerm);
addChild(dependedVariable);
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public MetaRDLTerm(MetaRDLTerm dependingTerm, ResourceVariable dependedVariable, MetaRDLTerm argumentTerm) {
super(new Symbol(":", 3), -1);
if (! EvaluatableTerm.class.isAssignableFrom(dependingTerm.getTermType().getBaseTermClass())) {
throw new IllegalTypeException();
}
if(! EvaluatableTerm.class.isAssignableFrom(argumentTerm.getTermType().getBaseTermClass())) {
throw new IllegalTypeException();
}
addChild(dependingTerm);
addChild(dependedVariable);
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public MetaRDLTerm(MetaRDLTerm dependingTerm, MetaRDLTerm dependedVariable, EvaluatableTerm argumentTerm) {
super(new Symbol(":", 3), -1);
if (! EvaluatableTerm.class.isAssignableFrom(dependingTerm.getTermType().getBaseTermClass())) {
throw new IllegalTypeException();
}
addChild(dependingTerm);
addChild(dependedVariable);
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public MetaRDLTerm(MetaRDLTerm dependingTerm, ResourceVariable dependedVariable, EvaluatableTerm argumentTerm) {
super(new Symbol(":", 3), -1);
if (! EvaluatableTerm.class.isAssignableFrom(dependingTerm.getTermType().getBaseTermClass())) {
throw new IllegalTypeException();
}
addChild(dependingTerm);
addChild(dependedVariable);
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public MetaRDLTerm(EvaluatableTerm dependingTerm, MetaResourceVariable dependedVariable, EvaluatableTerm argumentTerm) {
super(new Symbol(":", 3), -1);
addChild(dependingTerm);
addChild(dependedVariable);
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public MetaRDLTerm(EvaluatableTerm dependingTerm, ResourceVariable dependedVariable, MetaRDLTerm argumentTerm) {
super(new Symbol(":", 3), -1);
if(! EvaluatableTerm.class.isAssignableFrom(argumentTerm.getTermType().getBaseTermClass())) {
throw new IllegalTypeException();
}
addChild(dependingTerm);
addChild(dependedVariable);
addChild(argumentTerm);
this.termType = TermType.META_DEPENDENCY_TERM;
}
public boolean isVariable() {
return false;
}
public boolean isMatchedBy(RDLTerm another) {
return isMatchedBy(another, new HashMap<>(), new HashMap<>());
}
public boolean isMatchedBy(RDLTerm another, Map<Variable, RDLTerm> binding, Map<Variable, OrderVariableConstraint> orderConstraint) {
if (! another.getClass().isAssignableFrom(this.termType.getBaseTermClass())) {
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;
}
public boolean checkTermType(Class<? extends RDLTerm> clazz) {
return clazz.isAssignableFrom(termType.getBaseTermClass());
}
public boolean isDependency() {
return checkTermType(Dependency.class);
}
public boolean isEvaluatableTerm() {
return checkTermType(EvaluatableTerm.class);
}
public boolean isDependencyTerm() {
return checkTermType(DependencyTerm.class);
}
public boolean isResourceVariable() {
return checkTermType(ResourceVariable.class);
}
@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;
}
}