package ca.intelliware.ihtsdo.mlds.service; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; import java.util.Random; import javax.annotation.Resource; import javax.persistence.EntityManager; import javax.transaction.Transactional; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import ca.intelliware.ihtsdo.mlds.domain.Affiliate; import ca.intelliware.ihtsdo.mlds.domain.AffiliateDetails; import ca.intelliware.ihtsdo.mlds.domain.AffiliateType; import ca.intelliware.ihtsdo.mlds.domain.Application; import ca.intelliware.ihtsdo.mlds.domain.ApprovalState; import ca.intelliware.ihtsdo.mlds.domain.CommercialUsage; import ca.intelliware.ihtsdo.mlds.domain.CommercialUsageCountry; import ca.intelliware.ihtsdo.mlds.domain.CommercialUsageEntry; import ca.intelliware.ihtsdo.mlds.domain.ExtensionApplication; import ca.intelliware.ihtsdo.mlds.domain.MailingAddress; import ca.intelliware.ihtsdo.mlds.domain.Member; import ca.intelliware.ihtsdo.mlds.domain.PrimaryApplication; import ca.intelliware.ihtsdo.mlds.domain.StandingState; import ca.intelliware.ihtsdo.mlds.domain.User; import ca.intelliware.ihtsdo.mlds.repository.AffiliateDetailsRepository; import ca.intelliware.ihtsdo.mlds.repository.AffiliateRepository; import ca.intelliware.ihtsdo.mlds.repository.ApplicationRepository; import ca.intelliware.ihtsdo.mlds.repository.CommercialUsageCountryRepository; import ca.intelliware.ihtsdo.mlds.repository.CommercialUsageEntryRepository; import ca.intelliware.ihtsdo.mlds.repository.CommercialUsageRepository; import ca.intelliware.ihtsdo.mlds.repository.MemberRepository; import ca.intelliware.ihtsdo.mlds.repository.UserRepository; import ca.intelliware.ihtsdo.mlds.security.ihtsdo.SecurityContextSetup; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = ca.intelliware.ihtsdo.mlds.Application.class) @WebAppConfiguration @ActiveProfiles("dev") @Transactional public class AffiliateDeleterTest { @Resource EntityManager entityManager; @Resource AffiliateRepository affiliateRepository; @Resource AffiliateDetailsRepository affiliateDetailsRepository; @Resource ApplicationRepository applicationRepository; @Resource UserRepository userRepository; @Resource CommercialUsageRepository commercialUsageRepository; @Resource CommercialUsageCountryRepository commercialUsageCountryRepository; @Resource CommercialUsageEntryRepository commercialUsageEntryRepository; @Resource MemberRepository memberRepository; SecurityContextSetup securityContextSetup = new SecurityContextSetup(); @Resource AffiliateDeleter affiliateDeleter; Random random = new Random(); private String uniqueKey; private Member sweden; private Member ihtsdo; @Before public void setUp() { ihtsdo = memberRepository.findOneByKey(Member.KEY_IHTSDO); sweden = memberRepository.findOneByKey("SE"); uniqueKey = ""+System.currentTimeMillis(); securityContextSetup.asAdmin(); } @Test public void deleteAffiliateWithAllData() throws Exception { securityContextSetup.asSwedenStaff(); String userEmail = "test"+uniqueKey+"@email.com"; User user = withUser(userEmail); Affiliate affiliate = withAffiliateUser(StandingState.APPLYING, ihtsdo, userEmail); AffiliateDetails affiliateDetails = affiliate.getAffiliateDetails(); Application primaryApplication = withPrimaryApplication(affiliate, ihtsdo, ApprovalState.APPROVED); AffiliateDetails affiliatePrimaryDetails = primaryApplication.getAffiliateDetails(); Application extensionApplication = withExtensionApplication(affiliate, sweden, ApprovalState.APPROVED); AffiliateDetails affiliateExtensionDetails = extensionApplication.getAffiliateDetails(); CommercialUsage commercialUsage = withCommercialUsage(affiliate); CommercialUsageCountry commercialUsageCountry = commercialUsage.getCountries().iterator().next(); CommercialUsageEntry commercialUsageEntry = commercialUsage.getEntries().iterator().next(); // Confirm unique affiliate details assertThat(affiliateDetails.getAffiliateDetailsId(), not(equalTo(affiliatePrimaryDetails.getAffiliateDetailsId()))); assertThat(affiliateDetails.getAffiliateDetailsId(), not(equalTo(affiliateExtensionDetails.getAffiliateDetailsId()))); assertThat(affiliatePrimaryDetails.getAffiliateDetailsId(), not(equalTo(affiliateExtensionDetails.getAffiliateDetailsId()))); // Confirm data model accessible from JPA assertThat(affiliateRepository.findOne(affiliate.getAffiliateId()), notNullValue(Affiliate.class)); assertThat(applicationRepository.findOne(primaryApplication.getApplicationId()), notNullValue(Application.class)); assertThat(applicationRepository.findOne(extensionApplication.getApplicationId()), notNullValue(Application.class)); assertThat(userRepository.findByLoginIgnoreCase(userEmail), notNullValue(User.class)); assertThat(commercialUsageRepository.findOne(commercialUsage.getCommercialUsageId()), notNullValue(CommercialUsage.class)); assertThat(affiliateDetailsRepository.findOne(affiliateDetails.getAffiliateDetailsId()), notNullValue(AffiliateDetails.class)); assertThat(affiliateDetailsRepository.findOne(affiliatePrimaryDetails.getAffiliateDetailsId()), notNullValue(AffiliateDetails.class)); assertThat(affiliateDetailsRepository.findOne(affiliateExtensionDetails.getAffiliateDetailsId()), notNullValue(AffiliateDetails.class)); assertThat(commercialUsageCountryRepository.findOne(commercialUsageCountry.getCommercialUsageCountId()), notNullValue(CommercialUsageCountry.class)); assertThat(commercialUsageEntryRepository.findOne(commercialUsageEntry.getCommercialUsageEntryId()), notNullValue(CommercialUsageEntry.class)); assertThat(applicationRepository.findByUsernameIgnoreCase(userEmail).size(), is(2)); // Test affiliateDeleter.deleteAffiliate(affiliate); // JPA should no longer match entities assertThat(affiliateRepository.findOne(affiliate.getAffiliateId()), nullValue(Affiliate.class)); assertThat(applicationRepository.findOne(primaryApplication.getApplicationId()), nullValue(Application.class)); assertThat(applicationRepository.findOne(extensionApplication.getApplicationId()), nullValue(Application.class)); assertThat(userRepository.findByLoginIgnoreCase(userEmail), nullValue(User.class)); assertThat(commercialUsageRepository.findOne(commercialUsage.getCommercialUsageId()), nullValue(CommercialUsage.class)); assertThat(affiliateDetailsRepository.findOne(affiliateDetails.getAffiliateDetailsId()), nullValue(AffiliateDetails.class)); assertThat(affiliateDetailsRepository.findOne(affiliatePrimaryDetails.getAffiliateDetailsId()), nullValue(AffiliateDetails.class)); assertThat(affiliateDetailsRepository.findOne(affiliateExtensionDetails.getAffiliateDetailsId()), nullValue(AffiliateDetails.class)); assertThat(commercialUsageCountryRepository.findOne(commercialUsageCountry.getCommercialUsageCountId()), nullValue(CommercialUsageCountry.class)); assertThat(commercialUsageEntryRepository.findOne(commercialUsageEntry.getCommercialUsageEntryId()), nullValue(CommercialUsageEntry.class)); // JPA should no longer find through custom repository assertThat(applicationRepository.findByUsernameIgnoreCase(userEmail).size(), is(0)); // Records should still be present in the database assertThat(matchingNativeRecords("SELECT affiliate_id FROM affiliate WHERE affiliate_id="+affiliate.getAffiliateId()), is(1)); assertThat(matchingNativeRecords("SELECT application_id FROM application WHERE application_id="+primaryApplication.getApplicationId()), is(1)); assertThat(matchingNativeRecords("SELECT application_id FROM application WHERE application_id="+extensionApplication.getApplicationId()), is(1)); assertThat(matchingNativeRecords("SELECT user_id FROM T_USER WHERE user_id="+user.getUserId()), is(1)); assertThat(matchingNativeRecords("SELECT commercial_usage_id FROM commercial_usage WHERE commercial_usage_id="+commercialUsage.getCommercialUsageId()), is(1)); assertThat(matchingNativeRecords("SELECT affiliate_details_id FROM affiliate_details WHERE affiliate_details_id="+affiliateDetails.getAffiliateDetailsId()), is(1)); assertThat(matchingNativeRecords("SELECT affiliate_details_id FROM affiliate_details WHERE affiliate_details_id="+affiliatePrimaryDetails.getAffiliateDetailsId()), is(1)); assertThat(matchingNativeRecords("SELECT affiliate_details_id FROM affiliate_details WHERE affiliate_details_id="+affiliateExtensionDetails.getAffiliateDetailsId()), is(1)); assertThat(matchingNativeRecords("SELECT commercial_usage_count_id FROM commercial_usage_count WHERE commercial_usage_count_id="+commercialUsageCountry.getCommercialUsageCountId()), is(1)); assertThat(matchingNativeRecords("SELECT commercial_usage_entry_id FROM commercial_usage_entry WHERE commercial_usage_entry_id="+commercialUsageEntry.getCommercialUsageEntryId()), is(1)); } @Test public void deleteAffiliateWithMinimalData() throws Exception { securityContextSetup.asSwedenStaff(); String userEmail = "test"+uniqueKey+"@email.com"; Affiliate affiliate = withAffiliateUser(StandingState.APPLYING, ihtsdo, userEmail); assertThat(affiliateRepository.findOne(affiliate.getAffiliateId()), notNullValue(Affiliate.class)); affiliateDeleter.deleteAffiliate(affiliate); // JPA should no longer match entities assertThat(affiliateRepository.findOne(affiliate.getAffiliateId()), nullValue(Affiliate.class)); // Records should still be present in the database assertThat(matchingNativeRecords("SELECT affiliate_id FROM affiliate WHERE affiliate_id="+affiliate.getAffiliateId()), is(1)); } @Test public void deleteAffiliateWithSharedAffiliateDetails() throws Exception { securityContextSetup.asSwedenStaff(); String userEmail = "test"+uniqueKey+"@email.com"; User user = withUser(userEmail); Affiliate affiliate = withAffiliateUser(StandingState.APPLYING, ihtsdo, userEmail); AffiliateDetails affiliateSharedDetails = affiliate.getAffiliateDetails(); Application primaryApplication = withPrimaryApplication(affiliate, ihtsdo, ApprovalState.APPROVED); primaryApplication.setAffiliateDetails(affiliate.getAffiliateDetails()); applicationRepository.save(primaryApplication); Application extensionApplication = withExtensionApplication(affiliate, sweden, ApprovalState.APPROVED); AffiliateDetails affiliateExtensionDetails = extensionApplication.getAffiliateDetails(); CommercialUsage commercialUsage = withCommercialUsage(affiliate); // Confirm data model accessible from JPA assertThat(affiliateRepository.findOne(affiliate.getAffiliateId()), notNullValue(Affiliate.class)); assertThat(applicationRepository.findOne(primaryApplication.getApplicationId()), notNullValue(Application.class)); assertThat(applicationRepository.findOne(extensionApplication.getApplicationId()), notNullValue(Application.class)); assertThat(userRepository.findByLoginIgnoreCase(userEmail), notNullValue(User.class)); assertThat(commercialUsageRepository.findOne(commercialUsage.getCommercialUsageId()), notNullValue(CommercialUsage.class)); assertThat(affiliateDetailsRepository.findOne(affiliateSharedDetails.getAffiliateDetailsId()), notNullValue(AffiliateDetails.class)); assertThat(affiliateDetailsRepository.findOne(affiliateExtensionDetails.getAffiliateDetailsId()), notNullValue(AffiliateDetails.class)); assertThat(applicationRepository.findByUsernameIgnoreCase(userEmail).size(), is(2)); // Test affiliateDeleter.deleteAffiliate(affiliate); // JPA should no longer match entities assertThat(affiliateRepository.findOne(affiliate.getAffiliateId()), nullValue(Affiliate.class)); assertThat(applicationRepository.findOne(primaryApplication.getApplicationId()), nullValue(Application.class)); assertThat(applicationRepository.findOne(extensionApplication.getApplicationId()), nullValue(Application.class)); assertThat(userRepository.findByLoginIgnoreCase(userEmail), nullValue(User.class)); assertThat(commercialUsageRepository.findOne(commercialUsage.getCommercialUsageId()), nullValue(CommercialUsage.class)); assertThat(affiliateDetailsRepository.findOne(affiliateSharedDetails.getAffiliateDetailsId()), nullValue(AffiliateDetails.class)); assertThat(affiliateDetailsRepository.findOne(affiliateExtensionDetails.getAffiliateDetailsId()), nullValue(AffiliateDetails.class)); // JPA should no longer find through custom repository assertThat(applicationRepository.findByUsernameIgnoreCase(userEmail).size(), is(0)); // Records should still be present in the database assertThat(matchingNativeRecords("SELECT affiliate_id FROM affiliate WHERE affiliate_id="+affiliate.getAffiliateId()), is(1)); assertThat(matchingNativeRecords("SELECT application_id FROM application WHERE application_id="+primaryApplication.getApplicationId()), is(1)); assertThat(matchingNativeRecords("SELECT application_id FROM application WHERE application_id="+extensionApplication.getApplicationId()), is(1)); assertThat(matchingNativeRecords("SELECT user_id FROM T_USER WHERE user_id="+user.getUserId()), is(1)); assertThat(matchingNativeRecords("SELECT commercial_usage_id FROM commercial_usage WHERE commercial_usage_id="+commercialUsage.getCommercialUsageId()), is(1)); assertThat(matchingNativeRecords("SELECT affiliate_details_id FROM affiliate_details WHERE affiliate_details_id="+affiliateSharedDetails.getAffiliateDetailsId()), is(1)); assertThat(matchingNativeRecords("SELECT affiliate_details_id FROM affiliate_details WHERE affiliate_details_id="+affiliateExtensionDetails.getAffiliateDetailsId()), is(1)); } private CommercialUsage withCommercialUsage(Affiliate affiliate) { CommercialUsage commercialUsage = new CommercialUsage(); commercialUsage.setType(AffiliateType.COMMERCIAL); entityManager.persist(commercialUsage); CommercialUsageCountry count = new CommercialUsageCountry(); entityManager.persist(count); commercialUsage.addCount(count); CommercialUsageEntry entry = new CommercialUsageEntry(); entityManager.persist(entry); commercialUsage.addEntry(entry); affiliate.addCommercialUsage(commercialUsage); affiliateRepository.save(affiliate); return commercialUsage; } private int matchingNativeRecords(String query) { return entityManager.createNativeQuery(query).getResultList().size(); } private Affiliate withAffiliateUser(StandingState standingState, Member homeMember, String email) { Affiliate affiliate = new Affiliate(); affiliate.setHomeMember(homeMember); affiliate.setCreator(email); AffiliateDetails affiliateDetails = new AffiliateDetails(); affiliateDetails.setEmail(email); affiliate.setAffiliateDetails(affiliateDetails); affiliate.setStandingState(standingState); entityManager.persist(affiliate.getAffiliateDetails()); affiliateRepository.save(affiliate); return affiliate; } private User withUser(String email) { User user = new User(); user.setEmail(email); user.setLogin(email); userRepository.save(user); return user; } private Application withPrimaryApplication(Affiliate affiliate, Member member, ApprovalState approvalState) { PrimaryApplication application = new PrimaryApplication(); application.setMember(member); application.setApprovalState(approvalState); application.setUsername(affiliate.getCreator()); AffiliateDetails applicationAffiliateDetails = createStandaloneAffiliateDetails(); application.setAffiliateDetails(applicationAffiliateDetails); entityManager.persist(application); affiliate.setApplication(application); affiliateRepository.save(affiliate); return application; } private AffiliateDetails createStandaloneAffiliateDetails() { AffiliateDetails applicationAffiliateDetails = new AffiliateDetails(); applicationAffiliateDetails.setFirstName(randomString("firstName")); applicationAffiliateDetails.setLastName(randomString("lastName"));; applicationAffiliateDetails.setAddress(new MailingAddress()); return applicationAffiliateDetails; } /** * flush to JPA + Lucene. JPA queries trigger a JPA flush, but Hibernate Search * only flushes on TX commit by default. But are using a TX rollback test strategy, so we * need to flush Lucene manually. */ private void flush() { entityManager.flush(); } Affiliate makeAffiliate() { Affiliate affiliate = new Affiliate(); affiliate.setAffiliateDetails(new AffiliateDetails()); affiliate.getAffiliateDetails().setFirstName(randomString("firstName"));; affiliate.getAffiliateDetails().setLastName(randomString("lastName"));; affiliate.getAffiliateDetails().setAddress(new MailingAddress()); affiliate.setHomeMember(ihtsdo); entityManager.persist(affiliate.getAffiliateDetails()); affiliateRepository.save(affiliate); return affiliate; } private Application withExtensionApplication(Affiliate affiliate, Member member, ApprovalState approvalState) { ExtensionApplication application = new ExtensionApplication(); application.setMember(member); application.setApprovalState(approvalState); application.setUsername(affiliate.getCreator()); AffiliateDetails affiliateDetails = createStandaloneAffiliateDetails(); application.setAffiliateDetails(affiliateDetails); entityManager.persist(application); affiliate.addApplication(application); affiliateRepository.save(affiliate); return application; } private String randomString(String prefix) { return prefix + random.nextLong(); } }