PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/addon-layers-repository-jpa/addon/src/main/java/org/springframework/roo/addon/layers/repository/jpa/addon/test/RepositoryJpaIntegrationTestMetadata.java

http://github.com/SpringSource/spring-roo
Java | 849 lines | 475 code | 167 blank | 207 comment | 19 complexity | fe277d5295e38f0879533c9204d3157f MD5 | raw file
  1. package org.springframework.roo.addon.layers.repository.jpa.addon.test;
  2. import java.lang.reflect.Modifier;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import org.apache.commons.lang3.StringUtils;
  6. import org.apache.commons.lang3.Validate;
  7. import org.apache.commons.lang3.builder.ToStringBuilder;
  8. import org.springframework.roo.addon.layers.repository.jpa.annotations.test.RooRepositoryJpaIntegrationTest;
  9. import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils;
  10. import org.springframework.roo.classpath.PhysicalTypeMetadata;
  11. import org.springframework.roo.classpath.details.FieldMetadata;
  12. import org.springframework.roo.classpath.details.FieldMetadataBuilder;
  13. import org.springframework.roo.classpath.details.MethodMetadata;
  14. import org.springframework.roo.classpath.details.MethodMetadataBuilder;
  15. import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
  16. import org.springframework.roo.classpath.details.annotations.ArrayAttributeValue;
  17. import org.springframework.roo.classpath.details.annotations.ClassAttributeValue;
  18. import org.springframework.roo.classpath.itd.AbstractItdTypeDetailsProvidingMetadataItem;
  19. import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder;
  20. import org.springframework.roo.metadata.MetadataIdentificationUtils;
  21. import org.springframework.roo.model.JavaSymbolName;
  22. import org.springframework.roo.model.JavaType;
  23. import org.springframework.roo.model.JdkJavaType;
  24. import org.springframework.roo.model.Jsr303JavaType;
  25. import org.springframework.roo.model.SpringJavaType;
  26. import org.springframework.roo.model.SpringletsJavaType;
  27. import org.springframework.roo.project.LogicalPath;
  28. /**
  29. * Metadata for {@link RooRepositoryJpaIntegrationTest}.
  30. *
  31. * @author Sergio Clares
  32. * @since 2.0
  33. */
  34. public class RepositoryJpaIntegrationTestMetadata extends
  35. AbstractItdTypeDetailsProvidingMetadataItem {
  36. private static final String PROVIDES_TYPE_STRING = RepositoryJpaIntegrationTestMetadata.class
  37. .getName();
  38. private static final String PROVIDES_TYPE = MetadataIdentificationUtils
  39. .create(PROVIDES_TYPE_STRING);
  40. private static final JavaSymbolName EXPECTED_EXCEPTION_FIELD_NAME = new JavaSymbolName("thrown");
  41. private static final JavaSymbolName REPOSITORY_FIELD_NAME = new JavaSymbolName("repository");
  42. private static final JavaSymbolName DATA_ON_DEMAND_FIELD_NAME = new JavaSymbolName("dod");
  43. private static final JavaSymbolName BEFORE_METHOD_NAME = new JavaSymbolName(
  44. "checkDataOnDemandHasInitializedCorrectly");
  45. private static final JavaSymbolName COUNT_TEST_METHOD_NAME = new JavaSymbolName(
  46. "countShouldReturnExpectedValue");
  47. private static final JavaSymbolName PERSIST_SHOULD_GENERATE_ID_METHOD_NAME = new JavaSymbolName(
  48. "persistShouldGenerateIdValue");
  49. private static final JavaType RULE = new JavaType("org.junit.Rule");
  50. private static final JavaType BEFORE = new JavaType("org.junit.Before");
  51. private static final JavaType TEST = new JavaType("org.junit.Test");
  52. private static final JavaType RUN_WITH = new JavaType("org.junit.runner.RunWith");
  53. private static final JavaType EXPECTED_EXCEPTION = new JavaType(
  54. "org.junit.rules.ExpectedException");
  55. private static final JavaType ASSERT_THAT = new JavaType(
  56. "org.assertj.core.api.Assertions.assertThat");
  57. public static String createIdentifier(final JavaType javaType, final LogicalPath path) {
  58. return PhysicalTypeIdentifierNamingUtils.createIdentifier(PROVIDES_TYPE_STRING, javaType, path);
  59. }
  60. public static JavaType getJavaType(final String metadataIdentificationString) {
  61. return PhysicalTypeIdentifierNamingUtils.getJavaType(PROVIDES_TYPE_STRING,
  62. metadataIdentificationString);
  63. }
  64. public static String getMetadataIdentiferType() {
  65. return PROVIDES_TYPE;
  66. }
  67. public static LogicalPath getPath(final String metadataIdentificationString) {
  68. return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING,
  69. metadataIdentificationString);
  70. }
  71. public static boolean isValid(final String metadataIdentificationString) {
  72. return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING,
  73. metadataIdentificationString);
  74. }
  75. private final RepositoryJpaIntegrationTestAnnotationValues annotationValues;
  76. private final JavaType jpaDetachableRepositoryClass;
  77. private final JavaType entity;
  78. private final JavaSymbolName getRandomIdMethodName;
  79. private final JavaType identifierType;
  80. private final String entityVar;
  81. private final FieldMetadata repositoryField;
  82. private final FieldMetadata dodField;
  83. private final JavaSymbolName identifierAccessorMethodName;
  84. private final String getRandomMethodName;
  85. private final String entityPlural;
  86. private final JavaType defaultReturnType;
  87. private final boolean isReadOnly;
  88. /**
  89. * Constructor
  90. *
  91. * @param identifier
  92. * @param aspectName
  93. * @param governorPhysicalTypeMetadata
  94. * @param annotationValues
  95. * @param jpaDetachableRepositoryClass
  96. * @param identifierType the managed entity identifier type
  97. * @param identifierAccessorMethodName the managed entity identifier
  98. * accessor method name
  99. * @param entityPlural
  100. * @param entity
  101. * @param defaultReturnType the repository default return type for default
  102. * queries
  103. * @param isReadOnly whether the entity is read only
  104. */
  105. public RepositoryJpaIntegrationTestMetadata(final String identifier, final JavaType aspectName,
  106. final PhysicalTypeMetadata governorPhysicalTypeMetadata,
  107. final RepositoryJpaIntegrationTestAnnotationValues annotationValues,
  108. final JavaType jpaDetachableRepositoryClass, final JavaType identifierType,
  109. final JavaSymbolName identifierAccessorMethodName, final String entityPlural,
  110. final JavaType entity, final JavaType defaultReturnType, final boolean isReadOnly) {
  111. super(identifier, aspectName, governorPhysicalTypeMetadata);
  112. Validate.isTrue(isValid(identifier),
  113. "Metadata identification string '%s' does not appear to be a valid", identifier);
  114. Validate.notNull(annotationValues, "Annotation values required");
  115. this.annotationValues = annotationValues;
  116. this.jpaDetachableRepositoryClass = jpaDetachableRepositoryClass;
  117. this.entity = entity;
  118. this.getRandomIdMethodName =
  119. new JavaSymbolName(String.format("getRandom%sId", this.entity.getSimpleTypeName()));
  120. this.getRandomMethodName = String.format("getRandom%s", this.entity.getSimpleTypeName());
  121. this.identifierType = identifierType;
  122. this.entityVar = StringUtils.uncapitalize(this.entity.getSimpleTypeName());
  123. this.identifierAccessorMethodName = identifierAccessorMethodName;
  124. this.entityPlural = entityPlural;
  125. this.defaultReturnType = defaultReturnType;
  126. this.isReadOnly = isReadOnly;
  127. // Add @RunWith(SpringRunner.class)
  128. ensureGovernorIsAnnotated(getRunWithAnnotation());
  129. // Add @DataJpaTest
  130. ensureGovernorIsAnnotated(getDataJpaTestAnnotation());
  131. // Add @Import
  132. ensureGovernorIsAnnotated(getImportAnnotation());
  133. // Add fields
  134. ensureGovernorHasField(getExpectedExceptionField());
  135. this.repositoryField = getRepositoryField().build();
  136. ensureGovernorHasField(getRepositoryField());
  137. this.dodField = getDodField().build();
  138. ensureGovernorHasField(getDodField());
  139. // Add @Before method
  140. ensureGovernorHasMethod(new MethodMetadataBuilder(getBeforeMethod()));
  141. // Add count test method
  142. ensureGovernorHasMethod(new MethodMetadataBuilder(getCountTestMethod()));
  143. // Add find one test method
  144. ensureGovernorHasMethod(new MethodMetadataBuilder(getFindOneTestMethod()));
  145. // Add find all test method
  146. ensureGovernorHasMethod(new MethodMetadataBuilder(getFindAllTestMethod()));
  147. if (!this.isReadOnly) {
  148. // Add persist should generate id method
  149. ensureGovernorHasMethod(new MethodMetadataBuilder(getPersistGenerateIdTestMethod()));
  150. // Add delete should make entity unavailable method
  151. ensureGovernorHasMethod(new MethodMetadataBuilder(
  152. getDeleteShouldMakeEntityUnavailableTestMethod()));
  153. }
  154. // Add find all custom not filtered and not paged test method
  155. ensureGovernorHasMethod(new MethodMetadataBuilder(
  156. getFindAllCustomNotFilteredNotPagedTestMethod()));
  157. // Add find all custom not filtered and paged test method
  158. ensureGovernorHasMethod(new MethodMetadataBuilder(getFindAllCustomNotFilteredPagedTestMethod()));
  159. // Add getRandomId method
  160. ensureGovernorHasMethod(new MethodMetadataBuilder(getRandomIdMethod()));
  161. itdTypeDetails = builder.build();
  162. }
  163. /**
  164. * Builds a method annotated with `@Before` which checks if data-on-demand
  165. * field has initialized correctly.
  166. *
  167. * @return {@link MethodMetadata}
  168. */
  169. private MethodMetadata getBeforeMethod() {
  170. MethodMetadata method = getGovernorMethod(BEFORE_METHOD_NAME);
  171. if (method != null) {
  172. return method;
  173. }
  174. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  175. // assertThat(dod.getRandomPet())
  176. bodyBuilder.appendFormalLine("%s(%s().%s())", getNameOfJavaType(ASSERT_THAT, true),
  177. getAccessorMethod(this.dodField).getMethodName(), this.getRandomMethodName);
  178. // .as("Check data on demand for 'Pet' initializes correctly by getting a random Pet")
  179. bodyBuilder.indent();
  180. bodyBuilder.appendFormalLine(
  181. ".as(\"Check data on demand for '%1$s' initializes correctly by getting a random %1$s\")",
  182. getNameOfJavaType(this.entity));
  183. // .isNotNull();
  184. bodyBuilder.appendFormalLine(".isNotNull();");
  185. bodyBuilder.reset();
  186. MethodMetadataBuilder methodBuilder =
  187. new MethodMetadataBuilder(getId(), Modifier.PUBLIC, BEFORE_METHOD_NAME,
  188. JavaType.VOID_PRIMITIVE, bodyBuilder);
  189. // Add @Before
  190. methodBuilder.addAnnotation(new AnnotationMetadataBuilder(BEFORE));
  191. return methodBuilder.build();
  192. }
  193. /**
  194. * Builds a method to test count method.
  195. *
  196. * @return {@link MethodMetadata}
  197. */
  198. private MethodMetadata getCountTestMethod() {
  199. MethodMetadata method = getGovernorMethod(COUNT_TEST_METHOD_NAME);
  200. if (method != null) {
  201. return method;
  202. }
  203. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  204. // Verify
  205. bodyBuilder.appendFormalLine("// Verify");
  206. // assertThat(repository.count()).as("Check there are available 'Pet' entries").isGreaterThan(0);
  207. bodyBuilder.appendFormalLine(
  208. "%s(%s().count()).as(\"Check there are available '%s' entries\").isGreaterThan(0);",
  209. getNameOfJavaType(ASSERT_THAT), getAccessorMethod(this.repositoryField).getMethodName(),
  210. getNameOfJavaType(this.entity));
  211. MethodMetadataBuilder methodBuilder =
  212. new MethodMetadataBuilder(getId(), Modifier.PUBLIC, COUNT_TEST_METHOD_NAME,
  213. JavaType.VOID_PRIMITIVE, bodyBuilder);
  214. // Add @Test
  215. methodBuilder.addAnnotation(new AnnotationMetadataBuilder(TEST));
  216. return methodBuilder.build();
  217. }
  218. /**
  219. * Builds and returns `@DataJpaTest` annotation
  220. *
  221. * @return {@link AnnotationMetadataBuilder}
  222. */
  223. private AnnotationMetadataBuilder getDataJpaTestAnnotation() {
  224. AnnotationMetadataBuilder annotationBuilder =
  225. new AnnotationMetadataBuilder(SpringJavaType.DATA_JPA_TEST);
  226. return annotationBuilder;
  227. }
  228. /**
  229. * Builds a method to test the deletion of entity records.
  230. *
  231. * @return {@link MethodMetadata}
  232. */
  233. private MethodMetadata getDeleteShouldMakeEntityUnavailableTestMethod() {
  234. JavaSymbolName methodName =
  235. new JavaSymbolName(String.format("deleteShouldMake%sUnavailable",
  236. getNameOfJavaType(this.entity)));
  237. // Check if method exists on governor
  238. MethodMetadata method = getGovernorMethod(methodName);
  239. if (method != null) {
  240. return method;
  241. }
  242. // Build method body
  243. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  244. // Setup
  245. bodyBuilder.appendFormalLine("// Setup");
  246. // Long id = getRandomPetId();
  247. bodyBuilder.appendFormalLine("%s id = %s();", getNameOfJavaType(this.identifierType),
  248. this.getRandomIdMethodName);
  249. // Pet pet = repository.findOne(id);
  250. bodyBuilder.appendFormalLine("%s %s = %s().findOne(id);", getNameOfJavaType(this.entity),
  251. this.entityVar, getAccessorMethod(this.repositoryField).getMethodName());
  252. // Exercise
  253. bodyBuilder.newLine();
  254. bodyBuilder.appendFormalLine("// Exercise");
  255. // repository.delete(pet);
  256. bodyBuilder.appendFormalLine("%s().delete(%s);", getAccessorMethod(this.repositoryField)
  257. .getMethodName(), this.entityVar);
  258. // Verify
  259. bodyBuilder.newLine();
  260. bodyBuilder.appendFormalLine("// Verify");
  261. // assertThat(repository.findOne(id))
  262. bodyBuilder.appendFormalLine("%s(%s().findOne(id))", getNameOfJavaType(ASSERT_THAT),
  263. getAccessorMethod(this.repositoryField).getMethodName());
  264. // .as("Check the deleted 'Pet' %s is no longer available with 'findOne'", pet).isNull();
  265. bodyBuilder.appendFormalLine(
  266. ".as(\"Check the deleted '%s' %s is no longer available with 'findOne'\", %s).isNull();",
  267. getNameOfJavaType(this.entity), "%s", this.entityVar);
  268. MethodMetadataBuilder methodBuilder =
  269. new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
  270. bodyBuilder);
  271. // Add @Test
  272. methodBuilder.addAnnotation(new AnnotationMetadataBuilder(TEST));
  273. return methodBuilder.build();
  274. }
  275. /**
  276. * Builds and returns a `private` data-on-demand field.
  277. *
  278. * @return {@link FieldMetadataBuilder}
  279. */
  280. private FieldMetadataBuilder getDodField() {
  281. FieldMetadataBuilder fieldBuilder =
  282. new FieldMetadataBuilder(this.getId(), Modifier.PRIVATE, DATA_ON_DEMAND_FIELD_NAME,
  283. this.annotationValues.getDodClass(), null);
  284. // Add @Autowired
  285. fieldBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.AUTOWIRED));
  286. return fieldBuilder;
  287. }
  288. /**
  289. * Builds and returns a <code>public</code> ExpectedException field.
  290. *
  291. * @return {@link FieldMetadataBuilder}
  292. */
  293. private FieldMetadataBuilder getExpectedExceptionField() {
  294. FieldMetadataBuilder fieldBuilder =
  295. new FieldMetadataBuilder(this.getId(), Modifier.PUBLIC, EXPECTED_EXCEPTION_FIELD_NAME,
  296. EXPECTED_EXCEPTION, String.format("%s.none()", getNameOfJavaType(EXPECTED_EXCEPTION)));
  297. // Add @Rule
  298. fieldBuilder.addAnnotation(new AnnotationMetadataBuilder(RULE));
  299. return fieldBuilder;
  300. }
  301. /**
  302. * Builds a method to test the find all custom method not filtered and paged.
  303. *
  304. * @return {@link MethodMetadata}
  305. */
  306. private MethodMetadata getFindAllCustomNotFilteredPagedTestMethod() {
  307. JavaSymbolName methodName =
  308. new JavaSymbolName(String.format("findAllCustomNotFilteredPagedShouldReturnA%sPage",
  309. this.entityPlural));
  310. // Check if method exists on governor
  311. MethodMetadata method = getGovernorMethod(methodName);
  312. if (method != null) {
  313. return method;
  314. }
  315. // Build method body
  316. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  317. // Exercise
  318. bodyBuilder.appendFormalLine("// Exercise");
  319. // Page<Pet> all = repository.findAll((GlobalSearch) null, new PageRequest(0, 3));
  320. bodyBuilder.appendFormalLine("%s<%s> all = %s().findAll((%s) null, new %s(0, 3));",
  321. getNameOfJavaType(SpringJavaType.PAGE), getNameOfJavaType(this.defaultReturnType),
  322. getAccessorMethod(this.repositoryField).getMethodName(),
  323. getNameOfJavaType(SpringletsJavaType.SPRINGLETS_GLOBAL_SEARCH),
  324. getNameOfJavaType(SpringJavaType.PAGE_REQUEST));
  325. // Verify
  326. bodyBuilder.newLine();
  327. bodyBuilder.appendFormalLine("// Verify");
  328. // assertThat(all.getNumberOfElements())
  329. bodyBuilder.appendFormalLine("%s(all.getNumberOfElements())", getNameOfJavaType(ASSERT_THAT));
  330. // .as("Check result number is not greater than the page size").isLessThanOrEqualTo(3);
  331. bodyBuilder.indent();
  332. bodyBuilder
  333. .appendFormalLine(".as(\"Check result number is not greater than the page size\").isLessThanOrEqualTo(3);");
  334. bodyBuilder.indentRemove();
  335. MethodMetadataBuilder methodBuilder =
  336. new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
  337. bodyBuilder);
  338. // Add @Test
  339. methodBuilder.addAnnotation(new AnnotationMetadataBuilder(TEST));
  340. return methodBuilder.build();
  341. }
  342. /**
  343. * Builds a method to test the find all custom method not filtered and not paged.
  344. *
  345. * @return {@link MethodMetadata}
  346. */
  347. private MethodMetadata getFindAllCustomNotFilteredNotPagedTestMethod() {
  348. JavaSymbolName methodName =
  349. new JavaSymbolName(String.format("findAllCustomNotFilteredNotPagedShouldReturnAll%s",
  350. this.entityPlural));
  351. // Check if method exists on governor
  352. MethodMetadata method = getGovernorMethod(methodName);
  353. if (method != null) {
  354. return method;
  355. }
  356. // Build method body
  357. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  358. // Exercise
  359. bodyBuilder.appendFormalLine("// Exercise");
  360. // Page<Pet> all = repository.findAll((GlobalSearch) null, new PageRequest(0, dod.getSize()));
  361. bodyBuilder.appendFormalLine(
  362. "%s<%s> all = %s().findAll((%s) null, new %s(0, %s().getSize()));",
  363. getNameOfJavaType(SpringJavaType.PAGE), getNameOfJavaType(this.defaultReturnType),
  364. getAccessorMethod(this.repositoryField).getMethodName(),
  365. getNameOfJavaType(SpringletsJavaType.SPRINGLETS_GLOBAL_SEARCH),
  366. getNameOfJavaType(SpringJavaType.PAGE_REQUEST), getAccessorMethod(this.dodField)
  367. .getMethodName());
  368. // Verify
  369. bodyBuilder.newLine();
  370. bodyBuilder.appendFormalLine("// Verify");
  371. // assertThat(all.getNumberOfElements())
  372. bodyBuilder.appendFormalLine("%s(all.getNumberOfElements())", getNameOfJavaType(ASSERT_THAT));
  373. // .as("Check 'findAll' with null 'GlobalSearch' and no pagination returns all entries")
  374. bodyBuilder.indent();
  375. bodyBuilder.appendFormalLine(
  376. ".as(\"Check 'findAll' with null '%s' and no pagination returns all entries\")",
  377. getNameOfJavaType(SpringletsJavaType.SPRINGLETS_GLOBAL_SEARCH));
  378. // .isEqualTo(dod.getSize());
  379. bodyBuilder.appendFormalLine(".isEqualTo(%s().getSize());", getAccessorMethod(this.dodField)
  380. .getMethodName());
  381. bodyBuilder.reset();
  382. MethodMetadataBuilder methodBuilder =
  383. new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
  384. bodyBuilder);
  385. // Add @Test
  386. methodBuilder.addAnnotation(new AnnotationMetadataBuilder(TEST));
  387. return methodBuilder.build();
  388. }
  389. /**
  390. * Builds a method to test all one method.
  391. *
  392. * @return {@link MethodMetadata}
  393. */
  394. private MethodMetadata getFindAllTestMethod() {
  395. // Set method name
  396. final JavaSymbolName methodName =
  397. new JavaSymbolName(String.format("findAllShouldReturnAll%s", this.entityPlural));
  398. // Check if method exists on governor
  399. MethodMetadata method = getGovernorMethod(methodName);
  400. if (method != null) {
  401. return method;
  402. }
  403. // Build method body
  404. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  405. // Setup
  406. bodyBuilder.appendFormalLine("// Setup");
  407. // assertThat(repository.count())
  408. bodyBuilder.appendFormalLine("%s(%s().count())", getNameOfJavaType(ASSERT_THAT),
  409. getAccessorMethod(this.repositoryField).getMethodName());
  410. // .as("Check the number of entries is not too big (250 entries). "
  411. bodyBuilder.indent();
  412. bodyBuilder
  413. .appendFormalLine(".as(\"Check the number of entries is not too big (250 entries). \"");
  414. // + "If it is, please review the tests so it doesn't take too long to run them")
  415. bodyBuilder.indent();
  416. bodyBuilder
  417. .appendFormalLine("+ \"If it is, please review the tests so it doesn't take too long to run them\")");
  418. bodyBuilder.indentRemove();
  419. // .isLessThan(250);
  420. bodyBuilder.appendFormalLine(".isLessThan(250);");
  421. bodyBuilder.indentRemove();
  422. // Exercise
  423. bodyBuilder.newLine();
  424. bodyBuilder.appendFormalLine("// Exercise");
  425. // List<Pet> result = repository.findAll();
  426. bodyBuilder.appendFormalLine("%s<%s> result = %s().findAll();",
  427. getNameOfJavaType(JavaType.LIST), getNameOfJavaType(this.entity),
  428. getAccessorMethod(this.repositoryField).getMethodName());
  429. // Verify
  430. bodyBuilder.newLine();
  431. bodyBuilder.appendFormalLine("// Verify");
  432. // assertThat(result).as("Check 'findAll' returns a not null list of entries").isNotNull();
  433. bodyBuilder.appendFormalLine(
  434. "%s(result).as(\"Check 'findAll' returns a not null list of entries\").isNotNull();",
  435. getNameOfJavaType(ASSERT_THAT));
  436. // assertThat(result.size()).as("Check 'findAll' returns a not empty list of entries")
  437. bodyBuilder.appendFormalLine(
  438. "%s(result.size()).as(\"Check 'findAll' returns a not empty list of entries\")",
  439. getNameOfJavaType(ASSERT_THAT));
  440. // .isGreaterThan(0);
  441. bodyBuilder.indent();
  442. bodyBuilder.appendFormalLine(".isGreaterThan(0);");
  443. bodyBuilder.reset();
  444. MethodMetadataBuilder methodBuilder =
  445. new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
  446. bodyBuilder);
  447. // Add @Test
  448. methodBuilder.addAnnotation(new AnnotationMetadataBuilder(TEST));
  449. return methodBuilder.build();
  450. }
  451. /**
  452. * Builds a method to test find one method.
  453. *
  454. * @return {@link MethodMetadata}
  455. */
  456. private MethodMetadata getFindOneTestMethod() {
  457. final JavaSymbolName methodName =
  458. new JavaSymbolName(String.format("findOneShouldReturnExisting%s",
  459. this.entity.getSimpleTypeName()));
  460. MethodMetadata method = getGovernorMethod(methodName);
  461. if (method != null) {
  462. return method;
  463. }
  464. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  465. // Setup
  466. bodyBuilder.appendFormalLine("// Setup");
  467. // Long id = getRandomPetId();
  468. bodyBuilder.appendFormalLine("%s id = %s();", getNameOfJavaType(this.identifierType),
  469. this.getRandomIdMethodName);
  470. // Exercise
  471. bodyBuilder.newLine();
  472. bodyBuilder.appendFormalLine("// Exercise");
  473. // Pet pet = repository.findOne(id);
  474. bodyBuilder.appendFormalLine("%s %s = %s().findOne(id);", getNameOfJavaType(this.entity),
  475. entityVar, getAccessorMethod(this.repositoryField).getMethodName());
  476. // Verify
  477. bodyBuilder.newLine();
  478. bodyBuilder.appendFormalLine("// Verify");
  479. // assertThat(pet).as("Check that findOne illegally returned null for id %s", id).isNotNull();
  480. bodyBuilder.appendFormalLine(
  481. "%s(%s).as(\"Check that findOne illegally returned null for id %s\", id).isNotNull();",
  482. getNameOfJavaType(ASSERT_THAT), this.entityVar, "%s");
  483. // assertThat(id).as("Check the identifier of the found 'Pet' is the same used to look for it")
  484. bodyBuilder.appendFormalLine(
  485. "%s(id).as(\"Check the identifier of the found '%s' is the same used to look for it\")",
  486. getNameOfJavaType(ASSERT_THAT), getNameOfJavaType(this.entity));
  487. // .isEqualTo(pet.getId());
  488. bodyBuilder.indent();
  489. bodyBuilder.appendFormalLine(".isEqualTo(%s.%s());", this.entityVar,
  490. this.identifierAccessorMethodName);
  491. bodyBuilder.reset();
  492. MethodMetadataBuilder methodBuilder =
  493. new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
  494. bodyBuilder);
  495. // Add @Test
  496. methodBuilder.addAnnotation(new AnnotationMetadataBuilder(TEST));
  497. return methodBuilder.build();
  498. }
  499. /**
  500. * Builds and returns `@Import` annotation
  501. *
  502. * @return {@link AnnotationMetadataBuilder}
  503. */
  504. private AnnotationMetadataBuilder getImportAnnotation() {
  505. AnnotationMetadataBuilder annotationBuilder =
  506. new AnnotationMetadataBuilder(SpringJavaType.ANNOTATION_IMPORT);
  507. // Create List of ClassAttributeValue
  508. List<ClassAttributeValue> typesToImport = new ArrayList<ClassAttributeValue>();
  509. typesToImport.add(new ClassAttributeValue(new JavaSymbolName("value"), this.annotationValues
  510. .getDodConfigurationClass()));
  511. typesToImport.add(new ClassAttributeValue(new JavaSymbolName("value"),
  512. this.jpaDetachableRepositoryClass));
  513. // Convert List to ArrayAttributeValue
  514. ArrayAttributeValue<ClassAttributeValue> importAttr =
  515. new ArrayAttributeValue<ClassAttributeValue>(new JavaSymbolName("value"), typesToImport);
  516. // Add annotation attribute
  517. annotationBuilder.addAttribute(importAttr);
  518. return annotationBuilder;
  519. }
  520. /**
  521. * Builds a method to test the generation of id when persisting entities.
  522. *
  523. * @return {@link MethodMetadata}
  524. */
  525. private MethodMetadata getPersistGenerateIdTestMethod() {
  526. // Check if method exists on governor
  527. MethodMetadata method = getGovernorMethod(PERSIST_SHOULD_GENERATE_ID_METHOD_NAME);
  528. if (method != null) {
  529. return method;
  530. }
  531. // Build method body
  532. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  533. // Setup
  534. bodyBuilder.appendFormalLine("// Setup");
  535. // Exercise
  536. bodyBuilder.appendFormalLine("// Exercise");
  537. // Pet pet = dod.getNewRandomTransientPet();
  538. bodyBuilder.appendFormalLine("%1$s %2$s = %3$s().getNewRandomTransient%1$s();",
  539. getNameOfJavaType(this.entity), this.entityVar, getAccessorMethod(this.dodField)
  540. .getMethodName());
  541. // Verify
  542. bodyBuilder.newLine();
  543. bodyBuilder.appendFormalLine("// Verify");
  544. // assertThat(pet).as("Check the Data on demand generated a new non null 'Pet'").isNotNull();
  545. bodyBuilder.appendFormalLine(
  546. "%s(%s).as(\"Check the Data on demand generated a new non null '%s'\").isNotNull();",
  547. getNameOfJavaType(ASSERT_THAT), this.entityVar, getNameOfJavaType(this.entity));
  548. // assertThat(pet.getId()).as("Check the Data on demand generated a new 'Pet' whose id is null")
  549. bodyBuilder.appendFormalLine(
  550. "%s(%s.%s()).as(\"Check the Data on demand generated a new '%s' whose id is null\")",
  551. getNameOfJavaType(ASSERT_THAT), this.entityVar, this.identifierAccessorMethodName,
  552. getNameOfJavaType(this.entity));
  553. // .isNull();
  554. bodyBuilder.indent();
  555. bodyBuilder.appendFormalLine(".isNull();");
  556. bodyBuilder.indentRemove();
  557. // try {
  558. bodyBuilder.appendFormalLine("try {");
  559. // pet = repository.saveAndFlush(pet);
  560. bodyBuilder.indent();
  561. bodyBuilder.appendFormalLine("%1$s = %2$s().saveAndFlush(%1$s);", this.entityVar,
  562. getAccessorMethod(this.repositoryField).getMethodName());
  563. // } catch (final ConstraintViolationException e) {
  564. bodyBuilder.indentRemove();
  565. bodyBuilder.appendFormalLine("} catch (final %s e) {",
  566. getNameOfJavaType(Jsr303JavaType.CONSTRAINT_VIOLATION_EXCEPTION));
  567. // final StringBuilder msg = new StringBuilder();
  568. bodyBuilder.indent();
  569. bodyBuilder.appendFormalLine("final %1$s msg = new %1$s();",
  570. getNameOfJavaType(JdkJavaType.STRING_BUILDER));
  571. // for (Iterator<ConstraintViolation<?>> iter = e.getConstraintViolations().iterator(); iter
  572. bodyBuilder.appendFormalLine(
  573. "for (%s<%s<?>> iter = e.getConstraintViolations().iterator(); iter",
  574. getNameOfJavaType(JdkJavaType.ITERATOR),
  575. getNameOfJavaType(Jsr303JavaType.CONSTRAINT_VIOLATION));
  576. // .hasNext();) {
  577. bodyBuilder.indent();
  578. bodyBuilder.appendFormalLine(".hasNext();) {");
  579. // final ConstraintViolation<?> cv = iter.next();
  580. bodyBuilder.appendFormalLine("final %s<?> cv = iter.next();",
  581. getNameOfJavaType(Jsr303JavaType.CONSTRAINT_VIOLATION));
  582. // msg.append("[").append(cv.getRootBean().getClass().getName()).append(".")
  583. bodyBuilder
  584. .appendFormalLine("msg.append(\"[\").append(cv.getRootBean().getClass().getName()).append(\".\")");
  585. // .append(cv.getPropertyPath()).append(": ").append(cv.getMessage())
  586. bodyBuilder.indent();
  587. bodyBuilder
  588. .appendFormalLine(".append(cv.getPropertyPath()).append(\": \").append(cv.getMessage())");
  589. // .append(" (invalid value = ").append(cv.getInvalidValue()).append(")").append("]");
  590. bodyBuilder
  591. .appendFormalLine(".append(\" (invalid value = \").append(cv.getInvalidValue()).append(\")\").append(\"]\");");
  592. // }
  593. bodyBuilder.indentRemove();
  594. bodyBuilder.indentRemove();
  595. bodyBuilder.appendFormalLine("}");
  596. // throw new IllegalStateException(msg.toString(), e);
  597. bodyBuilder.appendFormalLine("throw new %s(msg.toString(), e);",
  598. getNameOfJavaType(JdkJavaType.ILLEGAL_STATE_EXCEPTION));
  599. bodyBuilder.indentRemove();
  600. // }
  601. bodyBuilder.appendFormalLine("}");
  602. // assertThat(pet.getId()).as("Check a 'Pet' (%s) id is not null after been persisted", pet)
  603. bodyBuilder
  604. .appendFormalLine(
  605. "%1$s(%2$s.%3$s()).as(\"Check a '%4$s' (%5$s) id is not null after been persisted\", %2$s)",
  606. getNameOfJavaType(ASSERT_THAT), this.entityVar, this.identifierAccessorMethodName,
  607. getNameOfJavaType(this.entity), "%s");
  608. // .isNotNull();
  609. bodyBuilder.indent();
  610. bodyBuilder.appendFormalLine(".isNotNull();");
  611. bodyBuilder.reset();
  612. MethodMetadataBuilder methodBuilder =
  613. new MethodMetadataBuilder(getId(), Modifier.PUBLIC, PERSIST_SHOULD_GENERATE_ID_METHOD_NAME,
  614. JavaType.VOID_PRIMITIVE, bodyBuilder);
  615. // Add @Test
  616. methodBuilder.addAnnotation(new AnnotationMetadataBuilder(TEST));
  617. return methodBuilder.build();
  618. }
  619. /**
  620. * Builds a method to obtain the id value of a random generated entity
  621. * instance generated with data-on-demand.
  622. *
  623. * @return {@link MethodMetadata}
  624. */
  625. private MethodMetadata getRandomIdMethod() {
  626. MethodMetadata method = getGovernorMethod(this.getRandomIdMethodName);
  627. if (method != null) {
  628. return method;
  629. }
  630. InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  631. // Pet pet = dod.getRandomPet();
  632. bodyBuilder.appendFormalLine("%s %s = %s().%s();", getNameOfJavaType(this.entity),
  633. this.entityVar, getAccessorMethod(this.dodField).getMethodName(), this.getRandomMethodName);
  634. // Long id = pet.getId();
  635. bodyBuilder.appendFormalLine("%s id = %s.%s();", getNameOfJavaType(this.identifierType),
  636. this.entityVar, this.identifierAccessorMethodName);
  637. // assertThat(id).as("Check the Data on demand generated a 'Pet' with an identifier").isNotNull();
  638. bodyBuilder.appendFormalLine(
  639. "%s(id).as(\"Check the Data on demand generated a '%s' with an identifier\").isNotNull();",
  640. getNameOfJavaType(ASSERT_THAT), getNameOfJavaType(this.entity));
  641. // return id;
  642. bodyBuilder.appendFormalLine("return id;");
  643. MethodMetadataBuilder methodBuilder =
  644. new MethodMetadataBuilder(getId(), Modifier.PRIVATE, this.getRandomIdMethodName,
  645. this.identifierType, bodyBuilder);
  646. return methodBuilder.build();
  647. }
  648. /**
  649. * Builds and returns a `private` Roo repository field.
  650. *
  651. * @return {@link FieldMetadataBuilder}
  652. */
  653. private FieldMetadataBuilder getRepositoryField() {
  654. FieldMetadataBuilder fieldBuilder =
  655. new FieldMetadataBuilder(this.getId(), Modifier.PRIVATE, REPOSITORY_FIELD_NAME,
  656. this.annotationValues.getTargetClass(), null);
  657. // Add @Autowired
  658. fieldBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.AUTOWIRED));
  659. return fieldBuilder;
  660. }
  661. /**
  662. * Builds and returns `@RunWith` annotation
  663. *
  664. * @return {@link AnnotationMetadataBuilder}
  665. */
  666. private AnnotationMetadataBuilder getRunWithAnnotation() {
  667. AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder(RUN_WITH);
  668. annotationBuilder.addClassAttribute("value", SpringJavaType.SPRING_RUNNER);
  669. return annotationBuilder;
  670. }
  671. @Override
  672. public String toString() {
  673. final ToStringBuilder builder = new ToStringBuilder(this);
  674. builder.append("identifier", getId());
  675. builder.append("valid", valid);
  676. builder.append("aspectName", aspectName);
  677. builder.append("destinationType", destination);
  678. builder.append("governor", governorPhysicalTypeMetadata.getId());
  679. builder.append("itdTypeDetails", itdTypeDetails);
  680. return builder.toString();
  681. }
  682. }