PageRenderTime 26ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/integration/conversion/ConversionServiceTests.java

http://github.com/SpringSource/spring-data-neo4j
Java | 264 lines | 178 code | 44 blank | 42 comment | 0 complexity | 5772e6291c6b9e785e2f764573a13397 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Copyright 2011-2020 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * https://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.data.neo4j.integration.conversion;
  17. import java.lang.annotation.ElementType;
  18. import java.math.BigInteger;
  19. import java.math.RoundingMode;
  20. import java.util.Arrays;
  21. import org.junit.Before;
  22. import org.junit.Test;
  23. import org.junit.runner.RunWith;
  24. import org.neo4j.graphdb.Result;
  25. import org.neo4j.harness.ServerControls;
  26. import org.neo4j.ogm.session.Session;
  27. import org.neo4j.ogm.session.SessionFactory;
  28. import org.springframework.beans.factory.annotation.Autowired;
  29. import org.springframework.context.annotation.Bean;
  30. import org.springframework.context.annotation.ComponentScan;
  31. import org.springframework.context.annotation.Configuration;
  32. import org.springframework.core.convert.ConversionService;
  33. import org.springframework.core.convert.ConverterNotFoundException;
  34. import org.springframework.core.convert.support.DefaultConversionService;
  35. import org.springframework.data.neo4j.conversion.MetaDataDrivenConversionService;
  36. import org.springframework.data.neo4j.integration.conversion.domain.JavaElement;
  37. import org.springframework.data.neo4j.integration.conversion.domain.MonetaryAmount;
  38. import org.springframework.data.neo4j.integration.conversion.domain.PensionPlan;
  39. import org.springframework.data.neo4j.integration.conversion.domain.SiteMember;
  40. import org.springframework.data.neo4j.test.Neo4jIntegrationTest;
  41. import org.springframework.test.context.ContextConfiguration;
  42. import org.springframework.test.context.junit4.SpringRunner;
  43. import org.springframework.transaction.support.TransactionTemplate;
  44. import static org.assertj.core.api.Assertions.assertThat;
  45. /**
  46. * See DATAGRAPH-624
  47. *
  48. * @author Adam George
  49. * @author Luanne Misquitta
  50. * @author Vince Bickers
  51. * @author Mark Angrish
  52. * @author Mark Paluch
  53. * @author Jens Schauder
  54. * @author Michael J. Simons
  55. */
  56. @RunWith(SpringRunner.class)
  57. @ContextConfiguration(classes = ConversionServiceTests.ConversionServicePersistenceContext.class)
  58. public class ConversionServiceTests {
  59. @Autowired private ServerControls neo4jTestServer;
  60. @Autowired private PensionRepository pensionRepository;
  61. @Autowired private JavaElementRepository javaElementRepository;
  62. @Autowired private SiteMemberRepository siteMemberRepository;
  63. // TODO See below, for the time being at least be explicit on which type of conversion service we're working on here
  64. // The only thing that is under test, is the instance of MetaDataDrivenConversionService which get's even
  65. // modified heavily be this test. This needs to be fixed in the near future.
  66. // Also it doesn't test conversion with `graphPropertyType` attribute and a standard Spring Converter.
  67. @Autowired private MetaDataDrivenConversionService conversionService;
  68. @Autowired Session session;
  69. @Autowired private TransactionTemplate transactionTemplate;
  70. @Before
  71. public void setUp() {
  72. neo4jTestServer.graph().execute("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE r, n");
  73. }
  74. /**
  75. * This should work by virtue of the fact that there's an OGM-level converter defined on a class we've scanned.
  76. */
  77. @Test
  78. public void shouldBeAbleToConvertBetweenBytesAndBase64EncodedDataViaSpringConversionService() {
  79. String base64Representation = "YmNkZWY=";
  80. byte[] binaryData = new byte[] { 98, 99, 100, 101, 102 };
  81. assertThat(this.conversionService.canConvert(byte[].class, String.class))
  82. .isTrue();
  83. assertThat(this.conversionService.convert(binaryData, String.class))
  84. .isEqualTo(base64Representation);
  85. assertThat(this.conversionService.canConvert(String.class, byte[].class))
  86. .isTrue();
  87. assertThat(Arrays.equals(binaryData, this.conversionService
  88. .convert(base64Representation, byte[].class))).isTrue();
  89. }
  90. @Test
  91. public void shouldConvertBase64StringOutOfGraphDatabaseBackIntoByteArray() {
  92. Result rs = neo4jTestServer.graph()
  93. .execute("CREATE (u:SiteMember {profilePictureData:'MTIzNDU2Nzg5'}) RETURN id(u) AS userId");
  94. Long userId = (Long) rs.columnAs("userId").next();
  95. byte[] expectedData = "123456789".getBytes();
  96. SiteMember siteMember = this.siteMemberRepository.findById(userId).get();
  97. assertThat(Arrays.equals(expectedData, siteMember.getProfilePictureData()))
  98. .as("The data wasn't converted correctly").isTrue();
  99. }
  100. @Test
  101. public void shouldConvertFieldsUsingSpringConvertersAddedDirectlyToConversionService() {
  102. PensionPlan pensionToSave = transactionTemplate.execute(status -> {
  103. conversionService.addConverter(new SpringMonetaryAmountToIntegerConverter());
  104. conversionService.addConverter(new SpringIntegerToMonetaryAmountConverter());
  105. conversionService.addConverter(new SpringMonetaryAmountToLongConverter());
  106. conversionService.addConverter(new SpringLongToMonetaryAmountConverter());
  107. PensionPlan pensionToSave1 = new PensionPlan(new MonetaryAmount(16472, 81), "Tightfist Asset Management Ltd");
  108. pensionRepository.save(pensionToSave1);
  109. return pensionToSave1;
  110. });
  111. Result result = neo4jTestServer.graph().execute("MATCH (p:PensionPlan) RETURN p.fundValue AS fv");
  112. assertThat(result.hasNext()).as("Nothing was saved").isTrue();
  113. assertThat(String.valueOf(result.next().get("fv")))
  114. .as("The amount wasn't converted and persisted correctly")
  115. .isEqualTo("1647281");
  116. result.close();
  117. PensionPlan reloadedPension = this.pensionRepository.findById(pensionToSave.getPensionPlanId()).get();
  118. assertThat(reloadedPension.getFundValue())
  119. .as("The amount was converted incorrectly")
  120. .isEqualTo(pensionToSave.getFundValue());
  121. }
  122. /**
  123. * If target graph type is set to Integer but we have a converter for a Number then it should still save to the graph.
  124. */
  125. @Test
  126. public void shouldConvertFieldsUsingAnAvailableSupertypeConverterIfExactTypesDoNotMatch() {
  127. this.conversionService.addConverterFactory(new SpringMonetaryAmountToNumberConverterFactory());
  128. // this.conversionService.addConverter(new SpringIntegerToMonetaryAmountConverter());
  129. PensionPlan pension = new PensionPlan(new MonetaryAmount(20_000, 00), "Ashes Assets LLP");
  130. this.pensionRepository.save(pension);
  131. Result result = neo4jTestServer.graph().execute("MATCH (p:PensionPlan) RETURN p.fundValue AS fv");
  132. assertThat(result.hasNext()).as("Nothing was saved").isTrue();
  133. assertThat(String.valueOf(result.next().get("fv")))
  134. .as("The amount wasn't converted and persisted correctly")
  135. .isEqualTo("2000000");
  136. result.close();
  137. }
  138. /**
  139. * This should fix DATAGRAPH-659 too.
  140. */
  141. @Test
  142. public void shouldOperateWithDefaultSpringConvertersToConvertObjectTypesNotInMetaData() {
  143. DefaultConversionService.addDefaultConverters(this.conversionService);
  144. JavaElement method = new JavaElement();
  145. method.setName("toString");
  146. method.setElementType(ElementType.METHOD);
  147. this.javaElementRepository.save(method);
  148. Result result = neo4jTestServer.graph().execute("MATCH (e:JavaElement) RETURN e.elementType AS type");
  149. assertThat(result.hasNext()).as("Nothing was saved").isTrue();
  150. assertThat(result.next().get("type"))
  151. .as("The element type wasn't converted and persisted correctly")
  152. .isEqualTo("METHOD");
  153. result.close();
  154. JavaElement loadedObject = this.javaElementRepository.findAll().iterator().next();
  155. assertThat(loadedObject.getElementType())
  156. .as("The element type wasn't loaded and converted correctly")
  157. .isEqualTo(ElementType.METHOD);
  158. }
  159. @Test(expected = ConverterNotFoundException.class)
  160. public void shouldThrowExceptionIfSuitableConverterIsNotFound() {
  161. this.conversionService.addConverterFactory(new SpringMonetaryAmountToNumberConverterFactory());
  162. PensionPlan pension = new PensionPlan(new MonetaryAmount(20_000, 00), "Ashes Assets LLP");
  163. pension.setJavaElement(new JavaElement());
  164. this.pensionRepository.save(pension);
  165. }
  166. @Test
  167. public void shouldUseSpecifiedAttributeConverterInsteadOfSprings() {
  168. // We're registering Spring converters as well
  169. this.conversionService.addConverter(new SpringIntegerToByteArrayConverter());
  170. this.conversionService.addConverter(new SpringByteArrayToIntegerConverter());
  171. String base64Representation = "YmNkZWY=";
  172. byte[] binaryData = new byte[] { 98, 99, 100, 101, 102 };
  173. assertThat(this.conversionService.canConvert(byte[].class, String.class))
  174. .isTrue();
  175. assertThat(this.conversionService.convert(binaryData, String.class))
  176. .isEqualTo(base64Representation);
  177. assertThat(this.conversionService.canConvert(String.class, byte[].class))
  178. .isTrue();
  179. assertThat(Arrays.equals(binaryData, this.conversionService
  180. .convert(base64Representation, byte[].class))).isTrue();
  181. SiteMember siteMember = new SiteMember();
  182. siteMember.setProfilePictureData(binaryData);
  183. this.siteMemberRepository.save(siteMember);
  184. siteMember = session.loadAll(SiteMember.class).iterator().next();
  185. assertThat(siteMember.getProfilePictureData()).isEqualTo(binaryData);
  186. }
  187. @Test
  188. public void shouldUseDefaultAttributeConverterInsteadOfSprings() {
  189. // We're registering Spring converters which should not override the default ogm BigInteger converter
  190. this.conversionService.addConverter(new SpringBigIntegerToBooleanConverter());
  191. this.conversionService.addConverter(new SpringBooleanToBigIntegerConverter());
  192. byte[] binaryData = new byte[] { 98, 99, 100, 101, 102 };
  193. SiteMember siteMember = new SiteMember();
  194. siteMember.setProfilePictureData(binaryData);
  195. siteMember.setYears(BigInteger.valueOf(50));
  196. this.siteMemberRepository.save(siteMember);
  197. siteMember = session.loadAll(SiteMember.class).iterator().next();
  198. assertThat(siteMember.getProfilePictureData()).isEqualTo(binaryData);
  199. assertThat(siteMember.getYears().intValue()).isEqualTo(50);
  200. }
  201. @Test // DATAGRAPH-659
  202. public void shouldRecognizeJavaEnums() {
  203. SiteMember siteMember = new SiteMember();
  204. siteMember.setRoundingModes(Arrays.asList(RoundingMode.DOWN, RoundingMode.FLOOR));
  205. this.siteMemberRepository.save(siteMember);
  206. siteMember = session.loadAll(SiteMember.class).iterator().next();
  207. assertThat(siteMember.getRoundingModes().size()).isEqualTo(2);
  208. assertThat(siteMember.getRoundingModes().contains(RoundingMode.DOWN)).isTrue();
  209. assertThat(siteMember.getRoundingModes().contains(RoundingMode.FLOOR)).isTrue();
  210. }
  211. @Configuration
  212. @Neo4jIntegrationTest(domainPackages = "org.springframework.data.neo4j.integration.conversion.domain",
  213. repositoryPackages = "org.springframework.data.neo4j.integration.conversion")
  214. static class ConversionServicePersistenceContext {
  215. @Bean
  216. public ConversionService conversionService(SessionFactory sessionFactory) {
  217. return new MetaDataDrivenConversionService(sessionFactory.metaData());
  218. }
  219. }
  220. }