Newer
Older
ResourceDependencyLogic / src / models / terms / meta / MetaRDLTerm.java
@Sakoda2269 Sakoda2269 on 28 Feb 10 KB 公理による推論を実装中
package models.terms.meta;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import exceptions.IllegalTypeException;
import exceptions.SubstituteFailedException;
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.LinearRightNormalizedType;
import models.terms.RDLTerm;
import models.terms.ResourceVariable;
import models.terms.SetEvaluatableTerm;

@Getter
public class MetaRDLTerm extends RDLTerm {

	protected TermType termType;
	protected LinearRightNormalizedType linearRightNormalizedType = LinearRightNormalizedType.UNDEFINED;
	
	protected MetaRDLTerm(Symbol symbol, TermType termType) {
		super(symbol, -1);
		this.termType = termType;
		if (isResourceVariable()) {
			linearRightNormalizedType = LinearRightNormalizedType.LINEAR_RIGHT_NORMALIZED;
		}
	}
	
	//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 RDLTerm substitute(Map<Variable, RDLTerm> binding) {
		if (isDependency()) {
			RDLTerm dependingTerm = (RDLTerm) getChild(0);
			RDLTerm dependedVariable = (RDLTerm) getChild(1);
			if (dependingTerm instanceof MetaRDLTerm) {
				dependingTerm = ((MetaRDLTerm) dependingTerm).substitute(binding);
			}
			if (dependedVariable instanceof MetaRDLTerm) {
				dependedVariable = ((MetaRDLTerm) dependedVariable).substitute(binding);
			}
			return new Dependency(dependingTerm, (ResourceVariable) dependedVariable);
		}
		else if (isDependencyTerm()) {
			RDLTerm dependingTerm = (RDLTerm) getChild(0);
			RDLTerm dependedVariable = (RDLTerm) getChild(1);
			RDLTerm argumentTerm = (RDLTerm) getChild(2);
			if (dependingTerm instanceof MetaRDLTerm) {
				dependingTerm = ((MetaRDLTerm) dependingTerm).substitute(binding);
			}
			if (dependedVariable instanceof MetaRDLTerm) {
				dependedVariable = ((MetaRDLTerm) dependedVariable).substitute(binding);
			}
			if (argumentTerm instanceof MetaRDLTerm) {
				argumentTerm = ((MetaRDLTerm) argumentTerm).substitute(binding);
			}
			return new DependencyTerm((EvaluatableTerm) dependingTerm, (ResourceVariable) dependedVariable, (EvaluatableTerm) argumentTerm);
		} else if (isSetTerm()) {
			RDLTerm term = (RDLTerm) getChild(0);
			if (term instanceof MetaRDLTerm) {
				term = ((MetaRDLTerm) term).substitute(binding);
			}
			return new SetEvaluatableTerm((EvaluatableTerm) term);
		}
		throw new SubstituteFailedException();
	}
	
	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;
		}
		if (isDependencyTerm() && (! islinearRightNormalizedMatchedBy(another))) {
			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 isSetTerm() {
		return checkTermType(SetEvaluatableTerm.class);
	}
	
	public boolean isResourceVariable() {
		return checkTermType(ResourceVariable.class);
	}
	
	public void setLinearRightNormalizedType(LinearRightNormalizedType next) {
		if (isDependency()) {
			return;
		}
		this.linearRightNormalizedType = next;
	}
	
	public Collection<MetaVariable> getAllVariables() {
		return getSubTerms(MetaVariable.class).values();
	}
	
	protected boolean islinearRightNormalizedMatchedBy(RDLTerm another) {
		if (linearRightNormalizedType != LinearRightNormalizedType.UNDEFINED) {
			if (another instanceof DependencyTerm) {
				if (((DependencyTerm) another).getLinearRightNormalizedType() != linearRightNormalizedType) {
					return false;
				}
			}
			else if (another instanceof MetaRDLTerm) {
				if (((MetaRDLTerm) another).getLinearRightNormalizedType() != linearRightNormalizedType) {
					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() + "]";
		case META_EVALUATABLE_TERM_SET:
			return "{" + getChild(0).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;
	}

	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;
		}
		
	}
	
}