| /******************************************************************************* |
| * 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.callback; |
| |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.apache.olingo.odata2.api.ODataCallback; |
| import org.apache.olingo.odata2.api.edm.EdmEntitySet; |
| import org.apache.olingo.odata2.api.edm.EdmEntityType; |
| import org.apache.olingo.odata2.api.edm.EdmException; |
| import org.apache.olingo.odata2.api.edm.EdmNavigationProperty; |
| import org.apache.olingo.odata2.api.edm.EdmProperty; |
| import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties; |
| import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties.ODataEntityProviderPropertiesBuilder; |
| import org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent; |
| import org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent; |
| import org.apache.olingo.odata2.api.ep.callback.WriteCallbackContext; |
| import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext; |
| import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult; |
| import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext; |
| import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult; |
| import org.apache.olingo.odata2.api.exception.ODataApplicationException; |
| import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode; |
| import org.apache.olingo.odata2.api.uri.NavigationPropertySegment; |
| import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException; |
| import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAEntityParser; |
| |
| public class JPAExpandCallBack implements OnWriteFeedContent, OnWriteEntryContent, ODataCallback { |
| |
| private URI baseUri; |
| private List<ArrayList<NavigationPropertySegment>> expandList; |
| private EdmEntitySet nextEntitySet = null; |
| private HashMap<String, List<EdmProperty>> edmPropertyMap = new HashMap<String, List<EdmProperty>>(); |
| |
| private JPAExpandCallBack(final URI baseUri, final List<ArrayList<NavigationPropertySegment>> expandList) { |
| super(); |
| this.baseUri = baseUri; |
| this.expandList = expandList; |
| } |
| |
| @Override |
| public WriteEntryCallbackResult retrieveEntryResult(final WriteEntryCallbackContext context) |
| throws ODataApplicationException { |
| WriteEntryCallbackResult result = new WriteEntryCallbackResult(); |
| Map<String, Object> entry = context.getEntryData(); |
| Map<String, Object> edmPropertyValueMap = null; |
| List<EdmNavigationProperty> currentNavPropertyList = null; |
| Map<String, ExpandSelectTreeNode> navigationLinks = null; |
| JPAEntityParser jpaResultParser = new JPAEntityParser(); |
| EdmNavigationProperty currentNavigationProperty = context.getNavigationProperty(); |
| try { |
| Object inlinedEntry = entry.get(currentNavigationProperty.getName()); |
| if (nextEntitySet == null) { |
| nextEntitySet = context.getSourceEntitySet().getRelatedEntitySet(currentNavigationProperty); |
| } |
| edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(inlinedEntry, nextEntitySet.getEntityType()); |
| result.setEntryData(edmPropertyValueMap); |
| navigationLinks = context.getCurrentExpandSelectTreeNode().getLinks(); |
| if (navigationLinks.size() > 0) { |
| currentNavPropertyList = new ArrayList<EdmNavigationProperty>(); |
| EdmNavigationProperty nextNavProperty = |
| getNextNavigationProperty(context.getSourceEntitySet().getEntityType(), context.getNavigationProperty()); |
| if (nextNavProperty != null) { |
| currentNavPropertyList.add(nextNavProperty); |
| } |
| HashMap<String, Object> navigationMap = |
| jpaResultParser.parse2EdmNavigationValueMap(inlinedEntry, currentNavPropertyList); |
| if (edmPropertyValueMap != null) { |
| edmPropertyValueMap.putAll(navigationMap); |
| } |
| result.setEntryData(edmPropertyValueMap); |
| } |
| result.setInlineProperties(getInlineEntityProviderProperties(context)); |
| } catch (EdmException e) { |
| throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), e); |
| } catch (ODataJPARuntimeException e) { |
| throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), e); |
| } |
| |
| return result; |
| } |
| |
| private List<EdmProperty> getEdmProperties(final EdmEntitySet entitySet, final ExpandSelectTreeNode expandTreeNode) |
| throws ODataApplicationException { |
| |
| try { |
| String name = entitySet.getName(); |
| if (edmPropertyMap.containsKey(name)) { |
| return edmPropertyMap.get(name); |
| } |
| List<EdmProperty> edmProperties = new ArrayList<EdmProperty>(); |
| edmProperties.addAll(expandTreeNode.getProperties()); |
| boolean hit = false; |
| for (EdmProperty keyProperty : entitySet.getEntityType().getKeyProperties()) { |
| hit = false; |
| for (EdmProperty property : edmProperties) { |
| if (property.getName().equals(keyProperty.getName())) { |
| hit = true; |
| break; |
| } |
| } |
| if (hit == false) { |
| edmProperties.add(keyProperty); |
| } |
| } |
| edmPropertyMap.put(name, edmProperties); |
| return edmProperties; |
| } catch (EdmException e) { |
| throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), e); |
| } |
| } |
| |
| @Override |
| public WriteFeedCallbackResult retrieveFeedResult(final WriteFeedCallbackContext context) |
| throws ODataApplicationException { |
| WriteFeedCallbackResult result = new WriteFeedCallbackResult(); |
| HashMap<String, Object> inlinedEntry = (HashMap<String, Object>) context.getEntryData(); |
| List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, Object>>(); |
| JPAEntityParser jpaResultParser = new JPAEntityParser(); |
| List<EdmNavigationProperty> currentNavPropertyList = null; |
| EdmNavigationProperty currentNavigationProperty = context.getNavigationProperty(); |
| ExpandSelectTreeNode currentExpandTreeNode = context.getCurrentExpandSelectTreeNode(); |
| |
| try { |
| @SuppressWarnings({ "unchecked" }) |
| Collection<Object> listOfItems = (Collection<Object>) inlinedEntry.get(context.getNavigationProperty().getName()); |
| if (nextEntitySet == null) { |
| nextEntitySet = context.getSourceEntitySet().getRelatedEntitySet(currentNavigationProperty); |
| } |
| if (currentExpandTreeNode.getProperties().size() > 0) { |
| edmEntityList = |
| jpaResultParser.parse2EdmEntityList(listOfItems, getEdmProperties(nextEntitySet, |
| currentExpandTreeNode)); |
| } else { |
| edmEntityList = jpaResultParser.parse2EdmEntityList(listOfItems, nextEntitySet.getEntityType()); |
| } |
| result.setFeedData(edmEntityList); |
| |
| if (currentExpandTreeNode.getLinks().size() > 0) { |
| currentNavPropertyList = new ArrayList<EdmNavigationProperty>(); |
| EdmNavigationProperty nextNavProperty = |
| getNextNavigationProperty(context.getSourceEntitySet().getEntityType(), context.getNavigationProperty()); |
| if (nextNavProperty != null) { |
| currentNavPropertyList.add(nextNavProperty); |
| } |
| int count = 0; |
| for (Object object : listOfItems) { |
| HashMap<String, Object> navigationMap = |
| jpaResultParser.parse2EdmNavigationValueMap(object, currentNavPropertyList); |
| edmEntityList.get(count).putAll(navigationMap); |
| count++; |
| } |
| result.setFeedData(edmEntityList); |
| } |
| result.setInlineProperties(getInlineEntityProviderProperties(context)); |
| } catch (EdmException e) { |
| throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), e); |
| } catch (ODataJPARuntimeException e) { |
| throw new ODataApplicationException(e.getMessage(), Locale.getDefault(), e); |
| } |
| return result; |
| } |
| |
| private EdmNavigationProperty getNextNavigationProperty(final EdmEntityType sourceEntityType, |
| final EdmNavigationProperty navigationProperty) throws EdmException { |
| for (ArrayList<NavigationPropertySegment> navPropSegments : expandList) { |
| int size = navPropSegments.size(); |
| for (int i = 0; i < size; i++) { |
| EdmNavigationProperty navProperty = navPropSegments.get(i).getNavigationProperty(); |
| if (navProperty.getFromRole().equalsIgnoreCase(sourceEntityType.getName()) |
| && navProperty.getName().equals(navigationProperty.getName())) { |
| if (i < size - 1) { |
| return navPropSegments.get(i + 1).getNavigationProperty(); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| public static <T> Map<String, ODataCallback> getCallbacks(final URI baseUri, |
| final ExpandSelectTreeNode expandSelectTreeNode, final List<ArrayList<NavigationPropertySegment>> expandList) |
| throws EdmException { |
| Map<String, ODataCallback> callbacks = new HashMap<String, ODataCallback>(); |
| |
| for (String navigationPropertyName : expandSelectTreeNode.getLinks().keySet()) { |
| callbacks.put(navigationPropertyName, new JPAExpandCallBack(baseUri, expandList)); |
| } |
| |
| return callbacks; |
| |
| } |
| |
| private EntityProviderWriteProperties getInlineEntityProviderProperties(final WriteCallbackContext context) |
| throws EdmException { |
| ODataEntityProviderPropertiesBuilder propertiesBuilder = EntityProviderWriteProperties.serviceRoot(baseUri); |
| propertiesBuilder.callbacks(getCallbacks(baseUri, context.getCurrentExpandSelectTreeNode(), expandList)); |
| propertiesBuilder.expandSelectTree(context.getCurrentExpandSelectTreeNode()); |
| return propertiesBuilder.build(); |
| } |
| |
| } |