package com.sap.core.odata.processor.core.jpa.access.data;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import com.sap.core.odata.api.edm.EdmEntitySet;
import com.sap.core.odata.api.edm.EdmException;
import com.sap.core.odata.api.edm.EdmNavigationProperty;
import com.sap.core.odata.api.uri.UriInfo;
import com.sap.core.odata.api.uri.info.GetEntityUriInfo;
import com.sap.core.odata.api.uri.info.PostUriInfo;
import com.sap.core.odata.api.uri.info.PutMergePatchUriInfo;
import com.sap.core.odata.processor.api.jpa.ODataJPAContext;
import com.sap.core.odata.processor.api.jpa.access.JPAProcessor;
import com.sap.core.odata.processor.api.jpa.exception.ODataJPAModelException;
import com.sap.core.odata.processor.api.jpa.exception.ODataJPARuntimeException;
import com.sap.core.odata.processor.api.jpa.factory.ODataJPAFactory;
import com.sap.core.odata.processor.core.jpa.ODataEntityParser;
public class JPALink {
private ODataJPAContext context;
private JPAProcessor jpaProcessor;
private ODataEntityParser parser;
private Object targetJPAEntity;
private Object sourceJPAEntity;
public JPALink(final ODataJPAContext context) {
this.context = context;
jpaProcessor = ODataJPAFactory.createFactory().getJPAAccessFactory()
.getJPAProcessor(this.context);
parser = new ODataEntityParser(this.context);
}
public void setSourceJPAEntity(final Object jpaEntity) {
sourceJPAEntity = jpaEntity;
}
public void create(final PostUriInfo uriInfo, final InputStream content, final String requestContentType, final String contentType)
throws ODataJPARuntimeException, ODataJPAModelException {
EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
String targerEntitySetName;
EdmNavigationProperty navigationProperty = null;
try {
targerEntitySetName = targetEntitySet.getName();
} catch (EdmException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
}
List<UriInfo> uriInfoList = new ArrayList<UriInfo>();
if (((UriInfo) uriInfo).isLinks()) {
UriInfo getUriInfo = parser.parseLink(targetEntitySet, content, requestContentType);
uriInfoList = new ArrayList<UriInfo>();
uriInfoList.add(getUriInfo);
navigationProperty = uriInfo.getNavigationSegments().get(0).getNavigationProperty();
}
else
{
uriInfoList = parser.parseLinks(targetEntitySet, content, contentType);
}
if (uriInfoList == null) {
return;
}
try {
for (UriInfo getUriInfo : uriInfoList) {
if (!getUriInfo.getTargetEntitySet().getName().equals(targerEntitySetName))
{
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.RELATIONSHIP_INVALID, null);
}
if (!((UriInfo) uriInfo).isLinks()) {
navigationProperty = getUriInfo.getNavigationSegments().get(0).getNavigationProperty();
}
targetJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
if (targetJPAEntity != null && ((UriInfo) uriInfo).isLinks()) {
getUriInfo = parser.parseLinkURI();
sourceJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
if (sourceJPAEntity == null) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.RESOURCE_X_NOT_FOUND.
addContent(getUriInfo.getTargetEntitySet().getName()), null);
}
}
JPAEntityParser entityParser = new JPAEntityParser();
Method setMethod = entityParser.getAccessModifier(sourceJPAEntity,
navigationProperty, JPAEntityParser.ACCESS_MODIFIER_SET);
Method getMethod = entityParser.getAccessModifier(sourceJPAEntity,
navigationProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
if (getMethod.getReturnType().getTypeParameters() != null) {
@SuppressWarnings("unchecked")
List<Object> relatedEntities = (List<Object>) getMethod.invoke(sourceJPAEntity);
relatedEntities.add(targetJPAEntity);
setMethod.invoke(sourceJPAEntity, relatedEntities);
} else {
setMethod.invoke(sourceJPAEntity, targetJPAEntity);
}
}
} catch (IllegalAccessException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
} catch (IllegalArgumentException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
} catch (InvocationTargetException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
} catch (EdmException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
}
}
public void delete() {}
public void save() {
EntityManager em = context.getEntityManager();
EntityTransaction tx = em.getTransaction();
if (!tx.isActive()) {
em.getTransaction().begin();
em.persist(sourceJPAEntity);
em.getTransaction().commit();
}
}
public void update(final PutMergePatchUriInfo putUriInfo, final InputStream content,
final String requestContentType, final String contentType) throws ODataJPARuntimeException, ODataJPAModelException {
UriInfo uriInfo = (UriInfo) putUriInfo;
EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
String targerEntitySetName;
EdmNavigationProperty navigationProperty = null;
try {
targerEntitySetName = targetEntitySet.getName();
} catch (EdmException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
}
List<UriInfo> uriInfoList = new ArrayList<UriInfo>();
if (((UriInfo) uriInfo).isLinks()) {
UriInfo getUriInfo = parser.parseLink(targetEntitySet, content, requestContentType);
uriInfoList = new ArrayList<UriInfo>();
uriInfoList.add(getUriInfo);
navigationProperty = uriInfo.getNavigationSegments().get(0).getNavigationProperty();
}
else
{
uriInfoList = parser.parseLinks(targetEntitySet, content, contentType);
}
if (uriInfoList == null) {
return;
}
try {
for (UriInfo getUriInfo : uriInfoList) {
if (!getUriInfo.getTargetEntitySet().getName().equals(targerEntitySetName))
{
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.RELATIONSHIP_INVALID, null);
}
if (!((UriInfo) uriInfo).isLinks()) {
navigationProperty = getUriInfo.getNavigationSegments().get(0).getNavigationProperty();
}
targetJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
if (targetJPAEntity != null && ((UriInfo) uriInfo).isLinks()) {
getUriInfo = parser.parseLinkURI();
sourceJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
if (sourceJPAEntity == null) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.RESOURCE_X_NOT_FOUND.
addContent(getUriInfo.getTargetEntitySet().getName()), null);
}
}
JPAEntityParser entityParser = new JPAEntityParser();
Method setMethod = entityParser.getAccessModifier(sourceJPAEntity,
navigationProperty, JPAEntityParser.ACCESS_MODIFIER_SET);
Method getMethod = entityParser.getAccessModifier(sourceJPAEntity,
navigationProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
if (getMethod.getReturnType().getTypeParameters() != null && getMethod.getReturnType().getTypeParameters().length != 0) {
@SuppressWarnings("unchecked")
List<Object> relatedEntities = (List<Object>) getMethod.invoke(sourceJPAEntity);
relatedEntities.add(targetJPAEntity);
setMethod.invoke(sourceJPAEntity, relatedEntities);
} else {
setMethod.invoke(sourceJPAEntity, targetJPAEntity);
}
}
} catch (IllegalAccessException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
} catch (IllegalArgumentException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
} catch (InvocationTargetException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
} catch (EdmException e) {
throw ODataJPARuntimeException
.throwException(ODataJPARuntimeException.GENERAL
.addContent(e.getMessage()), e);
}
}
}