[BAEL-1219] Code polishing
This commit is contained in:
parent
270582b25a
commit
5f30277f9e
|
@ -31,7 +31,7 @@ public class CarModel {
|
||||||
@NotNull
|
@NotNull
|
||||||
private String sku;
|
private String sku;
|
||||||
|
|
||||||
@ManyToOne(optional=false, fetch= FetchType.LAZY)
|
@ManyToOne(optional=false, fetch= FetchType.EAGER )
|
||||||
@JoinColumn(name="maker_fk")
|
@JoinColumn(name="maker_fk")
|
||||||
private CarMaker maker;
|
private CarMaker maker;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package org.baeldung.examples.olingo4.edm;
|
package org.baeldung.examples.olingo4.edm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
@ -33,11 +35,14 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider {
|
||||||
private EdmTypeMapper typeMapper;
|
private EdmTypeMapper typeMapper;
|
||||||
|
|
||||||
// Service Namespace
|
// Service Namespace
|
||||||
public static final String NAMESPACE = "OData.Demo";
|
public static final String NAMESPACE = "Baeldung.OData";
|
||||||
|
|
||||||
// EDM Container
|
// EDM Container
|
||||||
public static final String CONTAINER_NAME = "Cars";
|
public static final String CONTAINER_NAME = "Cars";
|
||||||
public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME);
|
public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME);
|
||||||
|
|
||||||
|
// Caches of OData types by it fully qualified name
|
||||||
|
private Map<FullQualifiedName, CsdlEntityType> cdslName2Type = new HashMap<>();
|
||||||
|
|
||||||
public JpaEdmProvider(EntityManagerFactory emf, EdmTypeMapper mapper) {
|
public JpaEdmProvider(EntityManagerFactory emf, EdmTypeMapper mapper) {
|
||||||
this.emf = emf;
|
this.emf = emf;
|
||||||
|
@ -153,11 +158,13 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException {
|
public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException {
|
||||||
|
|
||||||
|
CsdlEntityType result = cdslName2Type.get(entityTypeName);
|
||||||
|
if ( result != null ) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Metamodel mm = emf.getMetamodel();
|
Metamodel mm = emf.getMetamodel();
|
||||||
|
|
||||||
CsdlEntityType result = null;
|
|
||||||
|
|
||||||
result = mm.getEntities()
|
result = mm.getEntities()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(et -> entityTypeName.equals(new FullQualifiedName(NAMESPACE, et.getName())))
|
.filter(et -> entityTypeName.equals(new FullQualifiedName(NAMESPACE, et.getName())))
|
||||||
|
@ -165,6 +172,8 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider {
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
|
// save for future use
|
||||||
|
cdslName2Type.put(entityTypeName, result);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.io.InputStream;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
@ -19,6 +20,7 @@ import org.apache.olingo.commons.api.data.Property;
|
||||||
import org.apache.olingo.commons.api.data.ValueType;
|
import org.apache.olingo.commons.api.data.ValueType;
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||||
|
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
|
||||||
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
||||||
import org.apache.olingo.commons.api.format.ContentType;
|
import org.apache.olingo.commons.api.format.ContentType;
|
||||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
|
@ -35,6 +37,7 @@ import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions
|
||||||
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerResult;
|
import org.apache.olingo.server.api.serializer.SerializerResult;
|
||||||
import org.apache.olingo.server.api.uri.UriInfo;
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
|
import org.apache.olingo.server.api.uri.UriParameter;
|
||||||
import org.apache.olingo.server.api.uri.UriResource;
|
import org.apache.olingo.server.api.uri.UriResource;
|
||||||
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
|
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
|
||||||
import org.baeldung.examples.olingo4.repository.RepositoryRegistry;
|
import org.baeldung.examples.olingo4.repository.RepositoryRegistry;
|
||||||
|
@ -110,8 +113,7 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces
|
||||||
Long count = getCount(edmEntitySet, uriInfo);
|
Long count = getCount(edmEntitySet, uriInfo);
|
||||||
|
|
||||||
// Finally: configure the response object: set the body, headers and status code
|
// Finally: configure the response object: set the body, headers and status code
|
||||||
response.setContent(new ByteArrayInputStream(count.toString()
|
response.setContent(new ByteArrayInputStream(count.toString().getBytes()));
|
||||||
.getBytes()));
|
|
||||||
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
|
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
|
||||||
response.setHeader(HttpHeader.CONTENT_TYPE, "text/plain");
|
response.setHeader(HttpHeader.CONTENT_TYPE, "text/plain");
|
||||||
|
|
||||||
|
@ -130,9 +132,9 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces
|
||||||
EntityCollection result = new EntityCollection();
|
EntityCollection result = new EntityCollection();
|
||||||
|
|
||||||
repo.findAll()
|
repo.findAll()
|
||||||
.stream()
|
.stream()
|
||||||
.forEach((it) -> result.getEntities()
|
.forEach((it) -> result.getEntities()
|
||||||
.add(entityMapper.map2entity(edmEntitySet, it)));
|
.add(entityMapper.map2entity(edmEntitySet, it)));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +146,7 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces
|
||||||
* @param uriInfo
|
* @param uriInfo
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) {
|
protected Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) {
|
||||||
|
|
||||||
EdmEntityType type = edmEntitySet.getEntityType();
|
EdmEntityType type = edmEntitySet.getEntityType();
|
||||||
JpaRepository<?, ?> repo = (JpaRepository<?, ?>)repositoryRegistry.getRepositoryForEntity(type);
|
JpaRepository<?, ?> repo = (JpaRepository<?, ?>)repositoryRegistry.getRepositoryForEntity(type);
|
||||||
|
@ -152,5 +154,8 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces
|
||||||
|
|
||||||
return repo.count();
|
return repo.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,13 +63,22 @@ public class JpaEntityMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Object getPropertyValue(Object entry, String name) {
|
public Object getPropertyValue(Object entry, String name) {
|
||||||
try {
|
try {
|
||||||
return PropertyUtils.getProperty(entry,name);
|
return PropertyUtils.getProperty(entry,name);
|
||||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
throw new ODataRuntimeException("[E141] Unable to read property from entity, property=" + name, e);
|
throw new ODataRuntimeException("[E141] Unable to read property from entity, property=" + name, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPropertyValue(Object entry, String name,Object value) {
|
||||||
|
try {
|
||||||
|
PropertyUtils.setProperty(entry,name,value);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new ODataRuntimeException("[E141] Unable to read property from entity, property=" + name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private URI createId(String entitySetName, Object id) {
|
private URI createId(String entitySetName, Object id) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -4,27 +4,19 @@
|
||||||
package org.baeldung.examples.olingo4.processor;
|
package org.baeldung.examples.olingo4.processor;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Member;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.stream.Collectors;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
|
||||||
import javax.persistence.criteria.Predicate;
|
|
||||||
import javax.persistence.criteria.Root;
|
|
||||||
import javax.persistence.metamodel.SingularAttribute;
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
import org.apache.commons.beanutils.PropertyUtils;
|
|
||||||
import org.apache.olingo.commons.api.data.ContextURL;
|
import org.apache.olingo.commons.api.data.ContextURL;
|
||||||
import org.apache.olingo.commons.api.data.Entity;
|
import org.apache.olingo.commons.api.data.Entity;
|
||||||
import org.apache.olingo.commons.api.data.EntityCollection;
|
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||||
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
|
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
|
||||||
import org.apache.olingo.commons.api.edm.EdmType;
|
|
||||||
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
||||||
import org.apache.olingo.commons.api.format.ContentType;
|
import org.apache.olingo.commons.api.format.ContentType;
|
||||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
|
@ -36,10 +28,8 @@ import org.apache.olingo.server.api.ODataRequest;
|
||||||
import org.apache.olingo.server.api.ODataResponse;
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
import org.apache.olingo.server.api.ServiceMetadata;
|
import org.apache.olingo.server.api.ServiceMetadata;
|
||||||
import org.apache.olingo.server.api.processor.EntityProcessor;
|
import org.apache.olingo.server.api.processor.EntityProcessor;
|
||||||
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
|
|
||||||
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
|
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
|
||||||
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerException;
|
|
||||||
import org.apache.olingo.server.api.serializer.SerializerResult;
|
import org.apache.olingo.server.api.serializer.SerializerResult;
|
||||||
import org.apache.olingo.server.api.uri.UriInfo;
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
import org.apache.olingo.server.api.uri.UriParameter;
|
import org.apache.olingo.server.api.uri.UriParameter;
|
||||||
|
@ -48,9 +38,7 @@ import org.apache.olingo.server.api.uri.UriResourceEntitySet;
|
||||||
import org.apache.olingo.server.api.uri.UriResourceNavigation;
|
import org.apache.olingo.server.api.uri.UriResourceNavigation;
|
||||||
import org.baeldung.examples.olingo4.repository.EdmEntityRepository;
|
import org.baeldung.examples.olingo4.repository.EdmEntityRepository;
|
||||||
import org.baeldung.examples.olingo4.repository.RepositoryRegistry;
|
import org.baeldung.examples.olingo4.repository.RepositoryRegistry;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,11 +87,9 @@ public class JpaEntityProcessor implements EntityProcessor {
|
||||||
UriResourceEntitySet rootResourceEntitySet = (UriResourceEntitySet) resourceParts.get(0);
|
UriResourceEntitySet rootResourceEntitySet = (UriResourceEntitySet) resourceParts.get(0);
|
||||||
EdmEntitySet rootEntitySet = rootResourceEntitySet.getEntitySet();
|
EdmEntitySet rootEntitySet = rootResourceEntitySet.getEntitySet();
|
||||||
List<UriParameter> rootPredicates = rootResourceEntitySet.getKeyPredicates();
|
List<UriParameter> rootPredicates = rootResourceEntitySet.getKeyPredicates();
|
||||||
EdmEntityType rootEntityType = rootEntitySet.getEntityType();
|
|
||||||
|
|
||||||
|
|
||||||
if ( resourceParts.size() == 1 ) {
|
if ( resourceParts.size() == 1 ) {
|
||||||
entityStream = readEntity(rootEntitySet,rootPredicates,responseFormat);
|
entityStream = readRootEntity(rootEntitySet,rootPredicates,responseFormat);
|
||||||
}
|
}
|
||||||
else if ( resourceParts.size() == 2 ) {
|
else if ( resourceParts.size() == 2 ) {
|
||||||
UriResource part = resourceParts.get(1);
|
UriResource part = resourceParts.get(1);
|
||||||
|
@ -112,27 +98,7 @@ public class JpaEntityProcessor implements EntityProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
UriResourceNavigation navSegment = (UriResourceNavigation)part;
|
UriResourceNavigation navSegment = (UriResourceNavigation)part;
|
||||||
|
entityStream = readRelatedEntity(request, rootEntitySet,rootPredicates,navSegment.getProperty(),navSegment.getKeyPredicates(),responseFormat);
|
||||||
// We have three scenarios we must handle:
|
|
||||||
// Entity(x)/Related, where Related is a 1:N or M:N relationship => result is a collection
|
|
||||||
// Entity(x)/Related, where Related is a N:1 or 1:1 relationship => result is a single entity
|
|
||||||
// Entity(x)/Related(z), where Related is a 1:N or M:N relationship => result is a single entity
|
|
||||||
if (navSegment.getKeyPredicates().isEmpty()) {
|
|
||||||
if ( isOne2ManyProperty(rootEntityType,navSegment.getProperty())) {
|
|
||||||
entityStream = readRelatedEntities(rootEntitySet,rootPredicates,navSegment.getProperty(),responseFormat);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The relation must point to another entity type, so casting should be safe here
|
|
||||||
EdmEntityType resultType = (EdmEntityType)rootEntityType.getNavigationProperty(navSegment.getProperty().getName()).getType();
|
|
||||||
EdmEntitySet resultEntitySet = entitySetFromType(resultType);
|
|
||||||
|
|
||||||
entityStream = readEntity(resultEntitySet, navSegment.getKeyPredicates(), responseFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entityStream = readRelatedEntity(request, rootEntitySet,rootPredicates,navSegment.getProperty(),navSegment.getKeyPredicates(),responseFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// For now, we'll only allow navigation just to directly linked navs
|
// For now, we'll only allow navigation just to directly linked navs
|
||||||
|
@ -161,14 +127,30 @@ public class JpaEntityProcessor implements EntityProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
private boolean isOne2ManyProperty(EdmEntityType entityType, EdmNavigationProperty property) {
|
// private boolean isOne2ManyProperty(EdmEntityType entityType, EdmNavigationProperty property) {
|
||||||
return entityType.getProperty(property.getName()) != null && property.isCollection();
|
// return entityType.getProperty(property.getName()) != null && property.isCollection();
|
||||||
}
|
//}
|
||||||
|
|
||||||
private InputStream readEntity(EdmEntitySet entitySet, List<UriParameter> keyPredicates,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
private InputStream readRootEntity(EdmEntitySet entitySet, List<UriParameter> keyPredicates,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {
|
||||||
Entity entity = readEntityData(entitySet,keyPredicates);
|
EdmEntityType type = entitySet.getEntityType();
|
||||||
|
JpaRepository repo = registry.getRepositoryForEntity(type);
|
||||||
|
|
||||||
|
// Get key value
|
||||||
|
Long keyValue = getEntityKey(keyPredicates);
|
||||||
|
Optional<Object> entry = repo.findById(keyValue);
|
||||||
|
if ( !entry.isPresent()) {
|
||||||
|
throw new ODataApplicationException(
|
||||||
|
"[E116] NO entity found for the given key",
|
||||||
|
HttpStatusCode.NOT_FOUND.getStatusCode(),
|
||||||
|
Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity e = entityMapper.map2entity(entitySet, entry.get());
|
||||||
|
return serializeEntity(entitySet,e,responseFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream serializeEntity(EdmEntitySet entitySet, Entity entity,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {
|
||||||
ContextURL contextUrl = ContextURL.with().entitySet(entitySet).build();
|
ContextURL contextUrl = ContextURL.with().entitySet(entitySet).build();
|
||||||
// expand and select currently not supported
|
// expand and select currently not supported
|
||||||
EntitySerializerOptions options = EntitySerializerOptions
|
EntitySerializerOptions options = EntitySerializerOptions
|
||||||
|
@ -180,157 +162,101 @@ public class JpaEntityProcessor implements EntityProcessor {
|
||||||
|
|
||||||
SerializerResult serializerResult = serializer.entity(serviceMetadata, entitySet.getEntityType(), entity, options);
|
SerializerResult serializerResult = serializer.entity(serviceMetadata, entitySet.getEntityType(), entity, options);
|
||||||
return serializerResult.getContent();
|
return serializerResult.getContent();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream readRelatedEntities(EdmEntitySet rootEntitySet, List<UriParameter> rootPredicates, EdmNavigationProperty property, ContentType responseFormat) throws ODataApplicationException {
|
// @SuppressWarnings("unchecked")
|
||||||
|
// protected InputStream readRelatedEntities(EdmEntitySet rootEntitySet, List<UriParameter> rootPredicates, EdmNavigationProperty property, ContentType responseFormat) throws ODataApplicationException {
|
||||||
Object jpaEntity = readJPAEntity(rootEntitySet, rootPredicates);
|
//
|
||||||
try {
|
// Object jpaEntity = readJPAEntity(rootEntitySet, rootPredicates);
|
||||||
Object set = PropertyUtils.getProperty(jpaEntity, property.getName());
|
// try {
|
||||||
EdmEntitySet entitySet = entitySetFromType(property.getType());
|
// Collection<Object> set = (Collection<Object>)PropertyUtils.getProperty(jpaEntity, property.getName());
|
||||||
ContextURL contextUrl = ContextURL
|
// EdmEntitySet entitySet = entitySetFromType(property.getType());
|
||||||
.with()
|
// ContextURL contextUrl = ContextURL
|
||||||
.entitySet(entitySet)
|
// .with()
|
||||||
.build();
|
// .entitySet(entitySet)
|
||||||
|
// .build();
|
||||||
EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions
|
//
|
||||||
.with()
|
// EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions
|
||||||
.contextURL(contextUrl)
|
// .with()
|
||||||
.build();
|
// .contextURL(contextUrl)
|
||||||
|
// .build();
|
||||||
EntityCollection result = new EntityCollection();
|
//
|
||||||
|
// EntityCollection result = new EntityCollection();
|
||||||
((Collection<Object>)set)
|
//
|
||||||
.stream()
|
// set.stream()
|
||||||
.map((o) -> this.entityMapper.map2entity(entitySet, o))
|
// .map((o) -> this.entityMapper.map2entity(entitySet, o))
|
||||||
.forEach((e) -> result.getEntities().add(e));
|
// .forEach((e) -> result.getEntities().add(e));
|
||||||
|
//
|
||||||
ODataSerializer serializer = odata.createSerializer(responseFormat);
|
// ODataSerializer serializer = odata.createSerializer(responseFormat);
|
||||||
SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, property.getType(), result, options);
|
// SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, property.getType(), result, options);
|
||||||
return serializerResult.getContent();
|
// return serializerResult.getContent();
|
||||||
}
|
// }
|
||||||
catch(Exception ex) {
|
// catch(Exception ex) {
|
||||||
throw new ODataRuntimeException("[E181] Error accessing database", ex);
|
// throw new ODataRuntimeException("[E181] Error accessing database", ex);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "serial", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
private InputStream readRelatedEntity(ODataRequest request, EdmEntitySet rootEntitySet, List<UriParameter> rootPredicates, EdmNavigationProperty property, List<UriParameter> predicates, ContentType responseFormat) throws ODataApplicationException, SerializerException {
|
private InputStream readRelatedEntity(ODataRequest request, EdmEntitySet entitySet, List<UriParameter> rootPredicates, EdmNavigationProperty property, List<UriParameter> parentPredicates, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {
|
||||||
|
|
||||||
|
|
||||||
JpaSpecificationExecutor<Object> rootRepo = (JpaSpecificationExecutor<Object>)registry.getRepositoryForEntity(rootEntitySet.getEntityType());
|
JpaRepository<Object,Object> repo = (JpaRepository<Object,Object>)registry.getRepositoryForEntity(entitySet.getEntityType());
|
||||||
JpaSpecificationExecutor<Object> repo = (JpaSpecificationExecutor<Object>)registry.getRepositoryForEntity(property.getType());
|
EdmEntityRepository<Object> relatedRepo = (EdmEntityRepository<Object>)registry.getRepositoryForEntity(property.getType());
|
||||||
|
|
||||||
// We assume here that we have a bi-directional 1:N relationship, so we'll
|
// We assume here that we have a bi-directional 1:N relationship, so we'll
|
||||||
// always have a property in the child entity that points to the parent
|
// always have a property in the child entity that points to the parent
|
||||||
Class<?> rootClass = ((EdmEntityRepository)rootRepo).getEntityClass();
|
Class<?> rootClass = ((EdmEntityRepository)repo).getEntityClass();
|
||||||
Class<?> childClass = ((EdmEntityRepository)repo).getEntityClass();
|
Class<?> relatedClass = ((EdmEntityRepository)relatedRepo).getEntityClass();
|
||||||
|
|
||||||
SingularAttribute fk = emf.getMetamodel()
|
SingularAttribute fk = emf.getMetamodel()
|
||||||
.entity(childClass)
|
.entity(rootClass)
|
||||||
.getSingularAttributes()
|
.getSingularAttributes()
|
||||||
.stream()
|
.stream()
|
||||||
.filter((attr) -> attr.isAssociation() && attr.getJavaType().isAssignableFrom(rootClass))
|
.filter((attr) -> {
|
||||||
|
boolean b = attr.isAssociation() && attr.getJavaType().isAssignableFrom(relatedClass);
|
||||||
|
return b;
|
||||||
|
})
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
SingularAttribute pk = emf.getMetamodel()
|
|
||||||
.entity(childClass)
|
|
||||||
.getId(Long.class);
|
|
||||||
|
|
||||||
SingularAttribute rootPk = emf.getMetamodel()
|
|
||||||
.entity(rootClass)
|
|
||||||
.getId(Long.class);
|
|
||||||
|
|
||||||
if ( fk == null ) {
|
if ( fk == null ) {
|
||||||
throw new ODataRuntimeException("[E230] No singular attribute of child class '" + childClass.getName() + "' found" );
|
throw new ODataRuntimeException("[E230] No singular attribute of child class '" + relatedClass.getName() + "' found" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Long pkValue = getEntityKey(rootPredicates);
|
||||||
Specification spec = new Specification() {
|
EntityManager em = this.emf.createEntityManager();
|
||||||
@Override
|
try {
|
||||||
public Predicate toPredicate(Root root, CriteriaQuery q, CriteriaBuilder cb) {
|
// Read data from DB
|
||||||
|
Object root = em.find(rootClass, pkValue);
|
||||||
|
Object related = this.entityMapper.getPropertyValue(root, fk.getName());
|
||||||
|
|
||||||
try {
|
EdmEntitySet relatedEntitySet = entitySetFromType(property.getType());
|
||||||
Object rootInstance = rootClass.newInstance();
|
Entity e = entityMapper.map2entity(relatedEntitySet, related);
|
||||||
PropertyUtils.setProperty(rootInstance, rootPk.getName(), getEntityKey(rootEntitySet.getEntityType(),rootPredicates));
|
return serializeEntity(relatedEntitySet,e,responseFormat);
|
||||||
|
}
|
||||||
final Predicate p = cb.and(
|
finally {
|
||||||
cb.equal(
|
em.close();
|
||||||
root.get(pk),
|
}
|
||||||
getEntityKey(property.getType(),predicates)),
|
|
||||||
cb.equal(
|
|
||||||
root.get(fk),
|
|
||||||
rootInstance));
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
catch(Exception ex) {
|
|
||||||
throw new ODataRuntimeException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Read data from DB
|
|
||||||
EdmEntitySet relatedEntitySet = entitySetFromType(property.getType());
|
|
||||||
EntityCollection data = new EntityCollection();
|
|
||||||
|
|
||||||
repo.findAll(spec)
|
|
||||||
.stream()
|
|
||||||
.forEach((entry) -> data.getEntities().add(entityMapper.map2entity(relatedEntitySet, entry)));
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
ODataSerializer serializer = odata.createSerializer(responseFormat);
|
|
||||||
|
|
||||||
// 4th: Now serialize the content: transform from the EntitySet object to InputStream
|
|
||||||
EdmEntityType edmEntityType = relatedEntitySet.getEntityType();
|
|
||||||
ContextURL contextUrl = ContextURL.with()
|
|
||||||
.entitySet(relatedEntitySet)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
final String id = request.getRawBaseUri() + "/" + relatedEntitySet.getName();
|
|
||||||
EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with()
|
|
||||||
.id(id)
|
|
||||||
.contextURL(contextUrl)
|
|
||||||
.build();
|
|
||||||
SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, data, opts);
|
|
||||||
InputStream serializedContent = serializerResult.getContent();
|
|
||||||
|
|
||||||
|
|
||||||
return serializedContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns a speficic entity given its primary key
|
|
||||||
* @param edmEntitySet
|
|
||||||
* @param keyPredicates
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected Entity readEntityData(EdmEntitySet edmEntitySet, List<UriParameter> keyPredicates) throws ODataApplicationException {
|
|
||||||
|
|
||||||
Object jpaEntry = readJPAEntity(edmEntitySet, keyPredicates);
|
|
||||||
Entity e = entityMapper.map2entity(edmEntitySet, jpaEntry);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object readJPAEntity(EdmEntitySet edmEntitySet, List<UriParameter> keyPredicates) throws ODataApplicationException {
|
|
||||||
EdmEntityType type = edmEntitySet.getEntityType();
|
|
||||||
JpaRepository<Object,Object> repo = (JpaRepository<Object,Object>)registry.getRepositoryForEntity(type);
|
|
||||||
|
|
||||||
// Get key value
|
|
||||||
Object keyValue = getEntityKey(type,keyPredicates);
|
|
||||||
Object entry = repo
|
|
||||||
.findById(keyValue)
|
|
||||||
.orElseThrow(
|
|
||||||
() -> new ODataApplicationException("[E116] NO entity found for the given key",
|
|
||||||
HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH));
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getEntityKey(EdmEntityType type, List<UriParameter> keyPredicates) {
|
// @SuppressWarnings("unchecked")
|
||||||
|
// private Object readJPAEntity(EdmEntitySet edmEntitySet, List<UriParameter> keyPredicates) throws ODataApplicationException {
|
||||||
|
// EdmEntityType type = edmEntitySet.getEntityType();
|
||||||
|
// JpaRepository<Object,Object> repo = (JpaRepository<Object,Object>)registry.getRepositoryForEntity(type);
|
||||||
|
//
|
||||||
|
// // Get key value
|
||||||
|
// Object keyValue = getEntityKey(type,keyPredicates);
|
||||||
|
// Object entry = repo
|
||||||
|
// .findById(keyValue)
|
||||||
|
// .orElseThrow(
|
||||||
|
// () -> new ODataApplicationException("[E116] NO entity found for the given key",
|
||||||
|
// HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH));
|
||||||
|
//
|
||||||
|
// return entry;
|
||||||
|
// }
|
||||||
|
|
||||||
|
private Long getEntityKey(List<UriParameter> keyPredicates) {
|
||||||
|
|
||||||
if ( keyPredicates.size() > 1 ) {
|
if ( keyPredicates.size() > 1 ) {
|
||||||
throw new ODataRuntimeException("[E131] Composite keys are not supported");
|
throw new ODataRuntimeException("[E131] Composite keys are not supported");
|
||||||
|
|
|
@ -5,23 +5,25 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class RepositoryRegistry {
|
public class RepositoryRegistry {
|
||||||
|
|
||||||
private Map<String,EdmEntityRepository<?>> repositoriesByClassName = new HashMap<>();
|
private Map<String,JpaRepository<?,?>> repositoriesByClassName = new HashMap<>();
|
||||||
|
|
||||||
public RepositoryRegistry(List<EdmEntityRepository<?>> allRepositories) {
|
public RepositoryRegistry(List<EdmEntityRepository<?>> allRepositories) {
|
||||||
|
|
||||||
allRepositories.stream().forEach((r) ->
|
allRepositories.stream()
|
||||||
repositoriesByClassName.put(r.getEdmEntityName(),(EdmEntityRepository<?>)r));
|
.forEach((r) ->
|
||||||
|
repositoriesByClassName.put(r.getEdmEntityName(),(JpaRepository<?,?>)r));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public EdmEntityRepository<?> getRepositoryForEntity(EdmEntityType entityType) {
|
public JpaRepository<?,?> getRepositoryForEntity(EdmEntityType entityType) {
|
||||||
EdmEntityRepository<?> repo = repositoriesByClassName.get(entityType.getName());
|
JpaRepository<?,?> repo = repositoriesByClassName.get(entityType.getName());
|
||||||
return repo;
|
return repo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@ server:
|
||||||
spring:
|
spring:
|
||||||
jpa:
|
jpa:
|
||||||
show-sql: true
|
show-sql: true
|
||||||
open-in-view: false
|
open-in-view: true
|
||||||
hibernate:
|
hibernate:
|
||||||
ddl-auto: update
|
ddl-auto: update
|
||||||
|
|
Loading…
Reference in New Issue