blob: 41cad612c5dcf7996fcbdbc9f8f688cd22dfce91 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}