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

com.blazebit.persistence.impl.EntitySelectResolveVisitor Maven / Gradle / Ivy

The newest version!
package com.blazebit.persistence.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.persistence.FetchType;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;

import com.blazebit.persistence.impl.expression.*;

/**
 * This visitor resolves entity references to their attributes. This is needed for entity references
 * in the select clause when used in combination with aggregate functions. We have to decompose the
 * entity and add the components to the group by because all components will end up in the select clause.
 * 
 * @author Christian Beikov
 * @since 1.0.5
 */
public class EntitySelectResolveVisitor extends VisitorAdapter {

    private final Metamodel m;
    private final Set pathExpressions;

    public EntitySelectResolveVisitor(Metamodel m) {
        this(m, new LinkedHashSet());
    }

    public EntitySelectResolveVisitor(Metamodel m, Set pathExpressions) {
        this.m = m;
        this.pathExpressions = pathExpressions;
    }

    public Set getPathExpressions() {
        return pathExpressions;
    }

    @Override
    public void visit(FunctionExpression expression) {
        /**
         * Only functions returning an entity should be further resolved here in which case
         * the resulting entity's fields would belong into the group by.
         * Only until grouping by entities is resolved: https://hibernate.atlassian.net/browse/HHH-1615
         */
        if (com.blazebit.persistence.impl.util.ExpressionUtils.isValueFunction(expression) ||
                com.blazebit.persistence.impl.util.ExpressionUtils.isEntryFunction(expression)) {
            super.visit(expression);
        }
    }

    @Override
    public void visit(PathExpression expression) {
        if (expression.getField() == null) {
            /**
             * We need to resolve entity selects because hibernate will
             * select every entity attribute. Since we need every select in
             * the group by (because of DB2) we need to resolve such entity
             * selects here
             */
            JoinNode baseNode = ((JoinNode) expression.getBaseNode());
            EntityType entityType;

            try {
                entityType = m.entity(baseNode.getPropertyClass());
            } catch (IllegalArgumentException e) {
                // ignore if the expression is not an entity
                return;
            }

            // we need to ensure a deterministic order for testing
            SortedSet> sortedAttributes = new TreeSet>(new Comparator>() {

                @Override
                public int compare(Attribute o1, Attribute o2) {
                    return o1.getName().compareTo(o2.getName());
                }

            });
            // TODO: a polymorphic query will fail because we don't collect subtype properties
            sortedAttributes.addAll(entityType.getAttributes());
            for (Attribute attr : sortedAttributes) {
                boolean resolve = false;
                if (ExpressionUtils.isAssociation(attr) && !attr.isCollection()) {
                    resolve = true;
                } else if (ExpressionUtils.getFetchType(attr) == FetchType.EAGER) {
                    if (attr.getPersistentAttributeType() == Attribute.PersistentAttributeType.ELEMENT_COLLECTION) {
                        throw new UnsupportedOperationException("Eager element collections are not supported");
                    }
                    resolve = true;
                }

                if (resolve) {
                    PathExpression attrPath = new PathExpression(new ArrayList(expression.getExpressions()));
                    attrPath.setPathReference(new SimplePathReference(baseNode, attr.getName(), null));
                    pathExpressions.add(attrPath);
                }
            }
        }
    }

    public void resolve(JoinNode baseNode) {

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy