All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.mysema.query.jpa.JPAQueryMixin Maven / Gradle / Ivy
/*
* Copyright 2011, Mysema Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mysema.query.jpa;
import javax.persistence.Entity;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.mysema.query.JoinFlag;
import com.mysema.query.QueryMetadata;
import com.mysema.query.support.*;
import com.mysema.query.types.*;
import com.mysema.query.types.path.CollectionPathBase;
/**
* JPAQueryMixin extends {@link QueryMixin} to support JPQL join construction
*
* @author tiwe
*
* @param
*/
public class JPAQueryMixin extends QueryMixin {
private final Set> paths = Sets.newHashSet();
private final Map, Path>> aliases = Maps.newHashMap();
private ReplaceVisitor replaceVisitor;
public static final JoinFlag FETCH = new JoinFlag("fetch ");
public static final JoinFlag FETCH_ALL_PROPERTIES = new JoinFlag(" fetch all properties");
public JPAQueryMixin() {}
public JPAQueryMixin(QueryMetadata metadata) {
super(metadata);
}
public JPAQueryMixin(T self, QueryMetadata metadata) {
super(self, metadata);
}
public T fetch() {
addJoinFlag(FETCH);
return getSelf();
}
public T fetchAll() {
addJoinFlag(FETCH_ALL_PROPERTIES);
return getSelf();
}
@Override
protected Expression createAlias(Expression> expr, Path> alias) {
aliases.put(expr, alias);
return super.createAlias(expr, alias);
}
private boolean isEntityPath(Path> path) {
if (path instanceof CollectionPathBase) {
return isEntityPath((Path>) ((CollectionPathBase)path).any());
} else {
return path instanceof EntityPath
|| path.getType().isAnnotationPresent(Entity.class);
}
}
private Class getElementTypeOrType(Path path) {
if (path instanceof CollectionExpression) {
return ((CollectionExpression)path).getParameter(0);
} else {
return (Class) path.getType();
}
}
private Path shorten(Path path, List> paths) {
PathMetadata> metadata = path.getMetadata();
if (metadata.isRoot() || paths.contains(path)) {
return path;
} else if (aliases.containsKey(path)) {
return (Path) aliases.get(path);
} else if (metadata.getPathType() == PathType.COLLECTION_ANY) {
return (Path) shorten(metadata.getParent(), paths);
} else if (!isEntityPath(path)) {
Path> parent = shorten(metadata.getParent(), paths);
if (parent.equals(metadata.getParent())) {
return path;
} else {
return new PathImpl(path.getType(),
new PathMetadata(parent, metadata.getElement(), metadata.getPathType()));
}
} else if (metadata.getParent().getMetadata().isRoot()) {
Class type = getElementTypeOrType(path);
Path newPath = new PathImpl(type, path.toString().replace('.', '_'));
leftJoin(path, newPath);
return newPath;
} else {
Class type = getElementTypeOrType(path);
Path> parent = shorten(metadata.getParent(), paths);
Path oldPath = new PathImpl(path.getType(),
new PathMetadata(parent, metadata.getElement(), metadata.getPathType()));
Path newPath = new PathImpl(type, oldPath.toString().replace('.', '_'));
leftJoin(oldPath, newPath);
return newPath;
}
}
private Path convertPathForOrder(Path path) {
PathMetadata> metadata = path.getMetadata();
// at least three levels
if (metadata.getParent() != null && !metadata.getParent().getMetadata().isRoot()) {
Set> exprs = Sets.newHashSet();
QueryMetadata md = getMetadata();
exprs.addAll(md.getGroupBy());
if (md.getWhere() != null) exprs.add(md.getWhere());
if (md.getHaving() != null) exprs.add(md.getHaving());
List> paths = Lists.newArrayList();
// extract paths
PathsExtractor.DEFAULT.visit(exprs, paths);
if (!paths.contains(path) && !paths.contains(metadata.getParent())) {
Path> shortened = shorten(metadata.getParent(), paths);
return new PathImpl(path.getType(),
new PathMetadata(shortened, metadata.getElement(), metadata.getPathType()));
} else {
return path;
}
} else {
return path;
}
}
@Override
public Expression convert(Expression expr, boolean forOrder) {
if (forOrder) {
if (expr instanceof Path) {
expr = convertPathForOrder((Path)expr);
} else {
if (replaceVisitor == null) {
replaceVisitor = new ReplaceVisitor() {
public Expression> visit(Path> expr, Void context) {
return convertPathForOrder(expr);
}
};
}
expr = (Expression)expr.accept(replaceVisitor, null);
}
}
return Conversions.convert(super.convert(expr, forOrder));
}
@Override
protected Predicate normalize(Predicate predicate, boolean where) {
if (predicate != null) {
predicate = (Predicate) ExpressionUtils.extract(predicate);
}
if (predicate != null) {
// transform any usage
predicate = (Predicate) predicate.accept(JPACollectionAnyVisitor.DEFAULT, new Context());
// transform list access
Context context = new Context();
predicate = (Predicate) predicate.accept(ListAccessVisitor.DEFAULT, context);
for (int i = 0; i < context.paths.size(); i++) {
Path> path = context.paths.get(i);
if (!paths.contains(path)) {
addCondition(context, i, path, where);
}
}
return predicate;
} else {
return null;
}
}
@SuppressWarnings("unchecked")
private void addCondition(Context context, int i, Path> path, boolean where) {
paths.add(path);
EntityPath> alias = context.replacements.get(i);
leftJoin((Expression)path.getMetadata().getParent(), context.replacements.get(i));
Expression index = OperationImpl.create(Integer.class, JPQLOps.INDEX, alias);
Object element = path.getMetadata().getElement();
if (!(element instanceof Expression)) {
element = ConstantImpl.create(element);
}
Predicate condition = ExpressionUtils.eq(index, (Expression)element);
if (where) {
super.where(condition);
} else {
super.having(condition);
}
}
}