/*
* Copyright 2014 - 2017 Blazebit.
*
* 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.blazebit.persistence.view.impl;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.Attribute.PersistentAttributeType;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.Type;
import com.blazebit.persistence.impl.expression.ArrayExpression;
import com.blazebit.persistence.impl.expression.Expression;
import com.blazebit.persistence.impl.expression.FunctionExpression;
import com.blazebit.persistence.impl.expression.PathElementExpression;
import com.blazebit.persistence.impl.expression.PathExpression;
import com.blazebit.persistence.impl.expression.PropertyExpression;
import com.blazebit.persistence.impl.expression.VisitorAdapter;
import com.blazebit.persistence.impl.predicate.IsEmptyPredicate;
import com.blazebit.persistence.impl.predicate.MemberOfPredicate;
import com.blazebit.persistence.impl.util.ExpressionUtils;
/**
*
* @author Christian Beikov
* @since 1.0
*/
public class CollectionJoinMappingGathererExpressionVisitor extends VisitorAdapter {
private final Metamodel metamodel;
private final ManagedType<?> managedType;
private final List<String> paths;
public CollectionJoinMappingGathererExpressionVisitor(ManagedType<?> managedType, Metamodel metamodel) {
this.metamodel = metamodel;
this.managedType = managedType;
this.paths = new ArrayList<String>();
}
public List<String> getPaths() {
return paths;
}
@Override
public void visit(PropertyExpression expression) {
throw new UnsupportedOperationException("This method should never be called!");
}
@Override
public void visit(PathExpression expression) {
List<PathElementExpression> expressions = expression.getExpressions();
int size = expressions.size();
StringBuilder sb = new StringBuilder(size * 10);
ManagedType<?> t = managedType;
Attribute<?, ?> jpaAttribute = null;
for (int i = 0; i < size; i++) {
String baseName;
Expression e = expressions.get(i);
if (e instanceof ArrayExpression) {
ArrayExpression arrayExpression = (ArrayExpression) e;
arrayExpression.getIndex().accept(this);
continue;
} else {
baseName = e.toString();
}
if (i != 0) {
sb.append('.');
}
sb.append(e.toString());
try {
jpaAttribute = t.getAttribute(baseName);
} catch (IllegalArgumentException ex) {
// Ignore non existing attributes
jpaAttribute = null;
}
// NOTE: Attribute could be null because this model might contain errors
if (jpaAttribute != null) {
if (jpaAttribute instanceof PluralAttribute<?, ?, ?>) {
paths.add(sb.toString());
Type<?> elementType = ((PluralAttribute<?, ?, ?>) jpaAttribute).getElementType();
if (elementType instanceof ManagedType<?>) {
t = (ManagedType<?>) elementType;
} else {
t = null;
}
} else {
if (jpaAttribute.getPersistentAttributeType() == PersistentAttributeType.BASIC) {
t = null;
} else {
t = metamodel.managedType(jpaAttribute.getJavaType());
}
}
}
}
if (jpaAttribute instanceof PluralAttribute<?, ?, ?>) {
paths.add(sb.toString());
}
}
@Override
public void visit(IsEmptyPredicate predicate) {
}
@Override
public void visit(MemberOfPredicate predicate) {
}
@Override
public void visit(FunctionExpression expression) {
if (!ExpressionUtils.isSizeFunction(expression)) {
super.visit(expression);
}
}
}