| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.olingo.odata2.jpa.processor.core.jpql; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.olingo.odata2.api.edm.EdmEntityType; |
| import org.apache.olingo.odata2.api.edm.EdmException; |
| import org.apache.olingo.odata2.api.edm.EdmMapping; |
| import org.apache.olingo.odata2.api.edm.EdmNavigationProperty; |
| import org.apache.olingo.odata2.api.edm.provider.Mapping; |
| import org.apache.olingo.odata2.api.exception.ODataException; |
| import org.apache.olingo.odata2.api.uri.NavigationSegment; |
| import org.apache.olingo.odata2.jpa.processor.api.access.JPAJoinClause; |
| import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException; |
| import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException; |
| import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext; |
| import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType; |
| import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLJoinContextView; |
| import org.apache.olingo.odata2.jpa.processor.core.ODataExpressionParser; |
| |
| public class JPQLJoinSelectContext extends JPQLSelectContext implements JPQLJoinContextView { |
| |
| private List<JPAJoinClause> jpaJoinClauses = null; |
| |
| protected void setJPAOuterJoinClause(final List<JPAJoinClause> jpaOuterJoinClauses) { |
| jpaJoinClauses = jpaOuterJoinClauses; |
| } |
| |
| public JPQLJoinSelectContext(final boolean isCountOnly) { |
| super(isCountOnly); |
| } |
| |
| public class JPQLJoinContextBuilder extends JPQLSelectContextBuilder { |
| |
| protected int relationShipAliasCounter = 0; |
| |
| @Override |
| public JPQLContext build() throws ODataJPAModelException, ODataJPARuntimeException { |
| try { |
| |
| if (JPQLJoinSelectContext.this.isCountOnly) { |
| setType(JPQLContextType.JOIN_COUNT); |
| } else { |
| setType(JPQLContextType.JOIN); |
| } |
| |
| if (withPaging) { |
| isPagingRequested(withPaging); |
| } |
| |
| setJPAOuterJoinClause(generateJoinClauses()); |
| |
| if (!jpaJoinClauses.isEmpty()) { |
| JPAJoinClause joinClause = jpaJoinClauses.get(jpaJoinClauses.size() - 1); |
| setJPAEntityName(joinClause.getEntityName()); |
| setJPAEntityAlias(joinClause.getEntityRelationShipAlias()); |
| } |
| |
| setOrderByCollection(generateOrderByFileds()); |
| |
| setSelectExpression(generateSelectExpression()); |
| |
| setWhereExpression(generateWhereExpression()); |
| |
| setJPQLContext(JPQLJoinSelectContext.this); |
| |
| } catch (ODataException e) { |
| throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e); |
| } |
| |
| |
| |
| return JPQLJoinSelectContext.this; |
| } |
| |
| protected List<JPAJoinClause> generateJoinClauses() throws ODataJPARuntimeException, EdmException { |
| |
| List<JPAJoinClause> jpaOuterJoinClauses = new ArrayList<JPAJoinClause>(); |
| JPAJoinClause jpaOuterJoinClause = null; |
| String joinCondition = null; |
| Map<String, Map<Integer, Object>> parameterizedExpressionMap = |
| new HashMap<String, Map<Integer,Object>>(); |
| String entityAlias = generateJPAEntityAlias(); |
| joinCondition = ODataExpressionParser.parseKeyPredicates(entitySetView.getKeyPredicates(), entityAlias); |
| |
| if (joinCondition != null) { |
| parameterizedExpressionMap.put(joinCondition, |
| ODataExpressionParser.getPositionalParametersThreadLocal()); |
| } |
| |
| EdmEntityType entityType = entitySetView.getStartEntitySet().getEntityType(); |
| Mapping mapping = (Mapping) entityType.getMapping(); |
| String entityTypeName = null; |
| if (mapping != null) { |
| entityTypeName = mapping.getInternalName(); |
| } else { |
| entityTypeName = entityType.getName(); |
| } |
| |
| jpaOuterJoinClause = |
| new JPAJoinClause(entityTypeName, entityAlias, null, null, joinCondition, JPAJoinClause.JOIN.INNER); |
| |
| jpaOuterJoinClauses.add(jpaOuterJoinClause); |
| |
| for (NavigationSegment navigationSegment : entitySetView.getNavigationSegments()) { |
| |
| EdmNavigationProperty navigationProperty = navigationSegment.getNavigationProperty(); |
| |
| String relationShipAlias = generateRelationShipAlias(); |
| |
| joinCondition = |
| ODataExpressionParser.parseKeyPredicates(navigationSegment.getKeyPredicates(), relationShipAlias); |
| |
| if (joinCondition != null) { |
| parameterizedExpressionMap.put(joinCondition, |
| ODataExpressionParser.getPositionalParametersThreadLocal()); |
| } |
| |
| jpaOuterJoinClause = |
| new JPAJoinClause(getFromEntityName(navigationProperty), entityAlias, |
| getRelationShipName(navigationProperty), relationShipAlias, joinCondition, JPAJoinClause.JOIN.INNER); |
| |
| jpaOuterJoinClauses.add(jpaOuterJoinClause); |
| |
| } |
| setParameterizedQueryMap(parameterizedExpressionMap); |
| return jpaOuterJoinClauses; |
| } |
| |
| private String getFromEntityName(final EdmNavigationProperty navigationProperty) throws EdmException { |
| |
| String fromRole = navigationProperty.getFromRole(); |
| |
| EdmEntityType toEntityType = navigationProperty.getRelationship().getEnd(fromRole).getEntityType(); |
| |
| EdmMapping mapping = toEntityType.getMapping(); |
| |
| String entityName = null; |
| if (mapping != null) { |
| entityName = mapping.getInternalName(); |
| } else { |
| entityName = toEntityType.getName(); |
| } |
| |
| return entityName; |
| |
| } |
| |
| private String getRelationShipName(final EdmNavigationProperty navigationProperty) throws EdmException { |
| |
| EdmMapping mapping = navigationProperty.getMapping(); |
| |
| String relationShipName = null; |
| if (mapping != null) { |
| relationShipName = mapping.getInternalName(); |
| } else { |
| relationShipName = navigationProperty.getName(); |
| } |
| |
| return relationShipName; |
| } |
| |
| private String generateRelationShipAlias() { |
| return new String("R" + ++relationShipAliasCounter); |
| } |
| } |
| |
| @Override |
| public List<JPAJoinClause> getJPAJoinClauses() { |
| return jpaJoinClauses; |
| } |
| |
| } |