[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,12 +35,15 @@ 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; | ||||||
|         this.typeMapper = mapper; |         this.typeMapper = mapper; | ||||||
| @ -154,10 +159,12 @@ 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"); | ||||||
| 
 | 
 | ||||||
| @ -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); | ||||||
| @ -153,4 +155,7 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces | |||||||
|         return repo.count(); |         return repo.count(); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ 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) { | ||||||
| @ -71,6 +71,15 @@ public class JpaEntityMapper { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     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 { | ||||||
|             return new URI(entitySetName + "(" + String.valueOf(id) + ")"); |             return new URI(entitySetName + "(" + String.valueOf(id) + ")"); | ||||||
|  | |||||||
| @ -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,28 +98,8 @@ public class JpaEntityProcessor implements EntityProcessor { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             UriResourceNavigation navSegment = (UriResourceNavigation)part; |             UriResourceNavigation navSegment = (UriResourceNavigation)part; | ||||||
|              |  | ||||||
|             // 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);                        |             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 | ||||||
|             throw new ODataApplicationException("[E109] Multi-level navigation not supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); |             throw new ODataApplicationException("[E109] Multi-level navigation not supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); | ||||||
| @ -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(); | ||||||
|  |     //} | ||||||
|  | 
 | ||||||
|  |     @SuppressWarnings({ "rawtypes", "unchecked" }) | ||||||
|  |     private InputStream readRootEntity(EdmEntitySet entitySet, List<UriParameter> keyPredicates,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {         | ||||||
|  |         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); | ||||||
|         } |         } | ||||||
|        |        | ||||||
|     private InputStream readEntity(EdmEntitySet entitySet, List<UriParameter> keyPredicates,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { |         Entity e = entityMapper.map2entity(entitySet, entry.get());         | ||||||
|          |         return serializeEntity(entitySet,e,responseFormat);         | ||||||
|         Entity entity = readEntityData(entitySet,keyPredicates); |     } | ||||||
|      |      | ||||||
|  |     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 { | ||||||
|  | //            Collection<Object> set = (Collection<Object>)PropertyUtils.getProperty(jpaEntity, property.getName()); | ||||||
|  | //            EdmEntitySet entitySet = entitySetFromType(property.getType()); | ||||||
|  | //            ContextURL contextUrl = ContextURL | ||||||
|  | //              .with() | ||||||
|  | //              .entitySet(entitySet) | ||||||
|  | //              .build(); | ||||||
|  | //             | ||||||
|  | //            EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions | ||||||
|  | //              .with() | ||||||
|  | //              .contextURL(contextUrl) | ||||||
|  | //              .build(); | ||||||
|  | //             | ||||||
|  | //            EntityCollection result = new EntityCollection(); | ||||||
|  | //             | ||||||
|  | //            set.stream() | ||||||
|  | //              .map((o) -> this.entityMapper.map2entity(entitySet, o)) | ||||||
|  | //              .forEach((e) -> result.getEntities().add(e)); | ||||||
|  | // | ||||||
|  | //            ODataSerializer serializer = odata.createSerializer(responseFormat);             | ||||||
|  | //            SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, property.getType(), result, options); | ||||||
|  | //            return serializerResult.getContent(); | ||||||
|  | //        } | ||||||
|  | //        catch(Exception ex) { | ||||||
|  | //            throw new ODataRuntimeException("[E181] Error accessing database", ex); | ||||||
|  | //        } | ||||||
|  | //    } | ||||||
|      |      | ||||||
|         Object jpaEntity = readJPAEntity(rootEntitySet, rootPredicates); |     @SuppressWarnings({ "rawtypes", "unchecked" }) | ||||||
|         try { |     private InputStream readRelatedEntity(ODataRequest request, EdmEntitySet entitySet, List<UriParameter> rootPredicates, EdmNavigationProperty property, List<UriParameter> parentPredicates, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { | ||||||
|             Object set = PropertyUtils.getProperty(jpaEntity, property.getName()); |  | ||||||
|             EdmEntitySet entitySet = entitySetFromType(property.getType()); |  | ||||||
|             ContextURL contextUrl = ContextURL |  | ||||||
|               .with() |  | ||||||
|               .entitySet(entitySet) |  | ||||||
|               .build(); |  | ||||||
|              |  | ||||||
|             EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions |  | ||||||
|               .with() |  | ||||||
|               .contextURL(contextUrl) |  | ||||||
|               .build(); |  | ||||||
|              |  | ||||||
|             EntityCollection result = new EntityCollection(); |  | ||||||
|              |  | ||||||
|             ((Collection<Object>)set) |  | ||||||
|               .stream() |  | ||||||
|               .map((o) -> this.entityMapper.map2entity(entitySet, o)) |  | ||||||
|               .forEach((e) -> result.getEntities().add(e)); |  | ||||||
| 
 |  | ||||||
|             ODataSerializer serializer = odata.createSerializer(responseFormat);             |  | ||||||
|             SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, property.getType(), result, options); |  | ||||||
|             return serializerResult.getContent(); |  | ||||||
|         } |  | ||||||
|         catch(Exception ex) { |  | ||||||
|             throw new ODataRuntimeException("[E181] Error accessing database", ex); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     @SuppressWarnings({ "rawtypes", "serial", "unchecked" }) |  | ||||||
|     private InputStream readRelatedEntity(ODataRequest request, EdmEntitySet rootEntitySet, List<UriParameter> rootPredicates, EdmNavigationProperty property, List<UriParameter> predicates, ContentType responseFormat) throws ODataApplicationException, SerializerException { |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         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 |  | ||||||
|             public Predicate toPredicate(Root root, CriteriaQuery q, CriteriaBuilder cb) { |  | ||||||
|                  |  | ||||||
|         try { |         try { | ||||||
|                     Object rootInstance = rootClass.newInstance(); |  | ||||||
|                     PropertyUtils.setProperty(rootInstance, rootPk.getName(), getEntityKey(rootEntitySet.getEntityType(),rootPredicates)); |  | ||||||
|                      |  | ||||||
|                     final Predicate p = cb.and( |  | ||||||
|                         cb.equal( |  | ||||||
|                           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  |             // Read data from DB  | ||||||
|  |             Object root = em.find(rootClass, pkValue);             | ||||||
|  |             Object related = this.entityMapper.getPropertyValue(root, fk.getName()); | ||||||
|  |                  | ||||||
|             EdmEntitySet relatedEntitySet = entitySetFromType(property.getType());         |             EdmEntitySet relatedEntitySet = entitySetFromType(property.getType());         | ||||||
|         EntityCollection data = new EntityCollection(); |             Entity e = entityMapper.map2entity(relatedEntitySet, related);                | ||||||
|          |             return serializeEntity(relatedEntitySet,e,responseFormat); | ||||||
|         repo.findAll(spec) |         } | ||||||
|            .stream() |         finally { | ||||||
|            .forEach((entry) -> data.getEntities().add(entityMapper.map2entity(relatedEntitySet, entry))); |             em.close(); | ||||||
| 
 |         } | ||||||
|         //  |  | ||||||
|          |  | ||||||
|         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; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | //    @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) { | ||||||
|      * 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) { |  | ||||||
|          |          | ||||||
|         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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user