From 982aaeda6c86ffaa5f7fa428ab121e1a90a53392 Mon Sep 17 00:00:00 2001 From: Oliver Grande Date: Wed, 11 Dec 2024 13:41:33 +0100 Subject: [PATCH] Defect/version 2.3.1 (#425) * Feature/transient fields (#142) * Fix null pointer if no enumerations are part of servcie * Enable HAS and enumeration as return type of operations * Allow Enumerations as operation parameter * Provide java based operations converted enumeration * Add SourceClear addon * Delete SourceClean addon * Enumerations at UDF functions - Works for bound functions - Works for functions with import * Correct unit tests * Enable multiple values for flags enumerations * Switch detection default between Embedded and Entity type * Allow collection attributes for metadata * Enable query without collection attributes * Rework query result conversion to reduce memory consumtion * Missing Metadata pom * First step entity with collections as return of function/action * Bugfix: Expand on Parent with $filter on navigation path * Enable the use of Join Tables - Filter on navigation via Join Table generally not supported * Create new query for inlinecount * Enable Join Tables@Navigation Filter - Not working mapped associations - Not working $count * Enable Join Tables@Navigation Filter - With mapped associations - With $count, know issue EclipsLink two sub types * Increase Version --> 0.2.6 * Remove deprecated JPAExecutableQuery * Bugfix: unidirectional join table based association * Access collection properties via navigation - New version * Access collection properties w and w/o $select * Access collection properties which are part of complex property * CUD operations on collection properties * Filter on collection properties pre optimization * Filter on collection properties any/all * Filter on collection w/o filter on $count and orderby $count * Correct issue #29 - Correct /$count implementation in JPAJoinQuery - Clean-up Hibernate differences -- Subquery from clause -- Id Class determination * Increase Version to 0.2.7 * Enable ..@odata.navigationLink in case of odata.metadata=full - links@complex types not yet working * Preparation for solution of issue OLINGO-1143 * Correct NullPointer and some clean-ups * Support order by $count - Increase version to 0.2.8 * Intermediate merge clean-up * Solve merge problem navigate complex collections * Resolve merge conflict converter * Correct error collection property and expand=* * Enable filter $count on collection property * Update version and url * Create and use page provider * Recreate change for solution of issue OLINGO-1143 * Finalize top level server driven paging * Correct string handling error * Correct link problem * Enable skiptoken to have other type than String * Move paging so next request injects old uriInfo correctly * Enable deep insert via complex properties * Ignore test for next commit * Enable create of a new entity linked by a to one using PATCH * Update to Olingo 4.5.0 - use new Olingo version - adopt one test to changed @odata.context content * Collection attributes rework. Issue #60 - Change processor pom -> javax.servlet became provided * Enable annotation for properties to mark them authorization relevant * Enable multiple protected properties at complex attributes * Rework EdmProtectedBy annotation to handle multiple claims at complex * Process protection * Rework handling of ignored protected * Made inner class static * Fixing issue #60 * $count query not working correctly on complex collection attributes * Various small bugs - Reorg. pom.xml - Correct http status on empty result - Correct empty check for collection properties * Correct typo in interface JPAODataPagingProvider * Prepare JPAODataDatabaseTableFunction for paging * Change to HSQLDB * Remove function from sql-file to work around problems with Derby * Correct NullPointerException EdmEntitySetResult * Determine result of create dependent based on before image * EntityType getAttribute did not return value for embedded id * Provide CUD example and correct query status codes * Correct query response * Maven Archetype for Spring based service * Upgrade to Junit5 to get support for Java > 1.8 * Extract interface for better unit test support - Cleanup tests * Clean-up interface implementation * Add SQL function handling * Complete DB function changes * Clean-up test class * Clean-up test class * Update Version number * Update Version number * Additional test for API classes * Enable suppress of wildcard in metadata * Enable wildcards during query processing * Increase information on error during filter * Support of PUT on collection properties and primitive properties * Fix Null Pointer on PATCH with return != minimal * Claims where not respected by queries issue #69 part one - /$count - ?$count=true - paging queries * Claims where not respected by queries issue #69 part two - $filter - Update on Olingo 4.6.0 * Restrict the DISTINCT to protections only * Increase test coverage - New tests - Rework vocabulary handling * Cleanup Vocabularies II - Add Action and Function - Remove NavigationProperty and dependent * Additional test and solution of issue #78 * Enable new annotation EdmVisibleFor at properties * Introduction of Request Context - Deprecation of two variants of JPAODataGetHandler.process - Increase test coverage * Restrict EdmVisiableFor to nullable non key attributes * Skip properties from selection that do not belong to provided group * Handle collection properties and navigation path * Enable groups at complex collections * Handle OrderBy clause * Correct unit test * Rework test containing images * Rework context handling - Move of cud handler to request context - Move of DebugSupport to request context (is request specific because of isUserAuthorized) - Introduction of builder for Service Context to get a leaner creation of handler * Providing groups during modifying requests * Re-enable old shortcut with late metadata provisioning * Update pom for missing jackson dependency * Update Archetype to version 0.3.4 * Update Version * Extension of session context, so an emf can be provided * Ignore annotation qualified if empty * Go back to Olingo JSON deserializer * Add qualifier to annotation * Increase release * Clean-up JPAEdmNameBuilder * Preparation of custom name builder - Create public interface - replace class by new interface * Revoke test adoption * Providing custome name builder * Update annotation EdmFunction * Increase release * Adopt archetype - Simplify service - Add integration test * Modify example did not persist on create * Deep Insert did not responded deep * Always select ETag * Complete ETag handling * Missing Context Changes * Reset unit test to current pushed state * Increase test coverage * Adopt test to real number of complex types * Enable V4.01 JSON format as request and response * Additional Integration tests support OData V4.01 JSON * Allow usage of different types of transaction * Increase Spring support * Bugfix/issue83 (#120) * Update Version * Extension of session context, so an emf can be provided * Preparation of custom name builder - Create public interface - replace class by new interface * Revoke test adoption * Providing custome name builder * Update annotation EdmFunction * Increase release * Adopt archetype - Simplify service - Add integration test * Modify example did not persist on create * Deep Insert did not responded deep * Always select ETag * Complete ETag handling * Missing Context Changes * Reset unit test to current pushed state * Increase test coverage * Adopt test to real number of complex types * Enable V4.01 JSON format as request and response * Additional Integration tests support OData V4.01 JSON * Allow usage of different types of transaction * Increase Spring support * Restrict $expand select by key range * Support root with navigation like AdministrativeDivision(...)/Children * Protect dilution of test coverage by test package (#133) * Increase release * Increase release (#136) * Protect dilution of test coverage by test package (#135) * Remove deprecated artifacts (#134) * Remove deprecated artefacts * Missing test adoptions * Upgrade Olingo version and processor version * Feature/transient fields (#137) * Increase release * Upgrade Olingo version and processor version * Prevent NPE on expand empty result (#138) * Correct SonarQube and SpotBug hints * Feature/transient fields (#139) * Increase release * Upgrade Olingo version and processor version * Correct SonarQube and SpotBug hints * SpotBugs and clean-ups * Build metadata I * First draft of criteria builder and query implementation (#140) * First draft of criteria builder and query implementation * Add Transient * First join version * Correct structured type * Test adoption was missing * Update criteria builder * Solve enum error * Support aggregation function * Correct buildInverseJoinColumns() error * Add Test buildInverseJoinColumns() error * Enable table join without entity type * Correct Error table name * Own test for JPAEdmProvider and correct name builder error * Additional test * Support parallel processing of batch requests * Complete synchronized creation of metadata * Enable transient field calculator * Suppress transient fields at $filter and $orderby * Enable transient collections and collections with transient attributes * Additional tests for changing operations * Enable absolute path in url * Add sonar plugin (#144) * Add sonar plugin * Update pom with sonar plugin * Feature/logging (#145) * Add sonar plugin * Update pom with sonar plugin * Remove old xmake version * Feature/logging (#147) * Add sonar plugin * Update pom with sonar plugin * Remove old xmake version * Logging as part of standard debugger * Generic authorization check for JPAExampleCUDRequestHandler * Feature/logging (#148) * Add sonar plugin * Update pom with sonar plugin * Remove old xmake version * Logging as part of standard debugger * Generic authorization check for JPAExampleCUDRequestHandler * Update xmake version * Feature/logging (#150) * Add sonar plugin * Update pom with sonar plugin * Remove old xmake version * Logging as part of standard debugger * Generic authorization check for JPAExampleCUDRequestHandler * Update xmake version * Clean-up sonar issues * Feature/logging (#151) * Add sonar plugin * Update pom with sonar plugin * Remove old xmake version * Logging as part of standard debugger * Generic authorization check for JPAExampleCUDRequestHandler * Update xmake version * Clean-up sonar issues * Update build status on read.me * New badges * Update README.md * Update README.md * Feature/logging (#152) * Add sonar plugin * Update pom with sonar plugin * Remove old xmake version * Logging as part of standard debugger * Generic authorization check for JPAExampleCUDRequestHandler * Update xmake version * Clean-up sonar issues * Update build status on read.me * New badges * Clean-up sonar issues * Create additional test for debugger * Add tests for debugger * Update README.md * Replace database derby -> hsqldb * Update README.md (#153) * Feature/logging (#154) * Add sonar plugin * Update pom with sonar plugin * Remove old xmake version * Logging as part of standard debugger * Generic authorization check for JPAExampleCUDRequestHandler * Update xmake version * Clean-up sonar issues * Update build status on read.me * New badges * Clean-up sonar issues * Create additional test for debugger * Add tests for debugger * Update README.md * Replace database derby -> hsqldb * Cleanup sonar issue * Increase test coverage for criteria builder (#155) * Feature/criteria builder (#156) * Increase test coverage for criteria builder * Replace double implementation by mocks * Update README.md (#157) * Feature/criteria builder (#158) * Increase test coverage for criteria builder * Replace double implementation by mocks * Rework vocabulary read * Feature/criteria builder (#159) * Increase test coverage for criteria builder * Replace double implementation by mocks * Rework vocabulary read * Add method to retrieve all claims * Update README.md (#160) * Update README.md * Update README.md * Remove potential null pointer (#161) * Bugfix/sonar issues (#162) * Remove potential null pointer * Remove potential Null Pointer * Bugfix/sonar issues (#163) * Remove potential null pointer * Remove potential Null Pointer * Remove potential Null Pointer * Bugfix/sonar issues (#164) * Remove potential null pointer * Remove potential Null Pointer * Remove potential Null Pointer * Additional clean-ups * Work on soanr issues * Bugfix/sonar issues (#165) * Remove potential null pointer * Remove potential Null Pointer * Remove potential Null Pointer * Additional clean-ups * Work on soanr issues * Additional cleanups * Feature/release 1.0.0 (#170) * Bugfix/typo package (#168) * Update version to 1.0.0-RC * Rename package to ...metadata.core.edm.mapper.extension * Rename message constants * Correct typos in method names * Rollback change to Optional * Support Include Annotation (#169) * Feature/include annotation (#171) * Support Include Annotation * Increase test coverage transient properties * Bugfix/issue98 (#173) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Bugfix/issue98 (#174) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * sonar issues (#175) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Bugfix/issue98 (#176) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Clean-up sonar issues * Bugfix/issue98 (#177) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Clean-up sonar issues * Delete intermediate code * Feature/criteria builder (#178) * Increase test coverage for criteria builder * Replace double implementation by mocks * Rework vocabulary read * Add method to retrieve all claims * Add README.md and correct spelling errors * Add README.md and correct spelling errors (#179) * Feature/release 1.0.0 (#192) * Bugfix/typo package (#168) * Update version to 1.0.0-RC * Rename package to ...metadata.core.edm.mapper.extension * Rename message constants * Correct typos in method names * Rollback change to Optional * Support Include Annotation (#169) * Feature/include annotation (#171) * Support Include Annotation * Increase test coverage transient properties * Bugfix/syntax errors (#181) * Feature/release 1.0.0 (#170) * Bugfix/typo package (#168) * Update version to 1.0.0-RC * Rename package to ...metadata.core.edm.mapper.extension * Rename message constants * Correct typos in method names * Rollback change to Optional * Support Include Annotation (#169) * Feature/include annotation (#171) * Support Include Annotation * Increase test coverage transient properties * Bugfix/issue98 (#173) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Bugfix/issue98 (#174) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * sonar issues (#175) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Bugfix/issue98 (#176) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Clean-up sonar issues * Bugfix/issue98 (#177) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Clean-up sonar issues * Delete intermediate code * Feature/criteria builder (#178) * Increase test coverage for criteria builder * Replace double implementation by mocks * Rework vocabulary read * Add method to retrieve all claims * Add README.md and correct spelling errors * Add README.md and correct spelling errors * Correct syntax errors metadata * Clean-up typos * Rework build of OrderBy creation (#183) * Bugfix/syntax errors (#185) * Feature/release 1.0.0 (#170) * Bugfix/typo package (#168) * Update version to 1.0.0-RC * Rename package to ...metadata.core.edm.mapper.extension * Rename message constants * Correct typos in method names * Rollback change to Optional * Support Include Annotation (#169) * Feature/include annotation (#171) * Support Include Annotation * Increase test coverage transient properties * Bugfix/issue98 (#173) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Bugfix/issue98 (#174) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * sonar issues (#175) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Bugfix/issue98 (#176) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Clean-up sonar issues * Bugfix/issue98 (#177) * Support java.time.Instant and BigInteger * Correct issue #98 - Correct typo - Make DatabaseProcessor public * Enhance documentation of transient property calculator * Clean-up sonar issue * Clean-up sonar * Clean-up author * Meaningfull error message on $apply * Service Context creates Emf Wrapper if present in class path * Suppoprt of MappedSuperclass * $top and $skip use order by primary key * Clean-up sonar issues * Clean-up sonar issues * Delete intermediate code * Feature/criteria builder (#178) * Increase test coverage for criteria builder * Replace double implementation by mocks * Rework vocabulary read * Add method to retrieve all claims * Add README.md and correct spelling errors * Add README.md and correct spelling errors * Add README.md and correct spelling errors (#179) * Correct syntax errors metadata * Clean-up typos * Update Version -> 1.0.0 * Usage of builder to create external request context (#187) * Bugfix/continue on error (#189) * Move batch processor from API to PROCESSOR package * Correct continue-on-error handling * Support generated Id in example CUD handler (#190) * Support generated Id in example CUD handler * Correct failing test * Adoption of archetype to 1.0.0 (#191) * Adoption of archetype to 1.0.0 * Correct sql error * Clean-up sonar issues * Correct criteria builder implementation (#193) * Feature/criteria builder (#194) * Correct criteria builder implementation * Enable sub query as FROM * Update tests * Update sonar issues * Update sonar issue * Add mutation testing to processor and metadata * Feature/criteria builder (#195) * Correct criteria builder implementation * Enable sub query as FROM * Update tests * Update sonar issues * Update sonar issue * Add mutation testing to processor and metadata * Eliminate duplicate code * Feature/criteria builder (#196) * Correct criteria builder implementation * Enable sub query as FROM * Update tests * Update sonar issues * Update sonar issue * Add mutation testing to processor and metadata * Eliminate duplicate code * Add Locale to request context, so it can be set from user data * Correct request context copy * Feature/criteria builder (#197) * Correct criteria builder implementation * Enable sub query as FROM * Update tests * Update sonar issues * Update sonar issue * Add mutation testing to processor and metadata * Eliminate duplicate code * Add Locale to request context, so it can be set from user data * Correct request context copy * Missing transient fields at $expand * Add tests * Feature/criteria builder (#198) * Correct criteria builder implementation * Enable sub query as FROM * Update tests * Update sonar issues * Update sonar issue * Add mutation testing to processor and metadata * Eliminate duplicate code * Add Locale to request context, so it can be set from user data * Correct request context copy * Missing transient fields at $expand * Add tests * Fix GeneratedKey problem * Feature/criteria builder (#199) * Correct criteria builder implementation * Enable sub query as FROM * Update tests * Update sonar issues * Update sonar issue * Add mutation testing to processor and metadata * Eliminate duplicate code * Add Locale to request context, so it can be set from user data * Correct request context copy * Missing transient fields at $expand * Add tests * Fix GeneratedKey problem * Intermediate state * Enable next block of queries * Expand with Join Tables * Last unit test corrections * Eliminate typos * Finalize changes * missing variable usage (#200) * missing variable usage * Increase processor version * Clean-up Sonar issues (#201) * Bugfix/no mapper for operations (#202) * Clean-up Sonar issues * Add test for type mapping for actions and java function + Cleanup test classes * Feature/1.0.1 (#203) * Correct criteria builder implementation * Enable sub query as FROM * Update tests * Update sonar issues * Update sonar issue * Add mutation testing to processor and metadata * Eliminate duplicate code * Add Locale to request context, so it can be set from user data * Correct request context copy * Missing transient fields at $expand * Add tests * Fix GeneratedKey problem * Change version to 1.0.1 * New version (#204) * Bugfix/filter eq withdate (#205) * New version * Support filter on Date and DateTime * Correct precision * Change another test * Us generated alias for column selection (#206) * Upgrade Version (#207) * Us generated alias for column selection * Upgrade version * Reduce complexity (#209) * ALL did not work with functions like startswith (#210) * Update version (#208) * Entity Set Path @ DB Functions (#211) * Feature/new archetype (#212) * Clean-up folder name * Create archetype repo * Use copy of spring archetype as start * Enable named queries * Feature/new archetype (#213) * Clean-up folder name * Create archetype repo * Use copy of spring archetype as start * Enable named queries * Allow Star for non string claim properties * Add Equals method to DeepProtectedExample * Feature/new archetype (#214) * Clean-up folder name * Create archetype repo * Use copy of spring archetype as start * Enable named queries * Allow Star for non string claim properties * Add Equals method to DeepProtectedExample * Enable grant access to all for non string fields read * Replace Reflections API by Reflections8 (#215) * Support entitytypes singeltons (#216) * New annotation to make singletons and entity types - Update to olingo 4.8.0 - Deprecate EdmAsEntitySet - Read not ready * Update README.md (#218) * Update README.md * Update README.md * Update README.md * Solve issue 136 (#217) * Solve issue 136 * Eliminate hyphen * Eliminate WhiteSource detected vulnerabilities (#219) * Eliminate WhiteSource detected vulnerabilities * Add now required dependency * Remove setExternalName from Metadata Post Processor (#220) * Support entitytypes singeltons (#221) * New annotation to make singletons and entity types - Update to olingo 4.8.0 - Deprecate EdmAsEntitySet * Wrong entity type on singleton only * Add java doc to TopLevelElementRepresentation * Finalize singleton metadata handling * Clean-up test classes * Add option to retrieve Singleton from SD * Rename test class * Support entitytypes singeltons (#222) * New annotation to make singletons and entity types - Update to olingo 4.8.0 - Deprecate EdmAsEntitySet * Wrong entity type on singleton only * Add java doc to TopLevelElementRepresentation * Finalize singleton metadata handling * Clean-up test classes * Add option to retrieve Singleton from SD * Rename test class * Add and clean-up unit tests * Query extension declaration (#223) * New annotation to make singletons and entity types - Update to olingo 4.8.0 - Deprecate EdmAsEntitySet * Wrong entity type on singleton only * Add java doc to TopLevelElementRepresentation * Finalize singleton metadata handling * Clean-up test classes * Add option to retrieve Singleton from SD * Rename test class * Add and clean-up unit tests * Introduce query extension metadata * Enable Singleton and Cast on subtypes - clean-up sonar issues * Support entity types and singletons (#224) * New annotation to make singletons and entity types - Update to olingo 4.8.0 - Deprecate EdmAsEntitySet * Wrong entity type on singleton only * Add java doc to TopLevelElementRepresentation * Finalize singleton metadata handling * Clean-up test classes * Add option to retrieve Singleton from SD * Rename test class * Add and clean-up unit tests * Introduce query extension metadata * Enable Singleton and Cast on subtypes - clean-up sonar issues * Clean-up sonar issues * Support cast on navigations (#225) * New annotation to make singletons and entity types - Update to olingo 4.8.0 - Deprecate EdmAsEntitySet * Wrong entity type on singleton only * Add java doc to TopLevelElementRepresentation * Finalize singleton metadata handling * Clean-up test classes * Add option to retrieve Singleton from SD * Rename test class * Add and clean-up unit tests * Introduce query extension metadata * Enable Singleton and Cast on subtypes - clean-up sonar issues * Clean-up sonar issues * Cast within navigation path * Add cast collections * Add tests for EdmBoundCast * Support Cast on $expand * Update README.md (#226) * Update README.md * Update README.md * Update README.md * Update README.md * Bugfix/no constranis with ignored properties (#227) * Suppress referential constraint for properties that shall be ignored * No Referential Constraint in case one property shall be ignored * Bugfix/no constranis with ignored properties (#228) * Suppress referential constraint for properties that shall be ignored * No Referential Constraint in case one property shall be ignored * Bring back error on ignored * Enable subtyping for complex types (#229) * Support transient properties that require ignored properties (#231) * Bugfix/multi level inheritance (#232) * Adopt process-cb * Correct type converter problem * Use dbType for tuple result mapping * Bugfix/multi level inheritance (#233) * Adopt process-cb * Correct type converter problem * Use dbType for tuple result mapping * Correct constructor test of extension * Feature/release 1.0.3 (#234) * Correct typos and replace deprecated method * Set final Version * Feature/release 1.0.4 (#235) * Error corrections - Debugger did not work - Transaction Factory not forwarded * Update release * Make debugger runtime a List * Feature/release 1.0.4 (#236) * Error corrections - Debugger did not work - Transaction Factory not forwarded * Update release * Make debugger runtime a List * Small adoptions to test model * Reset change * Error correction (#237) * Feature/release 1.0.5 (#238) * Error corrections - Debugger did not work - Transaction Factory not forwarded * Update release * Make debugger runtime a List * Small adoptions to test model * Reset change * Add test for criteria builder * Error correction * Update H2 version (#239) * Update H2 version * Update version and rework DataSourceHelper * Feature/release 1.0.6 (#240) * Update H2 version * Update version and rework DataSourceHelper * Let H2 run in Postges mode * Upgrade version and additional tests (#241) * Upgrade version and additional tests * Remove session context from queries * Remove session context from processors * New version an sonar clean-up (#242) * Release 1.1.0 (#243) * New version an sonar clean-up * New path property fro sonar * Release 1.1.0 (#244) * New version an sonar clean-up * New path property fro sonar * Test usage of SNAPSHOT version * Update version -> 1.0.8 (#245) * Update version -> 1.0.8 * Count queries support Integer as result * Update archetype to support PATCH * Feature/release 1.0.0 (#247) * New version an sonar clean-up * New path property fro sonar * Test usage of SNAPSHOT version * Adopt archetype * Clean-up sonar issues * Resolve more sonar issues * Introducing virtual property * Clean-up associations and enable default columns when using ...-cb * Generate metadata for overloaded action (#248) * Generate metadata for overloaded action * Process action * Feature/action overload (#249) * Generate metadata for overloaded action * Process action * Use constructor of entity type an action is called for not of binding * Fix claims in collections where (#250) * Fix claims in collections where * Missed interface definition * Missed test renaming * Use dbtype to build key pair in case a conversion exists (#251) * Enable more constructors for binding parameter (#252) * Feature/more flexable constructor determination operations (#253) * Enable more constructors for binding parameter * Clean-up sonar errors * New type cast added - they have possible data lost (#254) * Collection not longer retrieves transient (#255) * Collection not longer retrieves transient * Skip unit test * Enhance partner determination (#256) * Bugfix/reuse navigation as partner (#257) * Enhance partner determination * Remove one sonar issue * Bugfix/reuse navigation as partner (#258) * Enhance partner determination * Remove one sonar issue * Correct partner determination * No fallback to server locale in case bundle requested local not found (#259) * Replace file reader (#260) * Replace fixed values by variables (#261) * Bugfix/error in controller test (#262) * Replace fixed values by variables * Update pom * Update archetype pom (#265) * Defect/archetype pom (#266) * Update archetype pom * Check older version of sonar plugin * Update test constants (#267) * Correct count behavior (#268) * Change to Java 11 (#269) * Change to Java 11 * Revert Java 11 * Update README.md (#270) * Defect/count not working on hana (#271) * Correct count behavior * Ignore sonar check. Equal methods are generated * Defect/java function parameter name (#272) * Raise meaningful exception on empty function parameter name * Meaningful exception if action parameter name empty * Raise message in case of Void as return type for functions (#273) * Raise message in case of Void as return type for functions * Add extenstion * Error in if clause * Extension of visitor for java functions (#274) * Update version to 1.1.1 (#275) * Feature/predefined annotations (#276) * First list of predefined OData annotations * Update capabilities annotations * Sonar issues * Update dependencies * Adopt layer test * Add page to order by builder (#277) * Feature/predefined annotations (#278) * First list of predefined OData annotations * Update capabilities annotations * Sonar issues * Update dependencies * Adopt layer test * Intermediate state * Clean-up basic mapping and introduce annotation * Finalize annotation mapper * Feature/predefined annotations (#279) * First list of predefined OData annotations * Update capabilities annotations * Sonar issues * Update dependencies * Adopt layer test * Intermediate state * Clean-up basic mapping and introduce annotation * Finalize annotation mapper * Update dependency * Feature/predefined annotations (#280) * First list of predefined OData annotations * Update capabilities annotations * Sonar issues * Update dependencies * Adopt layer test * Intermediate state * Clean-up basic mapping and introduce annotation * Finalize annotation mapper * Update dependency * Adopt HSQLDB * Update .xmake.cfg (#283) * Update .xmake.cfg * Update .xmake.cfg * Correct spelling (#281) * Feature/predefined annotations (#282) * First list of predefined OData annotations * Update capabilities annotations * Sonar issues * Update dependencies * Adopt layer test * Intermediate state * Clean-up basic mapping and introduce annotation * Finalize annotation mapper * Update dependency * Adopt HSQLDB * Rename package for vocabulary parser * Move OData vocabularies to new module * Merge tests * Annotations in metadata * Finalize annotations within metadata * Update .xmake.cfg (#284) * Update .xmake.cfg * Update .xmake.cfg * Feature/predefined annotations (#286) * First list of predefined OData annotations * Update capabilities annotations * Sonar issues * Update dependencies * Adopt layer test * Intermediate state * Clean-up basic mapping and introduce annotation * Finalize annotation mapper * Update dependency * Adopt HSQLDB * Rename package for vocabulary parser * Move OData vocabularies to new module * Merge tests * Annotations in metadata * Finalize annotations within metadata * Support sorting restrictions by annotation * Build annotation based expand check * Expand star via path reads only requested from database * Check countability * Support collection property count * Annotations@Singeltons * Provide AnnotationProvider to all model elements * Enable annotations at properties * Feature/predefined annotations (#287) * First list of predefined OData annotations * Update capabilities annotations * Sonar issues * Update dependencies * Adopt layer test * Intermediate state * Clean-up basic mapping and introduce annotation * Finalize annotation mapper * Update dependency * Adopt HSQLDB * Rename package for vocabulary parser * Move OData vocabularies to new module * Merge tests * Annotations in metadata * Finalize annotations within metadata * Support sorting restrictions by annotation * Build annotation based expand check * Expand star via path reads only requested from database * Check countability * Support collection property count * Annotations@Singeltons * Provide AnnotationProvider to all model elements * Enable annotations at properties * Enable access to annotations via JPARequestEntity * Watch filtering * Clean-up pom and typo correction (#288) * Solve issue 212 and fix permission check issue with join tables (#289) * Solve issue 212 and fix permission check issue with join tables * $count for collection join as well * Clean-up code * Fix issue, converting type (#290) * Fix issue, converting type * Fix unit test * Correct type determination * Multi step Mapped Superclass (#291) * Upgrade H2 to 2.2.220 (#293) * Correct navigation to one is null (#294) * Fix join column determination with cyclic dependency (#295) * Fix join column determination with cyclic dependency * Additional test for navigation with mapped join table * Make OneToOne required and handle non JPA Processor errors in metadata (#296) * Defect/issue214 (#297) * Make OneToOne required and handle non JPA Processor errors in metadata * Clean-up warnings * Defect/issue214 (#298) * Make OneToOne required and handle non JPA Processor errors in metadata * Clean-up warnings * Add check for OneToMany * Clean-up sonar issues * Update .xmake.cfg (#300) * Update version to 2.0.0 (#299) * Update version to 2.0.0 * Unify junit version * Make use of Jakarta * Clean-up sonar issues created by switching to Java 17 * Update dependencies * Update dependencies and clean-up typos * Add unit tests * Increase test coverage * Defect/issue226 (#301) * Update version * Adopt correction done for release * Clean-up archetype * Clean-up error * Add test to check Olingo not supporting $expand...($level=; $expand...) * Note thrown runtime exception * First level of COUNT query as IN (#302) * Defect/issues239 (#303) * First level of COUNT query as IN * Deletion of JPACollectionFilterQuery * Defect/issues239 (#304) * First level of COUNT query as IN * Deletion of JPACollectionFilterQuery * Handle null where conditions * Rename properties file to prevent name clashes (#305) * Rename properties file to prevent name clashes * Update dependency, resolve conflict with Olingo * Clean-up pom and some code (#306) * Defect/pom cleanup (#307) * Clean-up pom and some code * Update dependencies * Archetype and SOnar clean-up (#308) * Add protection where to collection query (#309) * Check if cast is necessary (#310) * Set version to 2.0.2 (#311) * Update to Olingo 5.0.0 and remove wrapper (#314) * Extend interface for server driven paging (#313) * Extend interface for server driven paging * Correct failing tests * Clean-ups * Sonar clean-up * Change default implementation * Enhance paging provider interface * Finalize paging provider * Feature/enhancement of paging (#315) * Extend interface for server driven paging * Correct failing tests * Clean-ups * Sonar clean-up * Change default implementation * Enhance paging provider interface * Finalize paging provider * Use synchronized instead of thread save collections * First version and some clean-ups (#312) * First version and some clean-ups * Update filter restriction and new query directives * New query implementation for count (#316) * Feature/annotation api extension (#317) * First step * Enhancement with path expressions * Re-factor annotation search * Get annotation value from property * Prepare test of EntityType and NavigationProperty * Finalize annotation API * Update project files (#318) * Add null check for NOT IN clauses (#319) * Fix $count problem with collection properties (#320) * Fix $count problem with collection properties * Handle navigation filter query for collection properties * Defect/use raw uri for vocabularies (#321) * Update urls * update pom * Defect/use raw uri for vocabularies (#322) * Update urls * update pom * Defect/missing paging expand with cp (#323) * Introduction of default paging provider * Skip token shall be null * Handle LIMIT and OFFSET with TypedQuery (#324) * Defect/eclipse link hana problem (#325) * Handle LIMIT and OFFSET with TypedQuery * Update default for LIMIT * Check restrictions on IN clause (#326) * Correct NPE if enum property is nullable (#327) * Update README.md (#328) * Update README.md * Update README.md * Fix duplicates result multi expands issue#292 (#329) * Defect/enumeration convertion error (#330) * Update Version * Make use of @Enumerated and fix order issue * Suppress generation of defaults for LIMIT and OFFSET (#331) * Enable order by to one associations (#333) * Enhanced ETag handling for GET entity set requests (#332) * Enhanced ETag handling for GET entity set requests * Prepare ETag handling for functions and actions * Cleanup test for filter using db functions * Fix unit tests * ETag at Functions and Actions * Defect/orderby navigation to on (#334) * Enable order by to one associations * Group By at sub queries * Correct collection property select clause issues (#335) * Enable nested lambda expressions (#336) * Fix problem with expand and lambda to collection (#337) * Set version to 2.1.3 (#338) * Feature/release 2.1.3 (#339) * Set version to 2.1.3 * Update readme * Enable weak etags * Add word * Generalize unit test * Feature/release 2.1.3 (#340) * Set version to 2.1.3 * Update readme * Enable weak etags * Add word * Generalize unit test * Adopt validation header check to potential lower case conversion * Update to version 2.1.4 (#341) * Update to version 2.2.0 (#342) * Defect/issue 330 (#343) * Add derby as db option and allow integer as count value * Merge remote-tracking branch 'origin/master' into defect/issue-330 * Defect/issue 330 (#344) * Add derby as db option and allow integer as count value * Merge remote-tracking branch 'origin/master' into defect/issue-330 * Enable database specific conversion of cb * Update test * Fix issue with orderby and description properties (#345) - re-think orderby creation * server driven paging on expand (#346) * Clean-up * Add MySQL to migration 1.1 * Uri switch and singleton problem solution * Page no longer used. Usage of wrapped uri info - Add paging provider to request context - Enable skip token for expand result * Enable paging for first level of expand * Solve issue 362 * Change way of conversion of expand result to on-demand * Support $level and paging * Solution for issue 376 and support of star - missing support of star levels=max - missing max deprecation warning * Solution for issue 376 and support of star - missing support of star levels=max - missing max deprecation warning * Set back Derby version * Add star with levels=max and warning * Adopt test * Update create response (#347) * Feature/server driven paging expand (#348) * Update create response * Clean-up sonar * Feature/server driven paging expand (#349) * Clean-up * Add MySQL to migration 1.1 * Uri switch and singleton problem solution * Page no longer used. Usage of wrapped uri info - Add paging provider to request context - Enable skip token for expand result * Enable paging for first level of expand * Solve issue 362 * Change way of conversion of expand result to on-demand * Support $level and paging * Solution for issue 376 and support of star - missing support of star levels=max - missing max deprecation warning * Solution for issue 376 and support of star - missing support of star levels=max - missing max deprecation warning * Set back Derby version * Add star with levels=max and warning * Adopt test * Finalize server driven paging $expand * Update pom (#350) * Update version to 2.3.0 (#351) * Feature/add criteria update (#352) * Update version to 2.3.0 * First version of CriteriaUpdate * Enable multiple versions * Clean-up * Add subquery to CriteriaUpdate * Change implementation of filter on boundary (#353) * Change implementation of filter on boundary * Correct lower - upper * Defect/issue 397 (#354) * Change implementation of filter on boundary * Correct lower - upper * Recreate of API change JPAAbstractDatabaseProcessor * Enable refresh of parameter buffer by query (#355) * Defect/issue 359 (#356) * Enable refresh of parameter buffer by query * Check if root query found any result * Clean-up and update versions * Adopt naming (#357) * Update version to 2.3.1 * Update version to 2.3.1 (#358) * Defect/issue 407 (#359) * Update version to 2.3.1 * Allow setting of sort order for UUIDs * Update versions * Support Upsert on example CUD request handler (#360) * Suppress order by key in case key is part of $orderby (#361) * Update documentation --- .xmake.cfg | 6 + README.md | 2 +- .../odata-jpa-archetype-spring/pom.xml | 2 +- jpa-archetype/pom.xml | 4 +- .../Questions/HowToHandleApiVersions.adoc | 4 +- jpa-tutorial/Questions/Preparation.adoc | 4 +- jpa-tutorial/QuickStart/QuickStart.adoc | 2 +- jpa/.dbeaver/credentials-config.json | 1 + jpa/.dbeaver/data-sources.json | 116 ++++++++++++++ jpa/.dbeaver/project-metadata.json | 1 + jpa/.dbeaver/project-settings.json | 1 + jpa/.gitignore | 2 +- jpa/.project | 1 + jpa/odata-jpa-coverage/pom.xml | 1 - jpa/odata-jpa-metadata/old.project | 47 ++++++ .../core/edm/mapper/api/JPAEntityType.java | 6 + .../mapper/impl/IntermediateEntityType.java | 6 + .../impl/IntermediateEntityTypeTest.java | 21 +++ jpa/odata-jpa-processor/old.project | 47 ++++++ .../core/api/JPAODataQueryDirectives.java | 26 ++- .../api/JPAODataQueryDirectivesBuilder.java | 4 + .../core/api/JPAODataServiceContext.java | 1 + .../example/JPAExampleCUDRequestHandler.java | 27 +++- .../core/processor/JPAModifyUtil.java | 39 ++++- .../JPANavigationRequestProcessor.java | 4 +- .../JPAAbstractProcessorAttributeImpl.java | 5 + .../properties/JPAProcessorAttribute.java | 3 + .../core/query/JPAExpandQueryResult.java | 2 +- .../jpa/processor/core/query/JPAKeyPair.java | 22 ++- .../core/query/JPAOrderByBuilder.java | 16 +- .../JPAExampleCUDRequestHandlerTest.java | 55 +++---- .../core/processor/JPAModifyUtilTest.java | 110 +++++++------ .../JPAODataInternalRequestContextTest.java | 3 +- .../core/query/JPAExpandQueryResultTest.java | 5 + .../core/query/JPAExpandQueryTest.java | 8 +- .../processor/core/query/JPAKeyPairTest.java | 148 ++++++++++-------- .../core/query/JPAOrderByBuilderTest.java | 5 +- .../core/util/JPAEntityTypeDouble.java | 47 +++--- .../main/resources/META-INF/persistence.xml | 11 +- jpa/pom.xml | 6 +- 40 files changed, 618 insertions(+), 203 deletions(-) create mode 100644 .xmake.cfg create mode 100644 jpa/.dbeaver/credentials-config.json create mode 100644 jpa/.dbeaver/data-sources.json create mode 100644 jpa/.dbeaver/project-metadata.json create mode 100644 jpa/.dbeaver/project-settings.json create mode 100644 jpa/odata-jpa-metadata/old.project create mode 100644 jpa/odata-jpa-processor/old.project diff --git a/.xmake.cfg b/.xmake.cfg new file mode 100644 index 000000000..81923357f --- /dev/null +++ b/.xmake.cfg @@ -0,0 +1,6 @@ +[xmake] +xmake-version=0.9.2-MS8 +[buildplugin] +java-type=sapmachine +alternate-path=jpa +java-version=17.0.8 diff --git a/README.md b/README.md index daa3c9d4b..818678563 100644 --- a/README.md +++ b/README.md @@ -102,5 +102,5 @@ Detailed information including third-party components and their licensing/copyri |2.1.0| - Enhancement of annotation API
- Enhancement of API for server driven paging
- Optional support of IN operand
- Update to Olingo 5.0.0
- Rework $count implementation
- Fix problem with $count on collection properties|No| |2.1.1| - Fix for issue [#292](https://github.com/SAP/olingo-jpa-processor-v4/issues/292)|No| |2.1.3| - Fix for issue [#319](https://github.com/SAP/olingo-jpa-processor-v4/issues/319)
- Fix for issue [#325](https://github.com/SAP/olingo-jpa-processor-v4/issues/325)
- Fix for issue [#327](https://github.com/SAP/olingo-jpa-processor-v4/issues/327)
- Fix for issue [#331](https://github.com/SAP/olingo-jpa-processor-v4/issues/331)
- Fix of en issue with $orderby and _to one_ navigation properties |No| -|2.2.0| - Fix for issue [#378](https://github.com/SAP/olingo-jpa-processor-v4/issues/378)
- Fix for issue [#378](https://github.com/SAP/olingo-jpa-processor-v4/issues/378)
- Fix for issue [#361](https://github.com/SAP/olingo-jpa-processor-v4/issues/361)
- Fix for issue [#352](https://github.com/SAP/olingo-jpa-processor-v4/issues/352)
- Fix for issue [#307](https://github.com/SAP/olingo-jpa-processor-v4/issues/307)
- Enhancement according to [#314](https://github.com/SAP/olingo-jpa-processor-v4/issues/314)|No| +|2.2.0| - Fix for issue [#378](https://github.com/SAP/olingo-jpa-processor-v4/issues/378)
- Fix for issue [#361](https://github.com/SAP/olingo-jpa-processor-v4/issues/361)
- Fix for issue [#352](https://github.com/SAP/olingo-jpa-processor-v4/issues/352)
- Fix for issue [#307](https://github.com/SAP/olingo-jpa-processor-v4/issues/307)
- Enhancement according to [#314](https://github.com/SAP/olingo-jpa-processor-v4/issues/314)|No| |2.3.0| - Add support for handling multiple API version. Issue [#308](https://github.com/SAP/olingo-jpa-processor-v4/issues/308)
- Fix for issue [#359](https://github.com/SAP/olingo-jpa-processor-v4/issues/359)
- Fix for issue [#406](https://github.com/SAP/olingo-jpa-processor-v4/issues/406)
- Fix for issue [#397](https://github.com/SAP/olingo-jpa-processor-v4/issues/397)|No| diff --git a/jpa-archetype/odata-jpa-archetype-spring/pom.xml b/jpa-archetype/odata-jpa-archetype-spring/pom.xml index c62b63bc1..739ec7950 100644 --- a/jpa-archetype/odata-jpa-archetype-spring/pom.xml +++ b/jpa-archetype/odata-jpa-archetype-spring/pom.xml @@ -4,7 +4,7 @@ com.sap.olingo odata-jpa-archetype - 2.3.1-SNAPSHOT + 2.3.1-SNAPSHOT odata-jpa-archetype-spring Archetype - odata-jpa-archetype-spring diff --git a/jpa-archetype/pom.xml b/jpa-archetype/pom.xml index 244b22cba..294f593f9 100644 --- a/jpa-archetype/pom.xml +++ b/jpa-archetype/pom.xml @@ -10,10 +10,10 @@ UTF-8 - 17 + 17 - odata-jpa-archetype-spring + odata-jpa-archetype-spring \ No newline at end of file diff --git a/jpa-tutorial/Questions/HowToHandleApiVersions.adoc b/jpa-tutorial/Questions/HowToHandleApiVersions.adoc index 7388847d2..79101124f 100644 --- a/jpa-tutorial/Questions/HowToHandleApiVersions.adoc +++ b/jpa-tutorial/Questions/HowToHandleApiVersions.adoc @@ -103,7 +103,7 @@ public abstract class EclipseLinkJpaConfiguration extends JpaBaseConfiguration { ---- Then we need to create the version specific entity manager factories. -Please note that with each version of the entity manager factory we also have to create a transaction manager. +Please note that with each version of the entity manager factory we also have to create a transaction manager and must have an own persistence unit name. It is also important that one of the beans for the factory has the name `entityManagerFactory`. First the entity manager factory for the old version: @@ -136,6 +136,7 @@ public class JpaConfigurationV1 extends EclipseLinkJpaConfiguration { return basicSettings(factoryBuilder) .packages(Trip.class, PlanItem.class, OffsetDateTimeConverter.class) + .persistenceUnit("TrippinV1") .build(); } } @@ -176,6 +177,7 @@ public class JpaConfigurationV2 extends EclipseLinkJpaConfiguration { return basicSettings(factoryBuilder) .packages(Trip.class, PlanItem.class, OffsetDateTimeConverter.class) + .persistenceUnit("TrippinV2") .build(); } } diff --git a/jpa-tutorial/Questions/Preparation.adoc b/jpa-tutorial/Questions/Preparation.adoc index 38f0b45e1..4f39dd8c9 100644 --- a/jpa-tutorial/Questions/Preparation.adoc +++ b/jpa-tutorial/Questions/Preparation.adoc @@ -290,7 +290,7 @@ insert into "Person" values ('keithpinckney', 'Keith', 'Pinckney', null, 0, null insert into "Person" values ('marshallgaray', 'Marshall', 'Garay', null, 0, null); insert into "Person" values ('ryantheriault', 'Ryan', 'Theriault', null, 0, null); insert into "Person" values ('elainestewart', 'Elaine', 'Stewart', null, 0, null); -insert into "Person" values ('salliesampson', 'Sallie', 'Sampson', null, 1, null); +insert into "Person" values ('sallysampson', 'Sally', 'Sampson', null, 1, null); insert into "Person" values ('jonirosales', 'Joni', 'Rosales', null, 2, null); insert into "Person" values ('georginabarlow', 'Georgina', 'Barlow', null, 1, null); insert into "Person" values ('angelhuffman', 'Angel', 'Huffman', null, 1, null); @@ -326,7 +326,7 @@ insert into "Trip" values (11, 'keithpinckney', 'a88f675d-9199-4392-9656-b08e3b4 insert into "Trip" values (12, 'marshallgaray', 'a88f675d-9199-4392-9656-b08e3b46df8a', 'Study trip', 1550.3, 'This is a 2 weeks study trip', '2014-01-01T00:00:00Z', '2014-01-14T00:00:00Z'); insert into "Trip" values (13, 'ryantheriault', 'a88f675d-9199-4392-9656-b08e3b46df8a', 'Study trip', 1550.3, 'This is a 2 weeks study trip', '2014-01-01T00:00:00Z', '2014-01-14T00:00:00Z'); insert into "Trip" values (14, 'elainestewart', 'a88f675d-9199-4392-9656-b08e3b46df8a', 'Study trip', 1550.3, 'This is a 2 weeks study trip', '2014-01-01T00:00:00Z', '2014-01-14T00:00:00Z'); -insert into "Trip" values (15, 'salliesampson', 'a88f675d-9199-4392-9656-b08e3b46df8a', 'Study trip', 600, 'This is a 2 weeks study trip', '2014-01-01T00:00:00Z', '2014-01-14T00:00:00Z'); +insert into "Trip" values (15, 'sallysampson', 'a88f675d-9199-4392-9656-b08e3b46df8a', 'Study trip', 600, 'This is a 2 weeks study trip', '2014-01-01T00:00:00Z', '2014-01-14T00:00:00Z'); insert into "Trip" values (16, 'jonirosales', 'a88f675d-9199-4392-9656-b08e3b46df8a', 'Study trip', 2000, 'This is a 2 weeks study trip', '2014-01-01T00:00:00Z', '2014-01-14T00:00:00Z'); insert into "Trip" values (17, 'georginabarlow', 'a88f675d-9199-4392-9656-b08e3b46df8a', 'Study trip', 1150.3, 'This is a 2 weeks study trip', '2014-01-01T00:00:00Z', '2014-01-14T00:00:00Z'); insert into "Trip" values (18, 'angelhuffman', 'cb0b8acb-79cb-4127-8316-772bc4302824', 'DIY Trip', 1500.3, 'This is a DIY trip', '2011-02-11T00:00:00Z', '2011-02-14T00:00:00Z'); diff --git a/jpa-tutorial/QuickStart/QuickStart.adoc b/jpa-tutorial/QuickStart/QuickStart.adoc index e8b5157df..2ec74d9be 100644 --- a/jpa-tutorial/QuickStart/QuickStart.adoc +++ b/jpa-tutorial/QuickStart/QuickStart.adoc @@ -46,7 +46,7 @@ This should contain the information about archetype: com.sap.olingo odata-jpa-archetype-spring - 2.1.3 + 2.3.0 diff --git a/jpa/.dbeaver/credentials-config.json b/jpa/.dbeaver/credentials-config.json new file mode 100644 index 000000000..3156ea04c --- /dev/null +++ b/jpa/.dbeaver/credentials-config.json @@ -0,0 +1 @@ +:b6 94E˗JA8/gU{~=eVZ̘8a\;}q6 +2`kuN)ɪW_=/^;o|sI5':%0GfRt f}:\s:4n[\K$UYGrUSj3?EDeuΧ,>\@#7pZ;,H>WQyRϚ@Y`VqVڹlauz-\hD%_>Ci-lp-0?W`o؀gjwg_HV:%OI@$lm_J%fKx1tPC}c4hw;Eŋwg\VmD Z&`F@ׅlKE GiE`ttډ<,Oz)qznuoW4 )[+iD?FY2([]n'ڣ& \ No newline at end of file diff --git a/jpa/.dbeaver/data-sources.json b/jpa/.dbeaver/data-sources.json new file mode 100644 index 000000000..473b37c41 --- /dev/null +++ b/jpa/.dbeaver/data-sources.json @@ -0,0 +1,116 @@ +{ + "folders": {}, + "connections": { + "postgres-jdbc-18d652c2b95-113570e0ec869f1d": { + "provider": "postgresql", + "driver": "postgres-jdbc", + "name": "postgres", + "save-password": true, + "configuration": { + "host": "localhost", + "port": "5432", + "database": "postgres", + "url": "jdbc:postgresql://localhost:5432/postgres", + "configurationType": "MANUAL", + "home": "postgresql-x64-16", + "type": "dev", + "closeIdleConnection": false, + "auth-model": "native" + } + }, + "postgres-jdbc-18d7dab8ffc-6870c0ec5fa5f049": { + "provider": "postgresql", + "driver": "postgres-jdbc", + "name": "Olingo", + "save-password": true, + "configuration": { + "host": "localhost", + "port": "5432", + "database": "Olingo", + "url": "jdbc:postgresql://localhost:5432/Olingo", + "configurationType": "MANUAL", + "home": "postgresql-x64-16", + "type": "dev", + "closeIdleConnection": false, + "auth-model": "native" + } + }, + "sap_hana-18d83921104-7dd425d3aee15bf1": { + "provider": "hana", + "driver": "sap_hana", + "name": "localhost", + "save-password": true, + "configuration": { + "host": "localhost", + "port": "30015", + "url": "jdbc:sap://localhost:30015", + "configurationType": "MANUAL", + "type": "dev", + "closeIdleConnection": false, + "provider-properties": { + "edition": "GENERIC" + }, + "auth-model": "native" + } + }, + "postgres-jdbc-18dec2e5845-6df665f2f5a08171": { + "provider": "postgresql", + "driver": "postgres-jdbc", + "name": "compass", + "save-password": true, + "configuration": { + "host": "localhost", + "port": "5432", + "database": "compass", + "url": "jdbc:postgresql://localhost:5432/compass", + "configurationType": "MANUAL", + "home": "postgresql-x64-16", + "type": "dev", + "closeIdleConnection": true, + "provider-properties": { + "@dbeaver-show-non-default-db@": "false" + }, + "auth-model": "native" + } + }, + "mysql8-18f81c6ea39-153fa1c6870708de": { + "provider": "mysql", + "driver": "mysql8", + "name": "MySql-Olingo", + "save-password": true, + "configuration": { + "host": "localhost", + "port": "3306", + "database": "Olingo", + "url": "jdbc:mysql://localhost:3306/Olingo?allowPublicKeyRetrieval=true&useSSL=false", + "configurationType": "URL", + "home": "mysql_client", + "type": "dev", + "closeIdleConnection": true, + "properties": { + "rewriteBatchedStatements": "true", + "connectTimeout": "20000", + "enabledTLSProtocols": "TLSv1,TLSv1.1,TLSv1.2,TLSv1.3" + }, + "auth-model": "native", + "handlers": {} + } + } + }, + "connection-types": { + "dev": { + "name": "Development", + "color": "255,255,255", + "description": "Regular development database", + "auto-commit": true, + "confirm-execute": false, + "confirm-data-change": false, + "smart-commit": false, + "smart-commit-recover": false, + "auto-close-transactions": true, + "close-transactions-period": 1800, + "auto-close-connections": true, + "close-connections-period": 14400 + } + } +} \ No newline at end of file diff --git a/jpa/.dbeaver/project-metadata.json b/jpa/.dbeaver/project-metadata.json new file mode 100644 index 000000000..205c91a6d --- /dev/null +++ b/jpa/.dbeaver/project-metadata.json @@ -0,0 +1 @@ +{"resources":{"Scripts/Script-1.sql":{"default-schema":"OLINGO","default-datasource":"postgres-jdbc-18d7dab8ffc-6870c0ec5fa5f049","default-catalog":"Olingo"},"Scripts/Script-10.sql":{"default-schema":"OLINGO","default-datasource":"postgres-jdbc-18d7dab8ffc-6870c0ec5fa5f049","default-catalog":"Olingo"},"Scripts/Script-11.sql":{"default-schema":"OLINGO","default-datasource":"sap_hana-18d83921104-7dd425d3aee15bf1"},"Scripts/Script-12.sql":{"default-schema":"public","default-datasource":"postgres-jdbc-18dec2e5845-6df665f2f5a08171","default-catalog":"compass"},"Scripts/Script-13.sql":{"default-datasource":"sap_hana-18d83921104-7dd425d3aee15bf1","default-schema":"OLINGO"},"Scripts/Script-2.sql":{"default-schema":"OLINGO","default-datasource":"sap_hana-18d83921104-7dd425d3aee15bf1","default-catalog":"compass"},"Scripts/Script-3.sql":{"default-schema":"OLINGO","default-datasource":"sap_hana-18d83921104-7dd425d3aee15bf1","default-catalog":"Olingo"},"Scripts/Script-4.sql":{"default-schema":"OLINGO","default-datasource":"postgres-jdbc-18d7dab8ffc-6870c0ec5fa5f049","default-catalog":"Olingo"},"Scripts/Script-5.sql":{"default-schema":"OLINGO","default-datasource":"postgres-jdbc-18d7dab8ffc-6870c0ec5fa5f049","default-catalog":"Olingo"},"Scripts/Script-6.sql":{"default-schema":"public","default-datasource":"postgres-jdbc-18dec2e5845-6df665f2f5a08171","default-catalog":"compass"},"Scripts/Script-7.sql":{"default-schema":"public","default-datasource":"postgres-jdbc-18dec2e5845-6df665f2f5a08171","default-catalog":"compass"},"Scripts/Script-8.sql":{"default-schema":"public","default-datasource":"postgres-jdbc-18dec2e5845-6df665f2f5a08171","default-catalog":"compass"},"Scripts/Script-9.sql":{"default-schema":"public","default-datasource":"postgres-jdbc-18dec2e5845-6df665f2f5a08171","default-catalog":"compass"},"Scripts/Script.sql":{"default-schema":"OLINGO","default-datasource":"sap_hana-18d83921104-7dd425d3aee15bf1","default-catalog":"Olingo"}}} \ No newline at end of file diff --git a/jpa/.dbeaver/project-settings.json b/jpa/.dbeaver/project-settings.json new file mode 100644 index 000000000..0e2242aaf --- /dev/null +++ b/jpa/.dbeaver/project-settings.json @@ -0,0 +1 @@ +{"id":"1dc9dc18-395d-49be-a7b8-2ad9bb1a4481"} \ No newline at end of file diff --git a/jpa/.gitignore b/jpa/.gitignore index 465424a3d..f932957a7 100644 --- a/jpa/.gitignore +++ b/jpa/.gitignore @@ -11,4 +11,4 @@ target/ *.log /old.project /Scripts/ -/.dbeaver/ +/.dbeaver/ \ No newline at end of file diff --git a/jpa/.project b/jpa/.project index 942c0feae..cf9aeda0a 100644 --- a/jpa/.project +++ b/jpa/.project @@ -24,6 +24,7 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + org.jkiss.dbeaver.DBeaverNature diff --git a/jpa/odata-jpa-coverage/pom.xml b/jpa/odata-jpa-coverage/pom.xml index 61d938d58..3d24b34fd 100644 --- a/jpa/odata-jpa-coverage/pom.xml +++ b/jpa/odata-jpa-coverage/pom.xml @@ -10,7 +10,6 @@ odata-jpa-coverage odata-jpa-coverage https://github.com/SAP/olingo-jpa-processor-v4 - com.sap.olingo diff --git a/jpa/odata-jpa-metadata/old.project b/jpa/odata-jpa-metadata/old.project new file mode 100644 index 000000000..ba05291b0 --- /dev/null +++ b/jpa/odata-jpa-metadata/old.project @@ -0,0 +1,47 @@ + + + jpa-metadata + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + + + + 1634102235525 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/jpa/odata-jpa-metadata/src/main/java/com/sap/olingo/jpa/metadata/core/edm/mapper/api/JPAEntityType.java b/jpa/odata-jpa-metadata/src/main/java/com/sap/olingo/jpa/metadata/core/edm/mapper/api/JPAEntityType.java index 42e89afef..06e9b87dc 100644 --- a/jpa/odata-jpa-metadata/src/main/java/com/sap/olingo/jpa/metadata/core/edm/mapper/api/JPAEntityType.java +++ b/jpa/odata-jpa-metadata/src/main/java/com/sap/olingo/jpa/metadata/core/edm/mapper/api/JPAEntityType.java @@ -61,6 +61,12 @@ public interface JPAEntityType extends JPAStructuredType, JPAAnnotatable { */ public boolean hasCompoundKey(); + /** + * True in case the entity type has an EmbeddedId + * @return + */ + public boolean hasEmbeddedKey(); + /** * @return a list of JPAPath to attributes marked with EdmSearchable * @throws ODataJPAModelException diff --git a/jpa/odata-jpa-metadata/src/main/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateEntityType.java b/jpa/odata-jpa-metadata/src/main/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateEntityType.java index e15381d83..54522ae49 100644 --- a/jpa/odata-jpa-metadata/src/main/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateEntityType.java +++ b/jpa/odata-jpa-metadata/src/main/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateEntityType.java @@ -295,6 +295,12 @@ public boolean hasCompoundKey() { || idType instanceof EmbeddableType; } + @Override + public boolean hasEmbeddedKey() { + return ((IdentifiableType) jpaManagedType).hasSingleIdAttribute() + && hasCompoundKey(); + } + @Override public boolean hasEtag() throws ODataJPAModelException { buildEdmTypeIfEmpty(); diff --git a/jpa/odata-jpa-metadata/src/test/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateEntityTypeTest.java b/jpa/odata-jpa-metadata/src/test/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateEntityTypeTest.java index 8c1cfe60b..1135f7386 100644 --- a/jpa/odata-jpa-metadata/src/test/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateEntityTypeTest.java +++ b/jpa/odata-jpa-metadata/src/test/java/com/sap/olingo/jpa/metadata/core/edm/mapper/impl/IntermediateEntityTypeTest.java @@ -677,6 +677,27 @@ void checkIdIsNotCompound() { assertFalse(et.hasCompoundKey()); } + @Test + void checkEmbeddedIdKeyIsEmbedded() { + final IntermediateEntityType et = new IntermediateEntityType<>( + new JPADefaultEdmNameBuilder(PUNIT_NAME), getEntityType(AdministrativeDivisionDescription.class), schema); + assertTrue(et.hasEmbeddedKey()); + } + + @Test + void checkMultipleKeyIsNotEmbedded() { + final IntermediateEntityType et = new IntermediateEntityType<>(new JPADefaultEdmNameBuilder( + PUNIT_NAME), getEntityType(AdministrativeDivision.class), schema); + assertFalse(et.hasEmbeddedKey()); + } + + @Test + void checkIdIsNotEmbedded() { + final IntermediateEntityType et = new IntermediateEntityType<>(new JPADefaultEdmNameBuilder( + PUNIT_NAME), getEntityType(BusinessPartner.class), schema); + assertFalse(et.hasEmbeddedKey()); + } + @Test void checkEntityWithMappedSuperClassContainsAllProperties() throws ODataJPAModelException { final IntermediateEntityType et = new IntermediateEntityType<>(new JPADefaultEdmNameBuilder(PUNIT_NAME), diff --git a/jpa/odata-jpa-processor/old.project b/jpa/odata-jpa-processor/old.project new file mode 100644 index 000000000..1fd67ec03 --- /dev/null +++ b/jpa/odata-jpa-processor/old.project @@ -0,0 +1,47 @@ + + + jpa-processor + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + + + + 1634102235540 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + \ No newline at end of file diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataQueryDirectives.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataQueryDirectives.java index 6b66f0c6e..8fc256798 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataQueryDirectives.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataQueryDirectives.java @@ -10,19 +10,28 @@ public static JPAODataQueryDirectivesBuilder with(final Builder builder) { int getMaxValuesInInClause(); - static record JPAODataQueryDirectivesImpl(int maxValuesInInClause) implements JPAODataQueryDirectives { + UuidSortOrder getUuidSortOrder(); + + static record JPAODataQueryDirectivesImpl(int maxValuesInInClause, UuidSortOrder uuidSortOrder) implements + JPAODataQueryDirectives { @Override public int getMaxValuesInInClause() { return maxValuesInInClause; } + @Override + public UuidSortOrder getUuidSortOrder() { + return uuidSortOrder; + } + } static class JPAODataQueryDirectivesBuilderImpl implements JPAODataQueryDirectivesBuilder { private final Builder parent; private int maxValuesInInClause = 0; + private UuidSortOrder uuidSortOrder = UuidSortOrder.AS_STRING; JPAODataQueryDirectivesBuilderImpl(final Builder builder) { this.parent = builder; @@ -36,7 +45,20 @@ public JPAODataQueryDirectivesBuilder maxValuesInInClause(final int maxValues) { @Override public JPAODataServiceContextBuilder build() { - return parent.setQueryDirectives(new JPAODataQueryDirectivesImpl(maxValuesInInClause)); + return parent.setQueryDirectives(new JPAODataQueryDirectivesImpl(maxValuesInInClause, uuidSortOrder)); + } + + @Override + public JPAODataQueryDirectivesBuilder uuidSortOrder(final UuidSortOrder order) { + this.uuidSortOrder = order; + return this; } } + + public enum UuidSortOrder { + AS_STRING, + AS_BYTE_ARRAY, + AS_JAVA_UUID; + } + } diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataQueryDirectivesBuilder.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataQueryDirectivesBuilder.java index 674e3496a..95392f47b 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataQueryDirectivesBuilder.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataQueryDirectivesBuilder.java @@ -1,9 +1,13 @@ package com.sap.olingo.jpa.processor.core.api; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives.UuidSortOrder; + public interface JPAODataQueryDirectivesBuilder { JPAODataQueryDirectivesBuilder maxValuesInInClause(int i); + JPAODataQueryDirectivesBuilder uuidSortOrder(UuidSortOrder order); + JPAODataServiceContextBuilder build(); } \ No newline at end of file diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataServiceContext.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataServiceContext.java index 7c1a27f9b..bb44bcba3 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataServiceContext.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/JPAODataServiceContext.java @@ -106,6 +106,7 @@ public JPAODataDatabaseOperations getOperationConverter() { return operationConverter; } + @Override public JPAODataPagingProvider getPagingProvider() { return pagingProvider; } diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/example/JPAExampleCUDRequestHandler.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/example/JPAExampleCUDRequestHandler.java index c9f4830c9..471929bbd 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/example/JPAExampleCUDRequestHandler.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/api/example/JPAExampleCUDRequestHandler.java @@ -84,7 +84,8 @@ public Object createEntity(final JPARequestEntity requestEntity, final EntityMan em.persist(instance); } } else { - // POST on Link only // https://issues.oasis-open.org/browse/ODATA-1294 + // POST on Link only + // https://issues.oasis-open.org/browse/ODATA-1294 instance = findEntity(requestEntity, em); } processRelatedEntities(requestEntity.getRelatedEntities(), instance, requestEntity.getModifyUtil(), em); @@ -109,14 +110,16 @@ public JPAUpdateResult updateEntity(final JPARequestEntity requestEntity, final final HttpMethod method) throws ODataJPAProcessException { if (method == HttpMethod.PATCH || method == HttpMethod.DELETE) { - final Object instance = em.find(requestEntity.getEntityType().getTypeClass(), requestEntity.getModifyUtil() + Object instance = em.find(requestEntity.getEntityType().getTypeClass(), requestEntity.getModifyUtil() .createPrimaryKey(requestEntity.getEntityType(), requestEntity.getKeys(), requestEntity.getEntityType())); - if (instance == null) throw new JPAExampleModifyException(ENTITY_NOT_FOUND, HttpStatusCode.NOT_FOUND); - requestEntity.getModifyUtil().setAttributesDeep(requestEntity.getData(), instance, requestEntity.getEntityType()); + if (instance == null) { + instance = createOneEntity(requestEntity, null); + requestEntity.getModifyUtil().setPrimaryKey(requestEntity.getEntityType(), requestEntity.getKeys(), instance); - updateLinks(requestEntity, em, instance); - setAuditInformation(instance, requestEntity.getClaims(), false); - return new JPAUpdateResult(false, instance); + return new JPAUpdateResult(true, instance); + } else { + return updateFoundEntity(requestEntity, em, instance); + } } return super.updateEntity(requestEntity, em, method); } @@ -128,6 +131,16 @@ public void validateChanges(final EntityManager em) throws ODataJPAProcessExcept processBindingLinks(entity.getValue().getRelationLinks(), entity.getKey(), entity.getValue().getModifyUtil(), em); } + private JPAUpdateResult updateFoundEntity(final JPARequestEntity requestEntity, final EntityManager em, + final Object instance) throws ODataJPAProcessorException, ODataJPAInvocationTargetException { + requestEntity.getModifyUtil().setAttributesDeep(requestEntity.getData(), instance, requestEntity + .getEntityType()); + + updateLinks(requestEntity, em, instance); + setAuditInformation(instance, requestEntity.getClaims(), false); + return new JPAUpdateResult(false, instance); + } + private void checkAuthorizationsOneClaim(final JPAProtectionInfo protectionInfo, final Object value, final List> pairs) throws JPAExampleModifyException { boolean match = false; diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAModifyUtil.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAModifyUtil.java index cd5be773c..eca048a81 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAModifyUtil.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPAModifyUtil.java @@ -6,6 +6,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -86,6 +87,7 @@ Map buildSetterList(@Nonnull final Class type, * * @param et * @param jpaKeys + * @param st * @return * @throws ODataJPAProcessorException */ @@ -129,6 +131,40 @@ public Object createPrimaryKey(final JPAEntityType et, final Object instance) th } } + /** + * Fills the key properties in instance. This is helpful e.g. for Upserts.
+ * Setter for the key attributes are required. + * @param et Metadata describing the entity type + * @param jpaKeys Map of key properties + * @param instance Instance of the JPA entity to be filled + * @throws ODataJPAProcessorException + */ + public void setPrimaryKey(final JPAEntityType et, final Map jpaKeys, final Object instance) + throws ODataJPAProcessorException { + try { + if (et.hasEmbeddedKey()) { + final Object key = et.getKeyType().getConstructor().newInstance(); + for (final JPAAttribute keyElement : et.getKey()) { + setAttribute(key, keyElement, jpaKeys.get(keyElement.getInternalName())); + } + final var setter = Arrays.stream(instance.getClass().getMethods()) + .filter(method -> method.getParameterCount() == 1 + && method.getParameters()[0].getType() == et.getKeyType()) + .findAny(); + if (setter.isPresent()) { + setter.get().invoke(instance, key); + } + } else { + for (final var key : et.getKey()) { + setAttribute(instance, key, jpaKeys.get(key.getInternalName())); + } + } + } catch (NoSuchMethodException | SecurityException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException | InstantiationException | ODataJPAModelException e) { + throw new ODataJPAProcessorException(e, HttpStatusCode.INTERNAL_SERVER_ERROR); + } + } + /** * Sets a link between a source and target instance. Prerequisite are * existing setter and getter on the level of the sourceInstance. In case of to n associations it is expected that the @@ -424,7 +460,8 @@ private void setEmbeddedAttributeDeep(final Object instance, final JPAStructured } @SuppressWarnings("unchecked") - private void setEmbeddedCollectionAttributeDeep(final Object instance, final JPAStructuredType st, final Method method, + private void setEmbeddedCollectionAttributeDeep(final Object instance, final JPAStructuredType st, + final Method method, final Object value, final Class[] parameters, final JPAAttribute attribute) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ODataJPAModelException, ODataJPAProcessorException, ODataJPAInvocationTargetException { diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPANavigationRequestProcessor.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPANavigationRequestProcessor.java index 800363746..bc1f0ef8b 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPANavigationRequestProcessor.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/processor/JPANavigationRequestProcessor.java @@ -213,8 +213,8 @@ JPAETagValidationResult validateEntityTag(final JPAConvertibleResult result, fin return JPAETagValidationResult.SUCCESS; } - boolean isRootResultEmpty(JPAConvertibleResult result) { - if (result instanceof JPAExpandResult expandResult) { + private boolean isRootResultEmpty(final JPAConvertibleResult result) { + if (result instanceof final JPAExpandResult expandResult) { return expandResult.getResult(ROOT_RESULT_KEY).isEmpty(); } return false; diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/properties/JPAAbstractProcessorAttributeImpl.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/properties/JPAAbstractProcessorAttributeImpl.java index 21d269bb4..1d3868711 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/properties/JPAAbstractProcessorAttributeImpl.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/properties/JPAAbstractProcessorAttributeImpl.java @@ -81,4 +81,9 @@ public boolean requiresJoin() { return !hops.isEmpty(); } + @Override + public JPAPath getJPAPath() { + return path; + } + } diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/properties/JPAProcessorAttribute.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/properties/JPAProcessorAttribute.java index 7948ea141..1b7b3330f 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/properties/JPAProcessorAttribute.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/properties/JPAProcessorAttribute.java @@ -11,6 +11,7 @@ import jakarta.persistence.criteria.Order; import jakarta.persistence.criteria.Path; +import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAPath; import com.sap.olingo.jpa.processor.core.exception.ODataJPAQueryException; public interface JPAProcessorAttribute { @@ -75,4 +76,6 @@ JPAProcessorAttribute setTarget(@Nonnull final From target, @Nonnull final */ Path getPath(); + JPAPath getJPAPath(); + } diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryResult.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryResult.java index b224b83c1..f7b1264e8 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryResult.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryResult.java @@ -222,7 +222,7 @@ public Optional getKeyBoundary(final JPAODataRequestContextAcces && (requestContext.getUriInfo().getTopOption() != null || requestContext.getUriInfo().getSkipOption() != null)) { - final JPAKeyPair boundary = new JPAKeyPair(jpaEntityType.getKey()); + final JPAKeyPair boundary = new JPAKeyPair(jpaEntityType.getKey(), requestContext.getQueryDirectives()); for (final Tuple tuple : jpaResult.get(ROOT_RESULT_KEY)) { @SuppressWarnings("rawtypes") final Map key = createKey(tuple); diff --git a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAKeyPair.java b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAKeyPair.java index af392da2e..26751df70 100644 --- a/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAKeyPair.java +++ b/jpa/odata-jpa-processor/src/main/java/com/sap/olingo/jpa/processor/core/query/JPAKeyPair.java @@ -1,11 +1,15 @@ package com.sap.olingo.jpa.processor.core.query; +import java.nio.ByteBuffer; import java.util.List; import java.util.Map; +import java.util.UUID; import jakarta.persistence.AttributeConverter; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAAttribute; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives.UuidSortOrder; import com.sap.olingo.jpa.processor.core.exception.ODataJPAKeyPairException; /** @@ -25,10 +29,12 @@ public class JPAKeyPair { private Map min; private Map max; private final List keyDefinition; + private final UuidSortOrder uuidSortOrder; - public JPAKeyPair(final List keyDef) { + public JPAKeyPair(final List keyDef, final JPAODataQueryDirectives queryDirectives) { super(); this.keyDefinition = keyDef; + this.uuidSortOrder = queryDirectives.getUuidSortOrder(); } public Map getMin() { @@ -95,6 +101,13 @@ private int compareValues(final Comparable value, final Map value.toString().compareTo(uuid.toString()); + case AS_BYTE_ARRAY -> new ComparableByteArray(convertUUIDToBytes((UUID) value)) + .compareTo(convertUUIDToBytes(uuid)); + case AS_JAVA_UUID -> value.compareTo(uuid); + }; } return value.compareTo(minValue); } @@ -103,4 +116,11 @@ private int compareValues(final Comparable value, final Map createOrderByList(@Nonnull final Map> joinTables, LOGGER.trace("Determined $top/$skip or page: add primary key to Order By"); final var factory = new JPAOrderByPropertyFactory(); for (final var key : jpaEntity.getKey()) { - orderByAttributes.add(factory.createProperty(target, jpaEntity.getPath(key.getExternalName()), cb)); + if (!containsAttribute(orderByAttributes, key)) + orderByAttributes.add(factory.createProperty(target, jpaEntity.getPath(key.getExternalName()), cb)); } } @@ -132,6 +134,18 @@ List createOrderByList(@Nonnull final Map> joinTables, return result; } + private boolean containsAttribute(final List orderByAttributes, final JPAAttribute key) + throws ODataJPAModelException { + + var found = false; + for (final var attribute : orderByAttributes) { + found = attribute.getJPAPath().equals(jpaEntity.getPath(key.getExternalName())); + if (found) + break; + } + return found; + } + @Nonnull List createOrderByList(final Map> joinTables) { return Collections.emptyList(); diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/api/example/JPAExampleCUDRequestHandlerTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/api/example/JPAExampleCUDRequestHandlerTest.java index 34a3d2748..d7f57b4ac 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/api/example/JPAExampleCUDRequestHandlerTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/api/example/JPAExampleCUDRequestHandlerTest.java @@ -443,22 +443,24 @@ void checkCreateEntityAutoIdNoJpaEntityType() throws ODataJPAProcessException, O } @Test - void checkUpdateEntityNotFound() throws ODataJPAProcessException, ODataJPAModelException { - final String id = "1"; + void checkUpdateEntityNotFoundUpsertsEntity() throws ODataJPAModelException, ODataJPAProcessException { + final String id = "100"; final Organization beforeImage = new Organization(id); final JPAEntityType et = helper.getJPAEntityType("Organizations"); beforeImage.setName1("Example Ltd"); doReturn(et).when(requestEntity).getEntityType(); doReturn(null).when(em).find(eq(et.getTypeClass()), any()); - data.put("name1", "Example SE"); keys.put("iD", id); - final ODataJPAProcessException exception = assertThrows(ODataJPAProcessException.class, () -> cut.updateEntity( - requestEntity, em, HttpMethod.PATCH)); + final var act = cut.updateEntity(requestEntity, em, HttpMethod.PATCH); + + assertNotNull(act); + assertTrue(act.wasCreate()); - assertEquals(404, exception.getStatusCode()); + final Organization org = (Organization) act.modifiedEntity(); + assertEquals("100", org.getID()); } @@ -768,16 +770,14 @@ void checkAuditFieldsSetOnUpdate() throws ODataJPAModelException, ODataJPAProces } @Test - void checkAuthorizationsCreateRejectsNotClaimsNotAllowed() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectsNotClaimsNotAllowed() { final JPAExampleModifyException act = assertThrows(JPAExampleModifyException.class, () -> createPersonProtected(null)); assertEquals(HttpStatusCode.FORBIDDEN.getStatusCode(), act.getStatusCode()); } @Test - void checkAuthorizationsCreateRejectsAttributeNotPresent() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectsAttributeNotPresent() { final JPAODataClaimProvider claims = mock(JPAODataClaimProvider.class); final JPAExampleModifyException act = assertThrows(JPAExampleModifyException.class, () -> createPersonProtected( claims)); @@ -785,8 +785,7 @@ void checkAuthorizationsCreateRejectsAttributeNotPresent() throws ODataJPAModelE } @Test - void checkAuthorizationsCreateRejectsAttributeNotMatch() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectsAttributeNotMatch() { final JPAClaimsPair claim = new JPAClaimsPair<>("DOT01"); final JPAODataClaimProvider claims = mock(JPAODataClaimProvider.class); when(claims.get("BuildingNumber")).thenReturn(singletonList(claim)); @@ -796,8 +795,7 @@ void checkAuthorizationsCreateRejectsAttributeNotMatch() throws ODataJPAModelExc } @Test - void checkAuthorizationsCreateRejectedOnlyOneProvided() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectedOnlyOneProvided() { final JPAClaimsPair claim = new JPAClaimsPair<>("MID*"); final JPAODataClaimProvider claims = mock(JPAODataClaimProvider.class); when(claims.get("BuildingNumber")).thenReturn(singletonList(claim)); @@ -828,8 +826,7 @@ void checkAuthorizationsCreateAllowedWithWildCardMix() throws ODataJPAModelExcep } @Test - void checkAuthorizationsCreateRejectsWildCardNotMatch() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectsWildCardNotMatch() { final JPAClaimsPair claim = new JPAClaimsPair<>("D_D*"); final JPAExampleModifyException act = assertThrows(JPAExampleModifyException.class, () -> createPersonProtected(createPersonProtectedClaims(claim))); @@ -851,8 +848,7 @@ void checkAuthorizationsCreateAllowedInRangeWildcard() throws ODataJPAModelExcep } @Test - void checkAuthorizationsCreateRejectRangeWildcardMin() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectRangeWildcardMin() { final JPAClaimsPair claim = new JPAClaimsPair<>("MI+0*", "MID99"); final JPAExampleModifyException act = assertThrows(JPAExampleModifyException.class, () -> createPersonProtected(createPersonProtectedClaims(claim))); @@ -860,8 +856,7 @@ void checkAuthorizationsCreateRejectRangeWildcardMin() throws ODataJPAModelExcep } @Test - void checkAuthorizationsCreateRejectRangeWildcardMax() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectRangeWildcardMax() { final JPAClaimsPair claim = new JPAClaimsPair<>("MID00", "MI*99"); final JPAExampleModifyException act = assertThrows(JPAExampleModifyException.class, () -> createPersonProtected(createPersonProtectedClaims(claim))); @@ -890,8 +885,7 @@ void checkAuthorizationsCreateAllowedInRange() throws ODataJPAModelException, // } @Test - void checkAuthorizationsCreateRejectRangeToLow() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectRangeToLow() throws ODataJPAModelException { buildOrganizationMockForAuthorizationTest(); data.put("id", 5); @@ -901,8 +895,7 @@ void checkAuthorizationsCreateRejectRangeToLow() throws ODataJPAModelException, } @Test - void checkAuthorizationsCreateRejectRangeToHigh() throws ODataJPAModelException, - ODataJPAProcessException { + void checkAuthorizationsCreateRejectRangeToHigh() throws ODataJPAModelException { buildOrganizationMockForAuthorizationTest(); data.put("id", 500); @@ -953,12 +946,8 @@ private void buildOrganizationMockForAuthorizationTest() throws ODataJPAModelExc when(path.getPath()).thenReturn(singletonList(idAttribute)); - when(et.getTypeClass()).thenAnswer(new Answer>() { - @Override - public Class answer(final InvocationOnMock invocation) throws Throwable { - return OrganizationWithAudit.class; - } - }); + doReturn(OrganizationWithAudit.class).when(et).getTypeClass(); + when(et.getKey()).thenReturn(singletonList(idAttribute)); when(et.getProtections()).thenReturn(singletonList(protectionInfo)); when(et.getAttribute("id")).thenReturn(Optional.of(idAttribute)); @@ -1008,8 +997,7 @@ private Object createAdminDiv() throws ODataJPAModelException, ODataJPAProcessEx data.put("countryCode", "DEU"); data.put("codePublisher", "Eurostat"); - final Object act = cut.createEntity(requestEntity, em); - return act; + return cut.createEntity(requestEntity, em); } private OrganizationWithAudit createOrganization() throws ODataJPAModelException, ODataJPAProcessException { @@ -1083,7 +1071,6 @@ private JPAUpdateResult updateSimplePrimitiveValue() throws ODataJPAModelExcepti data.put("name1", "Example SE"); keys.put("iD", id); - final JPAUpdateResult act = cut.updateEntity(requestEntity, em, HttpMethod.PATCH); - return act; + return cut.updateEntity(requestEntity, em, HttpMethod.PATCH); } } diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAModifyUtilTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAModifyUtilTest.java index 0f123eb2a..95f309f9a 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAModifyUtilTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAModifyUtilTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -20,8 +21,6 @@ import org.apache.olingo.commons.api.ex.ODataException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAAssociationPath; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAAttribute; @@ -30,6 +29,8 @@ import com.sap.olingo.jpa.processor.core.exception.ODataJPAInvocationTargetException; import com.sap.olingo.jpa.processor.core.exception.ODataJPAProcessException; import com.sap.olingo.jpa.processor.core.exception.ODataJPAProcessorException; +import com.sap.olingo.jpa.processor.core.testmodel.AdministrativeDivision; +import com.sap.olingo.jpa.processor.core.testmodel.AdministrativeDivisionDescription; import com.sap.olingo.jpa.processor.core.testmodel.AdministrativeDivisionKey; import com.sap.olingo.jpa.processor.core.testmodel.BusinessPartner; import com.sap.olingo.jpa.processor.core.testmodel.BusinessPartnerRole; @@ -119,8 +120,7 @@ void testSetAttributesDeepMultipleAttribute() throws ODataJPAProcessException { } @Test - void testSetAttributeDeepIfAttributeNull() throws ODataJPAProcessException, - ODataJPAInvocationTargetException { + void testSetAttributeDeepIfAttributeNull() throws ODataJPAProcessException { partner.setType("2"); jpaAttributes.put("iD", "Willi"); jpaAttributes.put("type", null); @@ -130,8 +130,7 @@ void testSetAttributeDeepIfAttributeNull() throws ODataJPAProcessException, } @Test - void testDoNotSetAttributeDeepIfNotInMap() throws ODataJPAProcessException, - ODataJPAInvocationTargetException { + void testDoNotSetAttributeDeepIfNotInMap() throws ODataJPAProcessException { partner.setType("2"); jpaAttributes.put("iD", "Willi"); cut.setAttributesDeep(jpaAttributes, partner, org); @@ -140,8 +139,7 @@ void testDoNotSetAttributeDeepIfNotInMap() throws ODataJPAProcessException, } @Test - void testSetAttributesDeepShallIgnoreRequestEntities() throws ODataJPAProcessException, - ODataJPAInvocationTargetException { + void testSetAttributesDeepShallIgnoreRequestEntities() throws ODataJPAProcessException { try { final JPARequestEntity roles = mock(JPARequestEntity.class); jpaAttributes.put("iD", "Willi"); @@ -154,8 +152,7 @@ void testSetAttributesDeepShallIgnoreRequestEntities() throws ODataJPAProcessExc } @Test - void testSetAttributesDeepOneLevelViaGetter() throws ODataJPAProcessException, - ODataJPAInvocationTargetException, ODataJPAModelException { + void testSetAttributesDeepOneLevelViaGetter() throws ODataJPAProcessException { final Map embeddedAttributes = new HashMap<>(); jpaAttributes.put("iD", "Willi"); jpaAttributes.put("address", embeddedAttributes); @@ -183,8 +180,7 @@ void testSetAttributesDeepOneLevelViaGetterWithWrongRequestData() throws Throwab } @Test - void testDoNotSetAttributesDeepOneLevelIfNotProvided() throws ODataJPAProcessException, - ODataJPAInvocationTargetException { + void testDoNotSetAttributesDeepOneLevelIfNotProvided() throws ODataJPAProcessException { jpaAttributes.put("iD", "Willi"); jpaAttributes.put("address", null); cut.setAttributesDeep(jpaAttributes, partner, org); @@ -194,8 +190,7 @@ void testDoNotSetAttributesDeepOneLevelIfNotProvided() throws ODataJPAProcessExc } @Test - void testSetAttributesDeepOneLevelIfNull() throws ODataJPAProcessException, - ODataJPAInvocationTargetException { + void testSetAttributesDeepOneLevelIfNull() throws ODataJPAProcessException { final PostalAddressData address = new PostalAddressData(); address.setCityName("Test City"); @@ -209,8 +204,7 @@ void testSetAttributesDeepOneLevelIfNull() throws ODataJPAProcessException, } @Test - void testSetAttributesDeepOneLevelViaSetter() throws ODataJPAProcessException, - ODataJPAInvocationTargetException, ODataJPAModelException { + void testSetAttributesDeepOneLevelViaSetter() throws ODataJPAProcessException { final Map embeddedAttributes = new HashMap<>(); jpaAttributes.put("iD", "Willi"); jpaAttributes.put("communicationData", embeddedAttributes); @@ -223,7 +217,7 @@ void testSetAttributesDeepOneLevelViaSetter() throws ODataJPAProcessException, } @Test - void testSetAttributesDeepTwoLevel() throws ODataJPAProcessException, ODataJPAModelException { + void testSetAttributesDeepTwoLevel() throws ODataJPAProcessException { final Map embeddedAttributes = new HashMap<>(); final Map innerEmbeddedAttributes = new HashMap<>(); jpaAttributes.put("iD", "Willi"); @@ -242,12 +236,7 @@ void testSetAttributesDeepTwoLevel() throws ODataJPAProcessException, ODataJPAMo void testCreatePrimaryKeyOneStringKeyField() throws ODataJPAProcessException, ODataJPAModelException { final JPAEntityType et = createSingleKeyEntityType(); - when(et.getKeyType()).thenAnswer(new Answer>() { - @Override - public Class answer(final InvocationOnMock invocation) throws Throwable { - return String.class; - } - }); + doReturn(String.class).when(et).getKeyType(); jpaAttributes.put("iD", "Willi"); final String act = (String) cut.createPrimaryKey(et, jpaAttributes, org); @@ -258,12 +247,7 @@ public Class answer(final InvocationOnMock invocation) throws Throwable { void testCreatePrimaryKeyOneIntegerKeyField() throws ODataJPAProcessException, ODataJPAModelException { final JPAEntityType et = createSingleKeyEntityType(); - when(et.getKeyType()).thenAnswer(new Answer>() { - @Override - public Class answer(final InvocationOnMock invocation) throws Throwable { - return Integer.class; - } - }); + doReturn(Integer.class).when(et).getKeyType(); jpaAttributes.put("iD", Integer.valueOf(10)); final Integer act = (Integer) cut.createPrimaryKey(et, jpaAttributes, org); @@ -274,12 +258,7 @@ public Class answer(final InvocationOnMock invocation) throws Throwable { void testCreatePrimaryKeyOneBigIntegerKeyField() throws ODataJPAProcessException, ODataJPAModelException { final JPAEntityType et = createSingleKeyEntityType(); - when(et.getKeyType()).thenAnswer(new Answer>() { - @Override - public Class answer(final InvocationOnMock invocation) throws Throwable { - return BigInteger.class; - } - }); + doReturn(BigInteger.class).when(et).getKeyType(); jpaAttributes.put("iD", new BigInteger("10")); final BigInteger act = (BigInteger) cut.createPrimaryKey(et, jpaAttributes, org); @@ -287,15 +266,10 @@ public Class answer(final InvocationOnMock invocation) throws Throwable { } @Test - void testCreatePrimaryKeyMultipleField() throws ODataJPAProcessException, ODataJPAModelException { + void testCreatePrimaryKeyMultipleField() throws ODataJPAProcessException { final JPAEntityType et = mock(JPAEntityType.class); - when(et.getKeyType()).thenAnswer(new Answer>() { - @Override - public Class answer(final InvocationOnMock invocation) throws Throwable { - return AdministrativeDivisionKey.class; - } - }); + doReturn(AdministrativeDivisionKey.class).when(et).getKeyType(); jpaAttributes.put("codePublisher", "Test"); jpaAttributes.put("codeID", "10"); @@ -321,6 +295,52 @@ void testDeepLinkComplexNotExist() throws ODataJPAProcessorException, ODataJPAMo assertEquals(target, source.getAdministrativeInformation().getUpdated().getUser()); } + @Test + void testSetPrimitiveKeyString() throws ODataJPAModelException, ODataJPAProcessorException { + + final var et = helper.getJPAEntityType(Person.class); + final var act = new Person(); + jpaAttributes.put("iD", "10"); + + cut.setPrimaryKey(et, jpaAttributes, act); + assertEquals("10", act.getID()); + } + + @Test + void testSetCompoundKeyString() throws ODataJPAModelException, ODataJPAProcessorException { + + final var et = helper.getJPAEntityType(AdministrativeDivision.class); + final var act = new AdministrativeDivision(); + jpaAttributes.put("codePublisher", "Test"); + jpaAttributes.put("codeID", "10"); + jpaAttributes.put("divisionCode", "10.1"); + + cut.setPrimaryKey(et, jpaAttributes, act); + assertEquals("Test", act.getCodePublisher()); + assertEquals("10", act.getCodeID()); + assertEquals("10.1", act.getDivisionCode()); + } + + @Test + void testSetEmbeddedKeyString() throws ODataJPAModelException, ODataJPAProcessorException { + + final var et = helper.getJPAEntityType(AdministrativeDivisionDescription.class); + final var act = new AdministrativeDivisionDescription(); + jpaAttributes.put("codePublisher", "Test"); + jpaAttributes.put("codeID", "10"); + jpaAttributes.put("divisionCode", "10.1"); + jpaAttributes.put("language", "DE"); + + cut.setPrimaryKey(et, jpaAttributes, act); + + final var key = act.getKey(); + + assertEquals("Test", key.getCodePublisher()); + assertEquals("10", key.getCodeID()); + assertEquals("10.1", key.getDivisionCode()); + assertEquals("DE", key.getLanguage()); + } + @Test void testDirectLink() throws ODataJPAProcessorException, ODataJPAModelException { final Organization source = new Organization("100"); @@ -350,8 +370,7 @@ void testSetForeignKeyOneKey() throws ODataJPAModelException, ODataJPAProcessorE } @Test - void testSetForeignKeyThrowsExceptionOnMissingGetter() throws ODataJPAModelException, - ODataJPAProcessorException { + void testSetForeignKeyThrowsExceptionOnMissingGetter() throws ODataJPAModelException { final OrganizationWithoutGetter source = new OrganizationWithoutGetter("100"); final BusinessPartnerRole target = new BusinessPartnerRole(); target.setRoleCategory("A"); @@ -363,8 +382,7 @@ void testSetForeignKeyThrowsExceptionOnMissingGetter() throws ODataJPAModelExcep } @Test - void testSetForeignKeyThrowsExceptionOnMissingSetter() throws ODataJPAModelException, - ODataJPAProcessorException { + void testSetForeignKeyThrowsExceptionOnMissingSetter() throws ODataJPAModelException { final Organization source = new Organization("100"); final BusinessPartnerRoleWithoutSetter target = new BusinessPartnerRoleWithoutSetter(); final JPAAssociationPath path = helper.getJPAAssociationPath("Organizations", diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContextTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContextTest.java index cc3185065..78dac8e5e 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContextTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/processor/JPAODataInternalRequestContextTest.java @@ -50,6 +50,7 @@ import com.sap.olingo.jpa.processor.core.api.JPAODataPagingProvider; import com.sap.olingo.jpa.processor.core.api.JPAODataPathInformation; import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives.UuidSortOrder; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContext; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContextAccess; import com.sap.olingo.jpa.processor.core.api.JPAODataSessionContextAccess; @@ -115,7 +116,7 @@ void setup() { dbProcessor = mock(JPAODataDatabaseProcessor.class); edmProvider = mock(JPAEdmProvider.class); operationConverter = mock(JPAODataDatabaseOperations.class); - queryDirectives = new JPAODataQueryDirectives.JPAODataQueryDirectivesImpl(0); + queryDirectives = new JPAODataQueryDirectives.JPAODataQueryDirectivesImpl(0, UuidSortOrder.AS_STRING); pagingProvider = mock(JPAODataPagingProvider.class); etagHelper = mock(JPAODataEtagHelper.class); pathInformation = new JPAODataPathInformation("", "", "", ""); diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryResultTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryResultTest.java index a05116803..e4097c7b9 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryResultTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryResultTest.java @@ -31,6 +31,8 @@ import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAEntityType; import com.sap.olingo.jpa.metadata.core.edm.mapper.exception.ODataJPAModelException; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives.UuidSortOrder; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContextAccess; import com.sap.olingo.jpa.processor.core.exception.ODataJPAProcessException; import com.sap.olingo.jpa.processor.core.util.TestBase; @@ -49,6 +51,7 @@ class JPAExpandQueryResultTest extends TestBase { private final List tuples = new ArrayList<>(); private JPAEntityType et; private List hops; + private JPAODataQueryDirectives directives; @BeforeEach void setup() throws ODataException { @@ -61,11 +64,13 @@ void setup() throws ODataException { hops = Arrays.asList(hop0, hop1); et = helper.getJPAEntityType("Organizations"); uriInfo = mock(UriInfoResource.class); + directives = new JPAODataQueryDirectives.JPAODataQueryDirectivesImpl(0, UuidSortOrder.AS_JAVA_UUID); requestContext = mock(JPAODataRequestContextAccess.class); top = mock(TopOption.class); skip = mock(SkipOption.class); expand = mock(ExpandOption.class); when(requestContext.getUriInfo()).thenReturn(uriInfo); + when(requestContext.getQueryDirectives()).thenReturn(directives); queryResult.put("root", tuples); } diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryTest.java index d13c37128..7655ae930 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAExpandQueryTest.java @@ -35,6 +35,8 @@ import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAAttribute; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAEntityType; import com.sap.olingo.jpa.metadata.core.edm.mapper.exception.ODataJPAModelException; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives.UuidSortOrder; import com.sap.olingo.jpa.processor.core.api.JPAODataRequestContextAccess; import com.sap.olingo.jpa.processor.core.api.JPAServiceDebugger; import com.sap.olingo.jpa.processor.core.database.JPADefaultDatabaseProcessor; @@ -57,16 +59,18 @@ abstract class JPAExpandQueryTest extends TestBase { protected Optional adminBoundary; @SuppressWarnings("rawtypes") protected Map simpleKey; + private JPAODataQueryDirectives directives; @BeforeEach void setup() throws ODataException { createHeaders(); helper = new TestHelper(emf, PUNIT_NAME); em = emf.createEntityManager(); + directives = new JPAODataQueryDirectives.JPAODataQueryDirectivesImpl(0, UuidSortOrder.AS_JAVA_UUID); requestContext = mock(JPAODataRequestContextAccess.class); - organizationPair = new JPAKeyPair(helper.getJPAEntityType("Organizations").getKey()); + organizationPair = new JPAKeyPair(helper.getJPAEntityType("Organizations").getKey(), directives); organizationBoundary = Optional.of(new JPAKeyBoundary(1, organizationPair)); - adminPair = new JPAKeyPair(helper.getJPAEntityType("AdministrativeDivisions").getKey()); + adminPair = new JPAKeyPair(helper.getJPAEntityType("AdministrativeDivisions").getKey(), directives); adminBoundary = Optional.of(new JPAKeyBoundary(1, adminPair)); final JPAServiceDebugger debugger = mock(JPAServiceDebugger.class); diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAKeyPairTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAKeyPairTest.java index 81bd9140c..a84dcf07e 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAKeyPairTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAKeyPairTest.java @@ -6,8 +6,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Arrays; @@ -21,12 +21,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAAttribute; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives; +import com.sap.olingo.jpa.processor.core.api.JPAODataQueryDirectives.UuidSortOrder; import com.sap.olingo.jpa.processor.core.exception.ODataJPAKeyPairException; -import com.sap.olingo.jpa.processor.core.exception.ODataJPAQueryException; import com.sap.olingo.jpa.processor.core.testmodel.UUIDToBinaryConverter; import com.sap.olingo.jpa.processor.core.testmodel.UUIDToStringConverter; @@ -40,9 +39,11 @@ class JPAKeyPairTest { private Map key2; private Map key3; private List keyDef; + private JPAODataQueryDirectives directives; @BeforeEach void setup() { + directives = new JPAODataQueryDirectives.JPAODataQueryDirectivesImpl(0, UuidSortOrder.AS_STRING); attribute1 = mock(JPAAttribute.class); attribute2 = mock(JPAAttribute.class); attribute3 = mock(JPAAttribute.class); @@ -51,7 +52,7 @@ void setup() { key3 = new HashMap<>(3); keyDef = new ArrayList<>(3); keyDef.add(attribute1); - cut = new JPAKeyPair(keyDef); + cut = new JPAKeyPair(keyDef, directives); key1.put(attribute1, Integer.valueOf(10)); key2.put(attribute1, Integer.valueOf(100)); } @@ -79,7 +80,7 @@ void testCreatePairWithOneValues() throws ODataJPAKeyPairException { } @Test - void testCreatePairWithTwoValues() throws ODataJPAQueryException, ODataJPAKeyPairException { + void testCreatePairWithTwoValues() throws ODataJPAKeyPairException { cut.setValue(key1); cut.setValue(key2); assertEquals(10, cut.getMin().get(attribute1)); @@ -88,7 +89,7 @@ void testCreatePairWithTwoValues() throws ODataJPAQueryException, ODataJPAKeyPai } @Test - void testCreatePairWithTwoValuesSecondLower() throws ODataJPAQueryException, ODataJPAKeyPairException { + void testCreatePairWithTwoValuesSecondLower() throws ODataJPAKeyPairException { cut.setValue(key2); cut.setValue(key1); assertEquals(10, cut.getMin().get(attribute1)); @@ -97,7 +98,7 @@ void testCreatePairWithTwoValuesSecondLower() throws ODataJPAQueryException, ODa } @Test - void testCreatePairWithThirdValuesHigher() throws ODataJPAQueryException, ODataJPAKeyPairException { + void testCreatePairWithThirdValuesHigher() throws ODataJPAKeyPairException { key3.put(attribute1, Integer.valueOf(101)); cut.setValue(key2); cut.setValue(key1); @@ -107,7 +108,7 @@ void testCreatePairWithThirdValuesHigher() throws ODataJPAQueryException, ODataJ } @Test - void testCreatePairWithThirdValuesLower() throws ODataJPAQueryException, ODataJPAKeyPairException { + void testCreatePairWithThirdValuesLower() throws ODataJPAKeyPairException { key3.put(attribute1, Integer.valueOf(9)); cut.setValue(key2); cut.setValue(key1); @@ -117,7 +118,7 @@ void testCreatePairWithThirdValuesLower() throws ODataJPAQueryException, ODataJP } @Test - void testCreatePairWithThirdValuesBetween() throws ODataJPAQueryException, ODataJPAKeyPairException { + void testCreatePairWithThirdValuesBetween() throws ODataJPAKeyPairException { key3.put(attribute1, Integer.valueOf(50)); cut.setValue(key2); cut.setValue(key1); @@ -207,20 +208,10 @@ void testCreatePairWithThreeCompoundLastKeySmallest() throws ODataJPAKeyPairExce @Test void testCreatePairConversionString() { final JPAAttribute attributeUUID = mock(JPAAttribute.class); - when(attributeUUID.getConverter()).thenAnswer(new Answer() { - @Override - public UUIDToStringConverter answer(final InvocationOnMock invocation) throws Throwable { - return new UUIDToStringConverter(); - } - }); - when(attributeUUID.getRawConverter()).thenAnswer(new Answer() { - @Override - public UUIDToStringConverter answer(final InvocationOnMock invocation) throws Throwable { - return new UUIDToStringConverter(); - } - }); - - cut = new JPAKeyPair(Collections.singletonList(attributeUUID)); + doReturn(new UUIDToStringConverter()).when(attributeUUID).getConverter(); + doReturn(new UUIDToStringConverter()).when(attributeUUID).getRawConverter(); + + cut = new JPAKeyPair(Collections.singletonList(attributeUUID), directives); Arrays.asList("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", "52a4eb6d-ab9d-4bc8-8405-5255d9607441", "59ce6d1c-0770-48ae-b9ea-47c4ce9994c1", "9768b78c-e010-4e62-bada-8a138be7334d", @@ -235,27 +226,11 @@ public UUIDToStringConverter answer(final InvocationOnMock invocation) throws Th @Test void testCreatePairConversionByteArray() { final JPAAttribute attributeUUID = mock(JPAAttribute.class); - when(attributeUUID.getDbType()).thenAnswer(new Answer>() { - @Override - public Class answer(final InvocationOnMock invocation) throws Throwable { - return byte[].class; - } - }); - when(attributeUUID.getConverter()).thenAnswer(new Answer() { - @Override - public UUIDToBinaryConverter answer(final InvocationOnMock invocation) throws Throwable { - return new UUIDToBinaryConverter(); - } - }); - - when(attributeUUID.getRawConverter()).thenAnswer(new Answer() { - @Override - public UUIDToBinaryConverter answer(final InvocationOnMock invocation) throws Throwable { - return new UUIDToBinaryConverter(); - } - }); - - cut = new JPAKeyPair(Collections.singletonList(attributeUUID)); + doReturn(byte[].class).when(attributeUUID).getDbType(); + doReturn(new UUIDToBinaryConverter()).when(attributeUUID).getConverter(); + doReturn(new UUIDToBinaryConverter()).when(attributeUUID).getRawConverter(); + + cut = new JPAKeyPair(Collections.singletonList(attributeUUID), directives); Arrays.asList("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", "52a4eb6d-ab9d-4bc8-8405-5255d9607441", "59ce6d1c-0770-48ae-b9ea-47c4ce9994c1", "9768b78c-e010-4e62-bada-8a138be7334d", @@ -270,33 +245,74 @@ public UUIDToBinaryConverter answer(final InvocationOnMock invocation) throws Th @Test void testCreatePairConversionTargetNotComparable() throws ODataJPAKeyPairException { final JPAAttribute attribute = mock(JPAAttribute.class); - when(attribute.getDbType()).thenAnswer(new Answer>() { - @Override - public Class answer(final InvocationOnMock invocation) throws Throwable { - return NotComparable.class; - } - }); - when(attribute.getConverter()).thenAnswer(new Answer() { - @Override - public NotComparableConverter answer(final InvocationOnMock invocation) throws Throwable { - return new NotComparableConverter(); - } - }); - - when(attribute.getRawConverter()).thenAnswer(new Answer() { - @Override - public NotComparableConverter answer(final InvocationOnMock invocation) throws Throwable { - return new NotComparableConverter(); - } - }); - - cut = new JPAKeyPair(Collections.singletonList(attribute)); + doReturn(NotComparable.class).when(attribute).getDbType(); + doReturn(new NotComparableConverter()).when(attribute).getConverter(); + doReturn(new NotComparableConverter()).when(attribute).getRawConverter(); + + cut = new JPAKeyPair(Collections.singletonList(attribute), directives); final Map key = new HashMap<>(3); key.put(attribute, "Hallo"); cut.setValue(key); assertThrows(ODataJPAKeyPairException.class, () -> cut.setValue(key)); } + @Test + void testCreatePairUuidSortedAsString() { + + final JPAAttribute attributeUUID = mock(JPAAttribute.class); + + cut = new JPAKeyPair(Collections.singletonList(attributeUUID), directives); + + Arrays.asList("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", "52a4eb6d-ab9d-4bc8-8405-5255d9607441", + "59ce6d1c-0770-48ae-b9ea-47c4ce9994c1", "9768b78c-e010-4e62-bada-8a138be7334d", + "e5406bb9-7166-4c0a-928c-f6deed6325bc").forEach(u -> addUUID(attributeUUID, u)); + + assertTrue(cut.hasUpperBoundary()); + assertEquals("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", cut.getMinElement(attributeUUID).toString()); + assertEquals("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", cut.getMin().get(attributeUUID).toString()); + assertEquals("e5406bb9-7166-4c0a-928c-f6deed6325bc", cut.getMaxElement(attributeUUID).toString()); + assertEquals("e5406bb9-7166-4c0a-928c-f6deed6325bc", cut.getMax().get(attributeUUID).toString()); + + } + + @Test + void testCreatePairUuidSortedAsByteArray() { + directives = new JPAODataQueryDirectives.JPAODataQueryDirectivesImpl(0, UuidSortOrder.AS_BYTE_ARRAY); + cut = new JPAKeyPair(keyDef, directives); + final JPAAttribute attributeUUID = mock(JPAAttribute.class); + + cut = new JPAKeyPair(Collections.singletonList(attributeUUID), directives); + + Arrays.asList("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", "52a4eb6d-ab9d-4bc8-8405-5255d9607441", + "59ce6d1c-0770-48ae-b9ea-47c4ce9994c1", "9768b78c-e010-4e62-bada-8a138be7334d", + "e5406bb9-7166-4c0a-928c-f6deed6325bc").forEach(u -> addUUID(attributeUUID, u)); + + assertTrue(cut.hasUpperBoundary()); + assertEquals("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", cut.getMinElement(attributeUUID).toString()); + assertEquals("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", cut.getMin().get(attributeUUID).toString()); + assertEquals("9768b78c-e010-4e62-bada-8a138be7334d", cut.getMaxElement(attributeUUID).toString()); + assertEquals("9768b78c-e010-4e62-bada-8a138be7334d", cut.getMax().get(attributeUUID).toString()); + } + + @Test + void testCreatePairUuidSortedAsUuid() { + directives = new JPAODataQueryDirectives.JPAODataQueryDirectivesImpl(0, UuidSortOrder.AS_JAVA_UUID); + cut = new JPAKeyPair(keyDef, directives); + final JPAAttribute attributeUUID = mock(JPAAttribute.class); + + cut = new JPAKeyPair(Collections.singletonList(attributeUUID), directives); + + Arrays.asList("400d7044-1e84-4e63-b2d9-0f58f4ca5bd0", "52a4eb6d-ab9d-4bc8-8405-5255d9607441", + "59ce6d1c-0770-48ae-b9ea-47c4ce9994c1", "9768b78c-e010-4e62-bada-8a138be7334d", + "e5406bb9-7166-4c0a-928c-f6deed6325bc").forEach(u -> addUUID(attributeUUID, u)); + + assertTrue(cut.hasUpperBoundary()); + assertEquals("9768b78c-e010-4e62-bada-8a138be7334d", cut.getMinElement(attributeUUID).toString()); + assertEquals("9768b78c-e010-4e62-bada-8a138be7334d", cut.getMin().get(attributeUUID).toString()); + assertEquals("59ce6d1c-0770-48ae-b9ea-47c4ce9994c1", cut.getMaxElement(attributeUUID).toString()); + assertEquals("59ce6d1c-0770-48ae-b9ea-47c4ce9994c1", cut.getMax().get(attributeUUID).toString()); + } + private void addUUID(final JPAAttribute attributeUUID, final String uuid) { final UUID id = UUID.fromString(uuid); try { diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAOrderByBuilderTest.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAOrderByBuilderTest.java index 08031855c..210d2e72b 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAOrderByBuilderTest.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/query/JPAOrderByBuilderTest.java @@ -171,11 +171,12 @@ void testOrderByPropertyAndTop() throws ODataException { when(uriResource.getOrderByOption()).thenReturn(orderBy); when(uriResource.getTopOption()).thenReturn(top); - final List act = cut.createOrderByList(joinTables, orderByAttributes, uriInfo); + final List act = cut.createOrderByList(joinTables, orderByAttributes, uriResource); assertFalse(act.isEmpty()); assertEquals(String.class, act.get(0).getExpression().getJavaType()); assertEquals("DivisionCode", act.get(0).getExpression().getAlias()); + assertEquals(4, act.size()); } @Test @@ -201,7 +202,7 @@ void testOrderByPropertyAndPage() throws ODataException { assertFalse(act.isEmpty()); assertEquals(String.class, act.get(0).getExpression().getJavaType()); assertEquals("DivisionCode", act.get(0).getExpression().getAlias()); - assertEquals(5, act.size()); + assertEquals(4, act.size()); } private List createOrderByClause(final Boolean isDescending) { diff --git a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/util/JPAEntityTypeDouble.java b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/util/JPAEntityTypeDouble.java index 5c11934dc..aadb5eeba 100644 --- a/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/util/JPAEntityTypeDouble.java +++ b/jpa/odata-jpa-processor/src/test/java/com/sap/olingo/jpa/processor/core/util/JPAEntityTypeDouble.java @@ -11,12 +11,12 @@ import org.apache.olingo.server.api.uri.UriResourceProperty; import com.sap.olingo.jpa.metadata.core.edm.annotation.EdmQueryExtensionProvider; -import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAEtagValidator; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAAssociationAttribute; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAAssociationPath; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAAttribute; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPACollectionAttribute; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAEntityType; +import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAEtagValidator; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAPath; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAProtectionInfo; import com.sap.olingo.jpa.metadata.core.edm.mapper.api.JPAQueryExtension; @@ -41,10 +41,10 @@ public JPAAssociationPath getAssociationPath(final String externalName) throws O return base.getAssociationPath(externalName); } + @SuppressWarnings("unchecked") @Override public List getAssociationPathList() throws ODataJPAModelException { - fail(); - return null; + return (List) failWithNull(); } @Override @@ -104,8 +104,7 @@ public JPAPath getPath(final String externalName) throws ODataJPAModelException @Override public JPAPath getPath(final String externalName, final boolean respectIgnore) throws ODataJPAModelException { - fail(); - return null; + return (JPAPath) failWithNull(); } @Override @@ -120,8 +119,7 @@ public Class getTypeClass() { @Override public boolean isAbstract() { - fail(); - return false; + return failWithFalse(); } @Override @@ -141,26 +139,24 @@ public String getInternalName() { @Override public String getContentType() throws ODataJPAModelException { - fail(); - return null; + return (String) failWithNull(); } @Override public JPAPath getContentTypeAttributePath() throws ODataJPAModelException { - fail(); - return null; + return (JPAPath) failWithNull(); } + @SuppressWarnings("unchecked") @Override public List getKey() throws ODataJPAModelException { - fail(); - return null; + return (List) failWithNull(); } + @SuppressWarnings("unchecked") @Override public List getKeyPath() throws ODataJPAModelException { - fail(); - return null; + return (List) failWithNull(); } @Override @@ -210,14 +206,17 @@ public List getProtections() throws ODataJPAModelException { @Override public JPAPath getEtagPath() throws ODataJPAModelException { - fail(); - return null; + return (JPAPath) failWithNull(); } @Override public boolean hasCompoundKey() { - fail(); - return false; + return failWithFalse(); + } + + @Override + public boolean hasEmbeddedKey() { + return failWithFalse(); } @Override @@ -247,4 +246,14 @@ public JPAEtagValidator getEtagValidator() { fail(); return JPAEtagValidator.WEAK; } + + private Object failWithNull() { + fail(); + return null; + } + + private boolean failWithFalse() { + fail(); + return false; + } } diff --git a/jpa/odata-jpa-test/src/main/resources/META-INF/persistence.xml b/jpa/odata-jpa-test/src/main/resources/META-INF/persistence.xml index 5fec96a33..dda3e0e62 100644 --- a/jpa/odata-jpa-test/src/main/resources/META-INF/persistence.xml +++ b/jpa/odata-jpa-test/src/main/resources/META-INF/persistence.xml @@ -99,13 +99,14 @@ - - + + + @@ -148,9 +149,9 @@ - - - + + + diff --git a/jpa/pom.xml b/jpa/pom.xml index 953e10441..415826997 100644 --- a/jpa/pom.xml +++ b/jpa/pom.xml @@ -19,19 +19,19 @@ 1.7.1 4.3.0 3.8.4 - 10.21.0 + 11.0.0 6.1.0 4.0.1 3.1.0 ${project.version} 6.2.0 - 4.0.3 + 4.0.4 6.4.0.Final 4.0.0 10.16.1.1 5.11.3 1.11.2 - 5.13.0 + 5.14.2 0.8.12 4.1.115.Final 2.0.16