package com.sap.core.odata.processor.core.jpa.access.data; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.sap.core.odata.api.edm.EdmEntitySet; import com.sap.core.odata.api.edm.EdmEntityType; import com.sap.core.odata.api.edm.EdmException; import com.sap.core.odata.api.edm.EdmNavigationProperty; import com.sap.core.odata.api.edm.EdmProperty; import com.sap.core.odata.api.edm.EdmStructuralType; import com.sap.core.odata.api.edm.EdmTypeKind; import com.sap.core.odata.api.edm.EdmTyped; import com.sap.core.odata.api.ep.entry.ODataEntry; import com.sap.core.odata.api.ep.feed.ODataFeed; import com.sap.core.odata.processor.api.jpa.exception.ODataJPARuntimeException; import com.sap.core.odata.processor.api.jpa.model.JPAEdmMapping; public class JPAEntity { private Object jpaEntity = null; private EdmEntityType oDataEntityType = null; private EdmEntitySet oDataEntitySet = null; private Class<?> jpaType = null; private HashMap<String, Method> accessModifiersWrite = null; private JPAEntityParser jpaEntityParser = null; public HashMap<EdmNavigationProperty, EdmEntitySet> inlinedEntities = null; public JPAEntity(final EdmEntityType oDataEntityType, final EdmEntitySet oDataEntitySet) { this.oDataEntityType = oDataEntityType; this.oDataEntitySet = oDataEntitySet; try { JPAEdmMapping mapping = (JPAEdmMapping) oDataEntityType.getMapping(); jpaType = mapping.getJPAType(); } catch (EdmException e) { return; } jpaEntityParser = new JPAEntityParser(); } public void setAccessModifersWrite(final HashMap<String, Method> accessModifiersWrite) { this.accessModifiersWrite = accessModifiersWrite; } public Object getJPAEntity() { return jpaEntity; } @SuppressWarnings("unchecked") private void write(final Map<String, Object> oDataEntryProperties, final boolean isCreate) throws ODataJPARuntimeException { try { EdmStructuralType structuralType = null; final List<String> keyNames = oDataEntityType.getKeyPropertyNames(); if (isCreate) { jpaEntity = instantiateJPAEntity(); } else if (jpaEntity == null) { throw ODataJPARuntimeException .throwException(ODataJPARuntimeException.RESOURCE_NOT_FOUND, null); } if (accessModifiersWrite == null) { accessModifiersWrite = jpaEntityParser.getAccessModifiers(jpaEntity, oDataEntityType, JPAEntityParser.ACCESS_MODIFIER_SET); } if (oDataEntityType == null || oDataEntryProperties == null) { throw ODataJPARuntimeException .throwException(ODataJPARuntimeException.GENERAL, null); } final HashMap<String, String> embeddableKeys = jpaEntityParser.getJPAEmbeddableKeyMap(jpaEntity.getClass().getName()); Set<String> propertyNames = null; if (embeddableKeys != null) { setEmbeddableKeyProperty(embeddableKeys, oDataEntityType.getKeyProperties(), oDataEntryProperties, jpaEntity); propertyNames = new HashSet<String>(); propertyNames.addAll(oDataEntryProperties.keySet()); for (String propertyName : oDataEntityType.getKeyPropertyNames()) { propertyNames.remove(propertyName); } } else { propertyNames = oDataEntryProperties.keySet(); } for (String propertyName : propertyNames) { EdmTyped edmTyped = (EdmTyped) oDataEntityType.getProperty(propertyName); Method accessModifier = null; switch (edmTyped.getType().getKind()) { case SIMPLE: if (isCreate == false) { if (keyNames.contains(edmTyped.getName())) { continue; } } accessModifier = accessModifiersWrite.get(propertyName); setProperty(accessModifier, jpaEntity, oDataEntryProperties.get(propertyName)); break; case COMPLEX: structuralType = (EdmStructuralType) edmTyped.getType(); accessModifier = accessModifiersWrite.get(propertyName); setComplexProperty(accessModifier, jpaEntity, structuralType, (HashMap<String, Object>) oDataEntryProperties.get(propertyName)); break; case NAVIGATION: case ENTITY: structuralType = (EdmStructuralType) edmTyped.getType(); accessModifier = jpaEntityParser.getAccessModifier(jpaEntity, (EdmNavigationProperty) edmTyped, JPAEntityParser.ACCESS_MODIFIER_SET); EdmEntitySet edmRelatedEntitySet = oDataEntitySet.getRelatedEntitySet((EdmNavigationProperty) edmTyped); List<ODataEntry> relatedEntries = (List<ODataEntry>) oDataEntryProperties.get(propertyName); List<Object> relatedJPAEntites = new ArrayList<Object>(); JPAEntity relatedEntity = new JPAEntity((EdmEntityType) structuralType, edmRelatedEntitySet); for (ODataEntry oDataEntry : relatedEntries) { relatedEntity.create(oDataEntry); relatedJPAEntites.add(relatedEntity.getJPAEntity()); } EdmNavigationProperty navProperty = (EdmNavigationProperty) edmTyped; switch (navProperty.getMultiplicity()) { case MANY: accessModifier.invoke(jpaEntity, relatedJPAEntites); break; case ONE: case ZERO_TO_ONE: accessModifier.invoke(jpaEntity, relatedJPAEntites.get(0)); break; } if (inlinedEntities == null) { inlinedEntities = new HashMap<EdmNavigationProperty, EdmEntitySet>(); } inlinedEntities.put((EdmNavigationProperty) edmTyped, edmRelatedEntitySet); default: continue; } } } catch (Exception e) { throw ODataJPARuntimeException .throwException(ODataJPARuntimeException.GENERAL .addContent(e.getMessage()), e); } } public void create(final ODataEntry oDataEntry) throws ODataJPARuntimeException { if (oDataEntry == null) { throw ODataJPARuntimeException .throwException(ODataJPARuntimeException.GENERAL, null); } Map<String, Object> oDataEntryProperties = oDataEntry.getProperties(); if (oDataEntry.containsInlineEntry()) { try { for (String navigationPropertyName : oDataEntityType.getNavigationPropertyNames()) { ODataFeed feed = (ODataFeed) oDataEntry.getProperties().get(navigationPropertyName); if (feed == null) { continue; } List<ODataEntry> relatedEntries = feed.getEntries(); oDataEntryProperties.put(navigationPropertyName, relatedEntries); } } catch (EdmException e) { throw ODataJPARuntimeException .throwException(ODataJPARuntimeException.GENERAL .addContent(e.getMessage()), e); } } write(oDataEntryProperties, true); } public void create(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException { write(oDataEntryProperties, true); } public void update(final ODataEntry oDataEntry) throws ODataJPARuntimeException { if (oDataEntry == null) { throw ODataJPARuntimeException .throwException(ODataJPARuntimeException.GENERAL, null); } Map<String, Object> oDataEntryProperties = oDataEntry.getProperties(); write(oDataEntryProperties, false); } public void update(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException { write(oDataEntryProperties, false); } @SuppressWarnings("unchecked") protected void setComplexProperty(Method accessModifier, final Object jpaEntity, final EdmStructuralType edmComplexType, final HashMap<String, Object> propertyValue) throws EdmException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, ODataJPARuntimeException { JPAEdmMapping mapping = (JPAEdmMapping) edmComplexType.getMapping(); Object embeddableObject = mapping.getJPAType().newInstance(); accessModifier.invoke(jpaEntity, embeddableObject); HashMap<String, Method> accessModifiers = jpaEntityParser.getAccessModifiers(embeddableObject, edmComplexType, JPAEntityParser.ACCESS_MODIFIER_SET); for (String edmPropertyName : edmComplexType.getPropertyNames()) { EdmTyped edmTyped = (EdmTyped) edmComplexType.getProperty(edmPropertyName); accessModifier = accessModifiers.get(edmPropertyName); if (edmTyped.getType().getKind().toString().equals(EdmTypeKind.COMPLEX.toString())) { EdmStructuralType structualType = (EdmStructuralType) edmTyped.getType(); setComplexProperty(accessModifier, embeddableObject, structualType, (HashMap<String, Object>) propertyValue.get(edmPropertyName)); } else { setProperty(accessModifier, embeddableObject, propertyValue.get(edmPropertyName)); } } } protected void setProperty(final Method method, final Object entity, final Object entityPropertyValue) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (entityPropertyValue != null) { method.invoke(entity, entityPropertyValue); } } protected void setEmbeddableKeyProperty(final HashMap<String, String> embeddableKeys, final List<EdmProperty> oDataEntryKeyProperties, final Map<String, Object> oDataEntryProperties, final Object entity) throws ODataJPARuntimeException, EdmException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { HashMap<String, Object> embeddableObjMap = new HashMap<String, Object>(); List<EdmProperty> leftODataEntryKeyProperties = new ArrayList<EdmProperty>(); HashMap<String, String> leftEmbeddableKeys = new HashMap<String, String>(); for (EdmProperty edmProperty : oDataEntryKeyProperties) { if (oDataEntryProperties.containsKey(edmProperty.getName()) == false) { continue; } String edmPropertyName = edmProperty.getName(); String embeddableKeyNameComposite = embeddableKeys.get(edmPropertyName); String embeddableKeyNameSplit[] = embeddableKeyNameComposite.split("\\."); String methodPartName = null; Method method = null; Object embeddableObj = null; if (embeddableObjMap.containsKey(embeddableKeyNameSplit[0]) == false) { methodPartName = embeddableKeyNameSplit[0]; method = jpaEntityParser.getAccessModifierSet(entity, methodPartName); embeddableObj = method.getParameterTypes()[0].newInstance(); method.invoke(entity, embeddableObj); embeddableObjMap.put(embeddableKeyNameSplit[0], embeddableObj); } else { embeddableObj = embeddableObjMap.get(embeddableKeyNameSplit[0]); } if (embeddableKeyNameSplit.length == 2) { methodPartName = embeddableKeyNameSplit[1]; method = jpaEntityParser.getAccessModifierSet(embeddableObj, methodPartName); Object simpleObj = oDataEntryProperties.get(edmProperty.getName()); method.invoke(embeddableObj, simpleObj); } else if (embeddableKeyNameSplit.length > 2) // Deeply nested { leftODataEntryKeyProperties.add(edmProperty); leftEmbeddableKeys.put(edmPropertyName, embeddableKeyNameComposite.split(embeddableKeyNameSplit[0] + ".", 2)[1]); setEmbeddableKeyProperty(leftEmbeddableKeys, leftODataEntryKeyProperties, oDataEntryProperties, embeddableObj); } } } protected Object instantiateJPAEntity() throws InstantiationException, IllegalAccessException { if (jpaType == null) { throw new InstantiationException(); } return jpaType.newInstance(); } public HashMap<EdmNavigationProperty, EdmEntitySet> getInlineJPAEntities() { return inlinedEntities; } public void setJPAEntity(final Object jpaEntity) { this.jpaEntity = jpaEntity; } }