All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.unibz.inf.ontop.iq.impl.IQTreeTools Maven / Gradle / Ivy

package it.unibz.inf.ontop.iq.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import it.unibz.inf.ontop.exception.MinorOntopInternalBugException;
import it.unibz.inf.ontop.injection.IntermediateQueryFactory;
import it.unibz.inf.ontop.iq.IQTree;
import it.unibz.inf.ontop.iq.node.InnerJoinNode;
import it.unibz.inf.ontop.iq.node.QueryNode;
import it.unibz.inf.ontop.iq.node.UnaryOperatorNode;
import it.unibz.inf.ontop.model.term.*;
import it.unibz.inf.ontop.substitution.Substitution;
import it.unibz.inf.ontop.substitution.InjectiveSubstitution;
import it.unibz.inf.ontop.substitution.SubstitutionFactory;
import it.unibz.inf.ontop.utils.ImmutableCollectors;

import java.util.Optional;
import java.util.function.Supplier;

@Singleton
public class IQTreeTools {

    private final IntermediateQueryFactory iqFactory;

    @Inject
    private IQTreeTools(IntermediateQueryFactory iqFactory) {
        this.iqFactory = iqFactory;
    }

    /**
     * Excludes the variables that are not projected by the IQTree
     *
     * If a "null" variable is propagated down, throws an UnsatisfiableDescendingSubstitutionException.
     *
     */
    public Optional> normalizeDescendingSubstitution(
            IQTree tree, Substitution descendingSubstitution)
            throws UnsatisfiableDescendingSubstitutionException {

        Substitution reducedSubstitution = descendingSubstitution.restrictDomainTo(tree.getVariables());

        if (reducedSubstitution.isEmpty())
            return Optional.empty();

        if (reducedSubstitution.rangeAnyMatch(ImmutableTerm::isNull)) {
            throw new UnsatisfiableDescendingSubstitutionException();
        }

        return Optional.of(reducedSubstitution);
    }

    public ImmutableSet computeNewProjectedVariables(
            Substitution descendingSubstitution,
            ImmutableSet projectedVariables) {

        ImmutableSet newVariables = descendingSubstitution.restrictDomainTo(projectedVariables).getRangeVariables();

        return Sets.union(newVariables, Sets.difference(projectedVariables, descendingSubstitution.getDomain())).immutableCopy();
    }

    public IQTree createConstructionNodeTreeIfNontrivial(IQTree child, Substitution substitution, Supplier> projectedVariables) {
        return substitution.isEmpty()
                ? child
                : iqFactory.createUnaryIQTree(iqFactory.createConstructionNode(projectedVariables.get(), substitution), child);
    }

    public IQTree createConstructionNodeTreeIfNontrivial(IQTree child, ImmutableSet variables) {
        return child.getVariables().equals(variables)
                ? child
                : iqFactory.createUnaryIQTree(iqFactory.createConstructionNode(variables), child);
    }

    public ImmutableSet getChildrenVariables(ImmutableList children) {
         return children.stream()
                .flatMap(c -> c.getVariables().stream())
                .collect(ImmutableCollectors.toSet());
    }

    public ImmutableSet getChildrenVariables(IQTree leftChild, IQTree rightChild) {
        return Sets.union(leftChild.getVariables(), rightChild.getVariables()).immutableCopy();
    }

    public ImmutableSet getChildrenVariables(IQTree child, Variable newVariable) {
        return Sets.union(child.getVariables(), ImmutableSet.of(newVariable)).immutableCopy();
    }

    public ImmutableSet extractChildVariables(ImmutableSet groupingVariables,
                                                               Substitution substitution) {
        return Sets.union(groupingVariables, substitution.getRangeVariables()).immutableCopy();
    }


    public IQTree createOptionalUnaryIQTree(Optional optionalNode, IQTree tree) {
        return optionalNode
                .map(n -> iqFactory.createUnaryIQTree(n, tree))
                .orElse(tree);
    }

    public IQTree createAncestorsUnaryIQTree(ImmutableList ancestors, IQTree tree) {
        return ancestors.stream()
                .reduce(tree,
                        (t, a) -> iqFactory.createUnaryIQTree(a, t),
                        (t1, t2) -> { throw new MinorOntopInternalBugException("No merge was expected"); });
    }

    public ImmutableList createUnaryOperatorChildren(UnaryOperatorNode node, IQTree child) {
         return child.getChildren().stream()
                .map(c -> iqFactory.createUnaryIQTree(node, c))
                .collect(ImmutableCollectors.toList());
    }

    public InnerJoinNode createInnerJoinNode(Optional optionalExpression) {
        return optionalExpression.map(iqFactory::createInnerJoinNode).orElseGet(iqFactory::createInnerJoinNode);
    }

    /**
     * If the substitution is a fresh renaming, returns it as an injective substitution
     */
    public Optional> extractFreshRenaming(Substitution descendingSubstitution,
                                                                          ImmutableSet projectedVariables) {

        Substitution var2VarFragment = descendingSubstitution.restrictRangeTo(Variable.class);
        int size = descendingSubstitution.getDomain().size();

        if (var2VarFragment.getDomain().size() != size
                || Sets.difference(var2VarFragment.getRangeSet(), projectedVariables).size() != size)
            return Optional.empty();

        return Optional.of(var2VarFragment.injective());
    }


    /**
     * Typically thrown when a "null" variable is propagated down
     *
     */
    public static class UnsatisfiableDescendingSubstitutionException extends Exception {
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy