Newer
Older
RDLProofSystem / src / main / java / models / terms / DependencyTerm.java
package models.terms;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

import lombok.Getter;
import models.algebra.Symbol;

@Getter
public class DependencyTerm extends EvaluatableTerm{

	private EvaluatableTerm dependingTerm;
	private List<Resource> dependedResources = new ArrayList<>();
	private List<EvaluatableTerm> argumentTerms = new ArrayList<>();
	
	
	public DependencyTerm(EvaluatableTerm dependingTerm, List<Resource> dependedTerms, List<EvaluatableTerm> argumentTerms) {
		super(
				new Symbol(":", 1 + dependedTerms.size() + argumentTerms.size()), 
				-1, 
				dependingTerm.getSize() + argumentTerms.stream().mapToInt(RDLTerm::getSize).sum() + dependedTerms.stream().mapToInt(RDLTerm::getSize).sum()
		);
		int maxOrder = argumentTerms.stream().mapToInt(EvaluatableTerm::getOrder).max().orElse(-1);
		if (dependedTerms.get(0).getOrder() < maxOrder) {
			this.order = dependingTerm.getOrder() + (maxOrder - dependedTerms.get(0).getOrder());
		} else if (dependedTerms.get(0).getOrder() == maxOrder) {
			this.order = dependingTerm.getOrder();
		} else {
			this.order = dependingTerm.getOrder() - 1;
		}
		
		for(int i = 0; i < dependedTerms.size(); i++) {
			if (dependedTerms.get(0).getOrder() != dependedTerms.get(i).getOrder()) {
				throw new RuntimeException("dependedTerms order not equals");
			}
		}
		
		if (dependedTerms.size() != argumentTerms.size()) {
			throw new RuntimeException("Size not equals");
		}
		this.dependingTerm = dependingTerm;
		this.dependedResources = new ArrayList<>(dependedTerms);
		this.argumentTerms = new ArrayList<>(argumentTerms);
		addChild(dependingTerm);
		for (int i = 0; i < dependedTerms.size(); i++) {
			addChild(dependedTerms.get(i));
			addChild(argumentTerms.get(i));
		}
	}
	
	public DependencyTerm(EvaluatableTerm dependingTerm, EvaluatableTerm ...terms) {
		this(
				dependingTerm, 
				IntStream.range(0, terms.length).filter(i -> i % 2 == 0).mapToObj(i -> (Resource) terms[i]).toList(), 
				IntStream.range(0, terms.length).filter(i -> i % 2 == 1).mapToObj(i -> terms[i]).toList()
			);
	}
	
	@Override
	public boolean isLinearRightNormalized() {
		return isLinearRightNormaled(0);
	}
	
	@Override
	public EvaluatableTerm linearRightNormalize() {
		DependencyTerm newTerm = (DependencyTerm) clone();
		newTerm.selfLinearRightNormalize();
		return newTerm;
	}
	
	@Override
	public void selfLinearRightNormalize() {
//		if(dependingTerm instanceof ResourceVariable || dependingTerm instanceof SetEvaluatableTerm) {
//			argumentTerm.selfLinearRightNormalize();
//			return;
//		}
//		DependencyTerm dependencyTerm = (DependencyTerm) dependingTerm;
//		if(! dependencyTerm.isLinearRightNormalized()) {
//			dependencyTerm.selfLinearRightNormalize();
//		}
//		if(! isLinearRightNormalized()) {
//			EvaluatableTerm childArgumentTerm = dependencyTerm.getArgumentTerm();
//			DependencyTerm nextDependencyTerm = new DependencyTerm(childArgumentTerm, dependedVariable, argumentTerm);
//			this.dependingTerm = dependencyTerm.getDependingTerm();
//			this.dependedVariable = dependencyTerm.getDependedVariable();
//			this.argumentTerm = nextDependencyTerm;
//			this.setChild(2, nextDependencyTerm);
//			this.setChild(0, dependencyTerm.getDependingTerm());
//			this.setChild(1, dependencyTerm.getDependedVariable());
//		}
//		argumentTerm.selfLinearRightNormalize();
		
	}
	
	private boolean isLinearRightNormaled(int depth) {
//		if(dependingTerm instanceof ResourceVariable || dependingTerm instanceof SetEvaluatableTerm) {
//			return dependingTerm.getOrder() == dependedVariable.getOrder();
//		}
//		DependencyTerm dependencyTerm = (DependencyTerm) dependingTerm;
//		if(
//				dependencyTerm.isLinearRightNormaled(depth + 1) && 
//				dependencyTerm.getDependedVariable().getOrder() - 1 == dependedVariable.getOrder() && 
//				dependencyTerm.getOrder() == dependedVariable.getOrder() &&
//				argumentTerm.getOrder() <= dependencyTerm.getOrder() &&
//				depth == 0
//		) {
//			return true;
//		}
//		if(
//				dependencyTerm.isLinearRightNormaled(depth + 1) && 
//				dependencyTerm.getDependedVariable().getOrder() - 1 == dependedVariable.getOrder() && 
//				dependencyTerm.getOrder() == dependedVariable.getOrder() &&
//				argumentTerm.getOrder() < dependencyTerm.getOrder()
//		) {
//			return true;
//		}
		
		return false;
	}
	
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append('[');
		sb.append(getDependingTerm().toString());
		sb.append(" : ");
		for (int i = 0; i < dependedResources.size(); i++) {
			sb.append(dependedResources.get(i).toString());
			sb.append(" -> ");
			sb.append(argumentTerms.get(i).toString());
			sb.append(", ");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.deleteCharAt(sb.length() - 1);
		sb.append(']');
		return sb.toString();
	}
	
	@Override
	public String toStringWithOrder() {
		StringBuilder sb = new StringBuilder();
		sb.append('[');
		sb.append(getDependingTerm().toStringWithOrder());
		sb.append(" : ");
		for (int i = 0; i < dependedResources.size(); i++) {
			sb.append(dependedResources.get(i).toStringWithOrder());
			sb.append(" -> ");
			sb.append(argumentTerms.get(i).toStringWithOrder());
			sb.append(", ");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append(']');
		sb.append('(');
		sb.append(order);
		sb.append(')');
		return sb.toString();
	}
	
	@Override
	public boolean equals(Object another) {
		if(! (another instanceof DependencyTerm)) {
			return false;
		}
		DependencyTerm term = (DependencyTerm) another;
		
		return dependingTerm.equals(term.getDependingTerm()) && 
				dependedResources.stream().sorted().toList().equals(term.getDependedResources().stream().sorted().toList()) &&
				argumentTerms.stream().sorted().toList().equals(term.getArgumentTerms().stream().sorted().toList());
	}

	@Override
	public int hashCode() {
		return ("DT" + toString()).hashCode();
	}

	@Override
	public Object clone() {
		return new DependencyTerm(
				(EvaluatableTerm) dependingTerm.clone(),
				new ArrayList<>(dependedResources),
				new ArrayList<>(argumentTerms)
		);
	}


}