diff --git a/solidify-auth/src/main/java/ch/unige/solidify/auth/oidc/OIDCUser.java b/solidify-auth/src/main/java/ch/unige/solidify/auth/oidc/OIDCUser.java index 31e72ef88af6629a61dd063d31c9ea69e0f2c4af..9b30f64b5bf54610c0962f68ba105d56585ebc24 100644 --- a/solidify-auth/src/main/java/ch/unige/solidify/auth/oidc/OIDCUser.java +++ b/solidify-auth/src/main/java/ch/unige/solidify/auth/oidc/OIDCUser.java @@ -3,6 +3,7 @@ package ch.unige.solidify.auth.oidc; import java.io.Serializable; import java.util.Set; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import ch.unige.solidify.auth.util.SsoUserData; @@ -73,6 +74,7 @@ public class OIDCUser extends SsoUser implements Serializable { @JsonProperty(value = "isMemberOf") @Override + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) public Set<String> getIsmemberOf() { return super.getIsmemberOf(); } @@ -111,4 +113,4 @@ public class OIDCUser extends SsoUser implements Serializable { + '\'' + ", name='" + name + '\'' + ", roles=" + roles + ", systemId=" + systemId + ", allProperties=" + allProperties + '}'; } -} \ No newline at end of file +} diff --git a/solidify-auth/src/main/java/ch/unige/solidify/auth/oidc/OidcUserFactory.java b/solidify-auth/src/main/java/ch/unige/solidify/auth/oidc/OidcUserFactory.java index bc2ea93356418fb22518e65381ca02bc3d33cd37..9f7e0185a08b7c6e55dd3b60d768f2697662da95 100644 --- a/solidify-auth/src/main/java/ch/unige/solidify/auth/oidc/OidcUserFactory.java +++ b/solidify-auth/src/main/java/ch/unige/solidify/auth/oidc/OidcUserFactory.java @@ -1,6 +1,8 @@ package ch.unige.solidify.auth.oidc; import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; @@ -10,7 +12,10 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.UnknownHttpStatusCodeException; import ch.unige.solidify.auth.util.OIDCUtil; import ch.unige.solidify.auth.util.OidcTokenExpiredException; @@ -18,7 +23,8 @@ import ch.unige.solidify.model.sso.SsoUser; @Component public class OidcUserFactory { - + private static final java.util.logging.Logger LOGGER = + Logger.getLogger(OidcUserFactory.class.getName()); public static final String OIDC_ACCESS_TOKEN = "oidc_access_token"; public static final String OIDC_ACCESS_TOKEN_EXPIRES = "oidc_access_token_expires"; public static final String OIDC_USER_CACHE_NAME = "cache_for_oidc"; @@ -38,10 +44,31 @@ public class OidcUserFactory { } HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Bearer " + token); - HttpEntity<String> entity = new HttpEntity<>("parameters", headers); + HttpEntity<String> entity = new HttpEntity<>(null, headers); RestTemplate restTemplate = new RestTemplate(); - OIDCUser result = - restTemplate.postForObject(userInfoLink, entity, OIDCUser.class); + OIDCUser result = null; + try { + result = + restTemplate.postForObject(userInfoLink, entity, OIDCUser.class); + } catch (Exception e) { + LOGGER.log(Level.SEVERE, "Exception when invoking url " + userInfoLink, e); + if (e instanceof HttpClientErrorException) { + throw (HttpClientErrorException) e; + } + if (e instanceof HttpServerErrorException) { + throw (HttpServerErrorException) e; + } + if (e instanceof UnknownHttpStatusCodeException) { + throw (UnknownHttpStatusCodeException) e; + } + String resultString = + restTemplate.postForObject(userInfoLink, entity, String.class); + LOGGER.log(Level.SEVERE, "Resultat invoking url " + resultString, e); + throw new RuntimeException( + "Response body from userInfoLink :" + resultString + " ; Error message : " + e + .getMessage() + " CAUSE: " + e.getCause().getMessage(), e); + + } result.setOauthToken(token); result.setOauthTokenExpiresTime(tokenExpiresTime); return result; @@ -55,7 +82,7 @@ public class OidcUserFactory { return OIDCUser.toUserData(result); } - @CacheEvict(allEntries = true, cacheNames = {OIDC_USER_CACHE_NAME}) + @CacheEvict(allEntries = true, cacheNames = { OIDC_USER_CACHE_NAME }) @Scheduled(fixedDelay = TEN_MINUTES) public void reFreshOidcUserCache() { } diff --git a/solidify-auth/src/test/java/ch/unige/solidify/test/auth/OidcSsoUserTest.java b/solidify-auth/src/test/java/ch/unige/solidify/test/auth/OidcSsoUserTest.java index bea0e50339482c01315c8cfa86fecd3ad3827389..f5d60f1abde120449d21ded2380e08772c5110f1 100644 --- a/solidify-auth/src/test/java/ch/unige/solidify/test/auth/OidcSsoUserTest.java +++ b/solidify-auth/src/test/java/ch/unige/solidify/test/auth/OidcSsoUserTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doAnswer; +import java.io.IOException; import java.util.Map; import org.junit.Before; @@ -13,9 +14,11 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; -import ch.unige.solidify.model.sso.SsoUser; +import com.fasterxml.jackson.databind.ObjectMapper; + import ch.unige.solidify.auth.oidc.OIDCUser; import ch.unige.solidify.auth.oidc.OidcUserFactory; +import ch.unige.solidify.model.sso.SsoUser; import ch.unige.solidify.test.auth.data.MockData; /** @@ -26,7 +29,7 @@ import ch.unige.solidify.test.auth.data.MockData; @RunWith(MockitoJUnitRunner.class) public class OidcSsoUserTest { - OIDCUser oidcUser = new OIDCUser(); + private OIDCUser oidcUser = new OIDCUser(); @Mock private OidcUserFactory oidcUserFactory; @@ -36,22 +39,18 @@ public class OidcSsoUserTest { @Before public void setup() { oidcHeaders = MockData.getOidcHeadersMockData(); - for (String key : oidcHeaders.keySet()) { - oidcHeaders.put(key, oidcHeaders.get(key)); - } + oidcHeaders.replaceAll((key, oldValue)->oidcHeaders.get(key)); oidcUser.setOauthToken((String) MockData.getOidcHeadersMockData().get("oidc_access_token")); oidcUser.setUniqueId((String) MockData.getOidcHeadersMockData().get("oidc_claim_sub")); - doAnswer((Answer<OIDCUser>) invocation -> { - return oidcUser; - } + doAnswer((Answer<OIDCUser>) invocation -> oidcUser ).when(oidcUserFactory) .getOidcUser((String) MockData.getOidcHeadersMockData().get("oidc_access_token"), (long) MockData.getOidcHeadersMockData().get("OIDC_access_token_expires")); } @Test - public void testOcidcIdUser() { + public void testOidcIdUser() { OIDCUser user = this.oidcUserFactory .getOidcUser((String) MockData.getOidcHeadersMockData().get("oidc_access_token"), (long) MockData.getOidcHeadersMockData().get("OIDC_access_token_expires")); @@ -63,4 +62,38 @@ public class OidcSsoUserTest { assertEquals(MockData.oauthAccessToken, ssoUserData.getAccessToken()); } + @Test + public void oidcJacksonString2ArrayTest() throws IOException { + String jsonAsString = + "{\"email\":\"Raoli.Wang@unige.ch\",\"sub\":\"135192@unige.ch\"," + + "\"isMemberOf\":\"webreporting:user\"," + + "\"affiliation\":\"member\"," + + "\"employeeType\":\"EDTUDIANT\"," + + "\"unigeChStudentCategory\":\"EDTUDIANT\"," + + "\"roles\":\"user\"" + + "}"; + ObjectMapper mapper = new ObjectMapper(); + OIDCUser user = mapper.readValue(jsonAsString, OIDCUser.class); + assertEquals("135192@unige.ch", user.getUniqueId()); + assertEquals(1, user.getIsmemberOf().size()); + assertEquals(1, user.getAffiliation().size()); + assertEquals(1, user.getEmployeeType().size()); + assertEquals(1, user.getUnigeChStudentCategory().size()); + assertEquals(1, user.getRoles().size()); + String jsonAsString2 = + "{\"email\":\"Raoli.Wang@unige.ch\",\"sub\":\"135192@unige.ch\"," + + "\"isMemberOf\":[\"webreporting:user\",\"internalinvoicing:user\"]," + + "\"affiliation\":[\"member\",\"staff\"]," + + "\"employeeType\":[\"webreporting:user\",\"internalinvoicing:user\"]," + + "\"unigeChStudentCategory\":[\"ETUDIANT\",\"STAFF\"]," + + "\"roles\":[\"user\",\"editor\"]" + + "}"; + user = mapper.readValue(jsonAsString2, OIDCUser.class); + assertEquals(2, user.getIsmemberOf().size()); + assertEquals(2, user.getAffiliation().size()); + assertEquals(2, user.getEmployeeType().size()); + assertEquals(2, user.getUnigeChStudentCategory().size()); + assertEquals(2, user.getRoles().size()); + } + } diff --git a/solidify-controller/pom.xml b/solidify-controller/pom.xml index 78a290d3196308e351373006160d58764f57ce37..448f4baef56622c2646f3584eec6d80847c7b3e3 100644 --- a/solidify-controller/pom.xml +++ b/solidify-controller/pom.xml @@ -1,69 +1,78 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>ch.unige.solidify</groupId> - <artifactId>solidify-parent</artifactId> - <version>0.9.0-SNAPSHOT</version> - </parent> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>ch.unige.solidify</groupId> + <artifactId>solidify-parent</artifactId> + <version>0.9.0-SNAPSHOT</version> + </parent> - <artifactId>solidify-controller</artifactId> - <name>Solidify Controller</name> - <description>Solidify Controller library</description> + <artifactId>solidify-controller</artifactId> + <name>Solidify Controller</name> + <description>Solidify Controller library</description> - <dependencies> - <!--Solidify dependencies --> - <dependency> - <groupId>ch.unige.solidify</groupId> - <artifactId>solidify-model</artifactId> - </dependency> - <!--Rest dependencies --> - <dependency> - <groupId>org.json</groupId> - <artifactId>json</artifactId> - </dependency> - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpasyncclient</artifactId> - </dependency> + <dependencies> + <!--Solidify dependencies --> + <dependency> + <groupId>ch.unige.solidify</groupId> + <artifactId>solidify-model</artifactId> + </dependency> + <!--Rest dependencies --> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpasyncclient</artifactId> + </dependency> - <!--Database dependencies --> - <dependency> - <groupId>mysql</groupId> - <artifactId>mysql-connector-java</artifactId> - </dependency> + <!--Database dependencies --> + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + </dependency> - <!--Spring dependencies --> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web-services</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-hateoas</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-security</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-activemq</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.security</groupId> - <artifactId>spring-security-test</artifactId> - </dependency> - </dependencies> + <!--Spring dependencies --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web-services</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-hateoas</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-activemq</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-test</artifactId> + </dependency> + + <dependency> + <groupId>com.oracle.jdbc</groupId> + <artifactId>ojdbc8</artifactId> + <version>12.2.0.1</version> + <scope>test</scope> + </dependency> + </dependencies> </project> diff --git a/solidify-controller/src/main/java/ch/unige/solidify/controller/ResourceController.java b/solidify-controller/src/main/java/ch/unige/solidify/controller/ResourceController.java index b4302dc7a0bc83de84267c41e7f3c54ce36c1cea..95cc2e0f0787af213201168802faf3b3034afd58 100644 --- a/solidify-controller/src/main/java/ch/unige/solidify/controller/ResourceController.java +++ b/solidify-controller/src/main/java/ch/unige/solidify/controller/ResourceController.java @@ -87,13 +87,13 @@ public abstract class ResourceController<T extends Resource<T>> extends Solidify new Object[] { t1.getClass().getSimpleName() + ": " + id })); } - if (t1.update(t2)) { - this.setAuthenticatedUserProperties(t1); - T item = this.itemService.save(t1); + if (t2.update(t1)) { + this.setAuthenticatedUserProperties(t2); + T item = this.itemService.save(t2); this.addLinks(item); return new ResponseEntity<>(item, HttpStatus.OK); } else { - return new ResponseEntity<>(t1, HttpStatus.OK); + return new ResponseEntity<>(t2, HttpStatus.OK); } } diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/ReadOnlyControllerWithOracleDbTest.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/ReadOnlyControllerWithOracleDbTest.java new file mode 100644 index 0000000000000000000000000000000000000000..654d348f9be8986a25fc7734a3f931f7fecbeb21 --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/ReadOnlyControllerWithOracleDbTest.java @@ -0,0 +1,45 @@ +package ch.unige.solidify.oracle.test; + +import static org.hamcrest.CoreMatchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import ch.unige.solidify.oracle.test.web.TestConfigApplication; + +@RunWith(SpringRunner.class) +@AutoConfigureMockMvc +@SpringBootTest(classes = TestConfigApplication.class) +@WithMockUser(username = "TEST", password = "TEST") +public class ReadOnlyControllerWithOracleDbTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void testGetSearchWithOracleContains() throws Exception { + mockMvc.perform(get("/oraTest/search?search=namesForSearch¢%RAOLI% WITHIN PRENOMS")) + .andExpect(status().isOk()) + .andExpect(content().contentType("application/hal+json;charset=UTF-8")) + // .andDo(print()); + .andExpect(jsonPath("_data[0].entityId", is("514425"))); + } + @Test + public void testGetSearchWithOracleContainsMix() throws Exception { + mockMvc.perform(get("/oraTest/search?search=lastname:WANG,namesForSearch¢RAOLI WITHIN PRENOMS")) + .andExpect(status().isOk()) + .andExpect(content().contentType("application/hal+json;charset=UTF-8")) + // .andDo(print()); + .andExpect(jsonPath("_data[0].entityId", is("514425"))); + } +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/bus/ApplicationLinkedResourceChecker.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/bus/ApplicationLinkedResourceChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..ad1e66ca54d673a3fdccd937230251c78a50574c --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/bus/ApplicationLinkedResourceChecker.java @@ -0,0 +1,19 @@ +package ch.unige.solidify.oracle.test.bus; + +import org.springframework.stereotype.Service; +import org.springframework.validation.BindingResult; + +import ch.unige.solidify.rest.Resource; +import ch.unige.solidify.service.CompositeResourceService; +import ch.unige.solidify.service.LinkedResourceChecker; + +@Service +public class ApplicationLinkedResourceChecker<T extends Resource<T>> + implements LinkedResourceChecker<T> { + + @Override + public void validateLinkedResources(CompositeResourceService<T> service, T item, + BindingResult errors) { + service.validateLinkedResources(item, errors); + } +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/bus/IindividuEntityService.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/bus/IindividuEntityService.java new file mode 100644 index 0000000000000000000000000000000000000000..29d08fcabf59fd281699e382c22e87f225e95ac7 --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/bus/IindividuEntityService.java @@ -0,0 +1,10 @@ +package ch.unige.solidify.oracle.test.bus; + +import org.springframework.stereotype.Service; + +import ch.unige.solidify.oracle.test.dao.IindividuEntity; +import ch.unige.solidify.service.CompositeResourceService; + +@Service +public class IindividuEntityService extends CompositeResourceService<IindividuEntity> { +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuEntity.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..a2368ea4abf6cfdde1f2624497a2237caf6e8a4e --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuEntity.java @@ -0,0 +1,96 @@ +package ch.unige.solidify.oracle.test.dao; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.springframework.data.jpa.domain.Specification; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import ch.unige.solidify.model.ChangeInfo; +import ch.unige.solidify.rest.ResourceDiverse; +import ch.unige.solidify.util.SearchCriteria; + +@Entity +@Table(name = "IINDIVIDU") +public class IindividuEntity extends ResourceDiverse<IindividuEntity> { + + @Id + @Column(name = "CN_INDIVIDU", nullable = false) + private String entityId; + + public String getLastname() { + return lastname; + } + + public void setLastname(String lastname) { + this.lastname = lastname; + } + + public String getFirstname() { + return firstname; + } + + public void setFirstname(String firstname) { + this.firstname = firstname; + } + + public String getNamesForSearch() { + return namesForSearch; + } + + public void setNamesForSearch(String namesForSearch) { + this.namesForSearch = namesForSearch; + } + + @Column(name = "NOM", nullable = false) + private String lastname; + + public void setEntityId(String entityId) { + this.entityId = entityId; + } + + @Column(name = "PRENOMS", nullable = false) + private String firstname; + + @Column(name = "RECH_NOMS") + private String namesForSearch; + + @Override + public Specification<IindividuEntity> getSpecification() { + return null; + } + + @Override + public void init() { + + } + + @Override + public ChangeInfo getCreation() { + return null; + } + + @Override + public String managedBy() { + return null; + } + + @java.beans.Transient + @JsonIgnore + public Specification<IindividuEntity> getSearchSpecification(SearchCriteria criteria) { + return new IindividuSpecification(criteria); + } + + @Override + public String getEntityId() { + return entityId; + } + + @Override + public ChangeInfo getLastUpdate() { + return null; + } +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuEntityRepository.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuEntityRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..d3b62b213861da5e89ee3554d56608a2d580cf87 --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuEntityRepository.java @@ -0,0 +1,9 @@ +package ch.unige.solidify.oracle.test.dao; + +import org.springframework.stereotype.Repository; + +import ch.unige.solidify.repository.SolidifyRepository; + +@Repository +public interface IindividuEntityRepository extends SolidifyRepository<IindividuEntity> { +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuSpecification.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuSpecification.java new file mode 100644 index 0000000000000000000000000000000000000000..1534458b3a2b811cf2201f4fd64789b976ecda8f --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/dao/IindividuSpecification.java @@ -0,0 +1,10 @@ +package ch.unige.solidify.oracle.test.dao; + +import ch.unige.solidify.specification.SearchSpecification; +import ch.unige.solidify.util.SearchCriteria; + +public class IindividuSpecification extends SearchSpecification<IindividuEntity> { + public IindividuSpecification(SearchCriteria criteria) { + super(criteria); + } +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/rest/IIndividuRestService.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/rest/IIndividuRestService.java new file mode 100644 index 0000000000000000000000000000000000000000..65ae9ea46b1484cb9e0525d3156598be173f55fd --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/rest/IIndividuRestService.java @@ -0,0 +1,17 @@ +package ch.unige.solidify.oracle.test.rest; + +import org.springframework.stereotype.Service; + +import ch.unige.solidify.service.AuthenticationStorageProxy; +import ch.unige.solidify.service.MessageService; +import ch.unige.solidify.service.SolidifyRestClientService; +import ch.unige.solidify.util.RestClientTool; + +@Service +public class IIndividuRestService extends SolidifyRestClientService { + + public IIndividuRestService(MessageService messageService, RestClientTool restClientTool, + AuthenticationStorageProxy authenticationStorageProxy) { + super(restClientTool, messageService, authenticationStorageProxy); + } +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/rest/IindividuResourceService.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/rest/IindividuResourceService.java new file mode 100644 index 0000000000000000000000000000000000000000..5ac1e23499eaf60fa871f46ec2edeac6470069a3 --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/rest/IindividuResourceService.java @@ -0,0 +1,20 @@ +package ch.unige.solidify.oracle.test.rest; + +import org.springframework.stereotype.Service; + +import ch.unige.solidify.oracle.test.dao.IindividuEntity; +import ch.unige.solidify.service.ResourceService; +import ch.unige.solidify.service.SolidifyRestClientService; + +@Service +public class IindividuResourceService extends ResourceService<IindividuEntity> { + + public IindividuResourceService(SolidifyRestClientService restClientService) { + super(restClientService); + } + + @Override + protected Class<IindividuEntity> getResourceClass() { + return null; + } +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/web/ReadOnlyControllerWithOracleDb.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/web/ReadOnlyControllerWithOracleDb.java new file mode 100644 index 0000000000000000000000000000000000000000..e45876fd4daf02218f759a67456c817e07a3ff5e --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/web/ReadOnlyControllerWithOracleDb.java @@ -0,0 +1,12 @@ +package ch.unige.solidify.oracle.test.web; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import ch.unige.solidify.controller.ResourceReadOnlyController; +import ch.unige.solidify.oracle.test.dao.IindividuEntity; + +@RestController +@RequestMapping("/oraTest") +public class ReadOnlyControllerWithOracleDb extends ResourceReadOnlyController<IindividuEntity> { +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/web/TestConfigApplication.java b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/web/TestConfigApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..41ec32d75c454acbb96dc80d7f5c50df871a6f9b --- /dev/null +++ b/solidify-controller/src/test/java/ch/unige/solidify/oracle/test/web/TestConfigApplication.java @@ -0,0 +1,33 @@ +package ch.unige.solidify.oracle.test.web; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.PropertySource; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootApplication(exclude = { + org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class, + org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration.class } +) +@ComponentScan(basePackages = { "ch.unige.solidify.oracle.test", "ch.unige.solidify" }, + excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, + pattern = "ch\\.unige\\.solidify\\.test\\..*")) +@PropertySource(value = "classpath:oracle_config.properties") +@EnableJpaRepositories(basePackages = { "ch.unige.solidify.oracle.test.dao" }) +@EntityScan(basePackages = "ch.unige.solidify.oracle.test") +public class TestConfigApplication extends SpringBootServletInitializer { + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(TestConfigApplication.class); + } + + public static void main(String[] args) { + SpringApplication.run(TestConfigApplication.class, args); + } + +} diff --git a/solidify-controller/src/test/java/ch/unige/solidify/test/controller/ResourceReadOnlyControllerTest.java b/solidify-controller/src/test/java/ch/unige/solidify/test/controller/ResourceReadOnlyControllerTest.java index 49705b600f700f2c793dbeed4f872e05e8b91f81..2a4b159944d63589ac96becb1358f4d1d390bef1 100644 --- a/solidify-controller/src/test/java/ch/unige/solidify/test/controller/ResourceReadOnlyControllerTest.java +++ b/solidify-controller/src/test/java/ch/unige/solidify/test/controller/ResourceReadOnlyControllerTest.java @@ -110,4 +110,7 @@ public class ResourceReadOnlyControllerTest { .andExpect(jsonPath("_data[0].searchCriterias").doesNotExist()) .andExpect(jsonPath("_data[0].name", is("doe"))); } + + public static class ResourceReadOnlyControllerOracleDBTest { + } } diff --git a/solidify-controller/src/test/java/ch/unige/solidify/test/controller/config/MockApplication.java b/solidify-controller/src/test/java/ch/unige/solidify/test/controller/config/MockApplication.java index 2788ceb0fc6bf9865992a614c0136f18db1706b4..b699c78f4d15c545ce0978d98c8ab4a16b8ccb50 100644 --- a/solidify-controller/src/test/java/ch/unige/solidify/test/controller/config/MockApplication.java +++ b/solidify-controller/src/test/java/ch/unige/solidify/test/controller/config/MockApplication.java @@ -6,6 +6,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.PropertySource; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -15,8 +17,11 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe @EnableGlobalMethodSecurity(jsr250Enabled = true, proxyTargetClass = true, prePostEnabled = true) @EntityScan(basePackages = "ch.unige.solidify.test.controller.dao") @ComponentScan(basePackages = { "ch.unige.solidify.test.controller.dao", - "ch.unige.solidify.test.controller", "ch.unige.solidify" }) + "ch.unige.solidify.test.controller", "ch.unige.solidify" }, + excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, + pattern = "ch\\.unige\\.solidify\\.oracle\\.test\\..*")) @EnableJpaRepositories(basePackages = { "ch.unige.solidify.test.controller.dao" }) +@PropertySource(value = "classpath:h2_config.properties") public class MockApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { diff --git a/solidify-controller/src/test/resources/H2_config.properties b/solidify-controller/src/test/resources/H2_config.properties new file mode 100644 index 0000000000000000000000000000000000000000..67a447e0cd97a389c8faa31ce816dc28fa8ea439 --- /dev/null +++ b/solidify-controller/src/test/resources/H2_config.properties @@ -0,0 +1,11 @@ +spring.application.name=test +spring.banner.location=classpath:SolidifyBanner.txt +spring.datasource.jndi-name=false +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:~/testdb;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password= +spring.h2.console.enabled=true +spring.jpa.show-sql=true +spring.jpa.database-platform: org.hibernate.dialect.H2Dialect +spring.jackson.serialization.write-dates-as-timestamps=false diff --git a/solidify-controller/src/test/resources/application.yaml b/solidify-controller/src/test/resources/application.yaml.backup similarity index 100% rename from solidify-controller/src/test/resources/application.yaml rename to solidify-controller/src/test/resources/application.yaml.backup diff --git a/solidify-controller/src/test/resources/oracle_config.properties b/solidify-controller/src/test/resources/oracle_config.properties new file mode 100644 index 0000000000000000000000000000000000000000..3e0687e0b3f321bbb44051d9b08b9a02c41714c9 --- /dev/null +++ b/solidify-controller/src/test/resources/oracle_config.properties @@ -0,0 +1,13 @@ +spring.application.name=test +spring.datasource.jndi-name=false +spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver +spring.datasource.url=jdbc:oracle:thin:@infatst:1529:infatst +spring.datasource.username=XXXX +spring.datasource.password=XXXX +spring.datasource.hikari.maximum-pool-size=1 +spring.jpa.show-sql=true +logging.level.org.hibernate.SQL=DEBUG +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE +spring.jpa.properties.hibernate.format_sql=true + + diff --git a/solidify-model/src/main/java/ch/unige/solidify/model/sso/SsoUser.java b/solidify-model/src/main/java/ch/unige/solidify/model/sso/SsoUser.java index 3e1796c40a54584effdabf3e935cc153535d1e51..7c713aa933609bfe233ff48390931a786f05cdcf 100644 --- a/solidify-model/src/main/java/ch/unige/solidify/model/sso/SsoUser.java +++ b/solidify-model/src/main/java/ch/unige/solidify/model/sso/SsoUser.java @@ -6,6 +6,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import com.fasterxml.jackson.annotation.JsonFormat; + import ch.unige.solidify.model.User; import ch.unige.solidify.util.StringTool; @@ -22,18 +24,26 @@ public class SsoUser implements User, Serializable { protected String email; protected String homeorganization; protected String homeorganizationtype; + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) protected Set<String> affiliation = Collections.synchronizedSet(new HashSet<>()); + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) protected Set<String> ismemberOf = Collections.synchronizedSet(new HashSet<>()); + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) protected Set<String> employeeType = Collections.synchronizedSet(new HashSet<>()); + protected String unigechoucode; protected String unigechstudentoucode; protected String unigechemployeeoucode; protected String uniqueId; + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) protected Set<String> unigeChStudentCategory = Collections.synchronizedSet(new HashSet<>()); protected String orgunitdn; protected String matriculationnumber; protected String cnindividu; protected String name = null; + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) protected Set<String> roles = Collections.synchronizedSet(new HashSet<>()); protected long systemId = 0; diff --git a/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceBase.java b/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceBase.java index df701a3980b74b2980811a51ec9caccb42404d39..c80aaca30e9a8cd67a61d0046b46cdab15c808e0 100644 --- a/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceBase.java +++ b/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceBase.java @@ -1,16 +1,21 @@ package ch.unige.solidify.rest; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.time.OffsetDateTime; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; import javax.persistence.Transient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.hateoas.ResourceSupport; +import org.springframework.util.ReflectionUtils; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -19,7 +24,8 @@ import ch.unige.solidify.util.ReflectionTool; public abstract class ResourceBase extends ResourceSupport { private static final Logger logger = LoggerFactory.getLogger(ResourceBase.class); - + private static final String[] No_updatable_metaColumnNames = + new String[] { "searchCriterias", "lastUpdate", "updatedAt", "updatedBy", "dirtyFields" }; @Transient @JsonIgnore protected List<String> dirtyFields; @@ -92,29 +98,48 @@ public abstract class ResourceBase extends ResourceSupport { /** * Update the current Resource with the dirty attributes of the given Resource * - * @param item - * Resource + * @param item Resource * @return boolean Return true if the current Resource has been modified */ public boolean update(ResourceBase item) { OffsetDateTime lastUpdate = this.getUpdateTime(); - - List<String> dirtyFields = item.getDirtyFields(); - - for (String fieldname : dirtyFields) { + Set<String> dirtyFields = new HashSet<>(this.getDirtyFields()); + // getAllFields + Set<String> listNonModifiable = new HashSet<>(); + + ReflectionUtils.doWithFields(item.getClass(), + new ReflectionUtils.FieldCallback() { + @Override + public void doWith(final Field field) throws IllegalArgumentException { + listNonModifiable.add(field.getName()); + } + }, + new ReflectionUtils.FieldFilter() { + @Override + public boolean matches(final Field field) { + final int modifiers = field.getModifiers(); + // no static fields + Boolean isNotStaticField = !Modifier.isStatic(modifiers); + Boolean isNotUpdatableField = + !Arrays.stream(No_updatable_metaColumnNames).anyMatch(field.getName()::equals); + return isNotStaticField && isNotUpdatableField; + } + }); + + listNonModifiable.removeAll(dirtyFields); + for (String fieldname : listNonModifiable) { try { - Field field = item.getClass().getDeclaredField(fieldname); + Field field = ReflectionUtils.findField(this.getClass(), fieldname); field.setAccessible(true); Object newValue = field.get(item); Object currentValue = field.get(this); - - if (currentValue == newValue || (currentValue != null && currentValue.equals(newValue))) { + if (currentValue == newValue || (currentValue != null && currentValue.equals(newValue))) { // update with same value --> do nothing } else { - this.setProperty(fieldname, newValue); + this.setProperty(fieldname, newValue); } - } catch (NoSuchFieldException | IllegalAccessException e) { + } catch (IllegalAccessException e) { return false; } } @@ -144,14 +169,14 @@ public abstract class ResourceBase extends ResourceSupport { ResourceBase resourceBase = (ResourceBase) obj; if (this.getCreationTime() != null && this.getUpdateTime() != null) { return super.equals(obj) - && Objects.equals(this.getCreationTime(), resourceBase.getCreationTime()) - && Objects.equals(this.getUpdateTime(), resourceBase.getUpdateTime()); + && Objects.equals(this.getCreationTime(), resourceBase.getCreationTime()) + && Objects.equals(this.getUpdateTime(), resourceBase.getUpdateTime()); } else if (this.getCreationTime() != null) { return super.equals(obj) - && Objects.equals(this.getCreationTime(), resourceBase.getCreationTime()); + && Objects.equals(this.getCreationTime(), resourceBase.getCreationTime()); } else if (this.getUpdateTime() != null) { return super.equals(obj) - && Objects.equals(this.getUpdateTime(), resourceBase.getUpdateTime()); + && Objects.equals(this.getUpdateTime(), resourceBase.getUpdateTime()); } return super.equals(obj); } diff --git a/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceCET.java b/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceCET.java index b3ad9d8a2a06f53d0fac75d3f0df49531beee7e3..e6435f100598b4e470c49f1eac101759249b5131 100644 --- a/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceCET.java +++ b/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceCET.java @@ -2,7 +2,6 @@ package ch.unige.solidify.rest; import java.time.LocalDateTime; import java.time.OffsetDateTime; -import java.time.ZoneOffset; import javax.persistence.Column; import javax.persistence.EntityListeners; @@ -41,10 +40,10 @@ public abstract class ResourceCET<T> extends Resource<T> { this.updatedBy = ""; this.createdAt = LocalDateTime.now(); this.createdBy = ""; - this.creation = new ChangeInfo(DateTool.swissDateTime2offSetDate(this.createdAt), - this.createdBy); - this.lastUpdate = new ChangeInfo(DateTool.swissDateTime2offSetDate(this.updatedAt), - this.updatedBy); + this.creation = + new ChangeInfo(DateTool.swissDateTime2offSetDate(this.createdAt), this.createdBy); + this.lastUpdate = + new ChangeInfo(DateTool.swissDateTime2offSetDate(this.updatedAt), this.updatedBy); } @@ -67,7 +66,8 @@ public abstract class ResourceCET<T> extends Resource<T> { @Override @JsonIgnore(false) public String getCreatedBy() { - if (this.getCreation().getWho() == null || this.getCreation().getWho().isEmpty()) { + if (this.creation.getWhen() == null || this.creation.getWho() == null || this.creation.getWho() + .isEmpty()) { resetCreation(); } return this.createdBy; @@ -75,17 +75,28 @@ public abstract class ResourceCET<T> extends Resource<T> { @Override public void setCreatedBy(String createdBy) { - resetCreation(); this.createdBy = createdBy; - this.updateTime(); + resetCreation(); + } + + public LocalDateTime getCreatedAt() { + if (this.creation.getWhen() == null || this.creation.getWho() == null || this.creation.getWho() + .isEmpty()) { + resetCreation(); + } + return this.createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; } @Override @JsonIgnore(false) public String getUpdatedBy() { - if (this.getLastUpdate().getWho() == null || this.getLastUpdate().getWho().isEmpty()) { - this.getLastUpdate().setWho(this.updatedBy); - this.getLastUpdate().setWhen(DateTool.swissDateTime2offSetDate(this.updatedAt)); + if (this.lastUpdate.getWhen() == null || this.lastUpdate.getWho() == null || this.lastUpdate + .getWho().isEmpty()) { + setLastUpdate(); } return this.updatedBy; } @@ -93,18 +104,14 @@ public abstract class ResourceCET<T> extends Resource<T> { @Override public void setUpdatedBy(String updatedBy) { this.updatedBy = updatedBy; - this.updateTime(); - } - - public LocalDateTime getCreatedAt() { - return this.createdAt; - } - - public void setCreatedAt(LocalDateTime createdAt) { - this.createdAt = createdAt; + updateTime(); } public LocalDateTime getUpdatedAt() { + if (this.lastUpdate.getWhen() == null || this.lastUpdate.getWho() == null || this.lastUpdate + .getWho().isEmpty()) { + setLastUpdate(); + } return updatedAt; } @@ -116,6 +123,7 @@ public abstract class ResourceCET<T> extends Resource<T> { @Override @JsonIgnore public ChangeInfo getCreation() { + return this.creation; } @@ -126,13 +134,6 @@ public abstract class ResourceCET<T> extends Resource<T> { return this.lastUpdate; } - @Override - public void updateTime() { - this.setUpdatedAt(LocalDateTime.now()); - this.getLastUpdate().setWhen(OffsetDateTime.now(ZoneOffset.UTC)); - this.getLastUpdate().setWho(this.updatedBy); - } - @Override public OffsetDateTime getCreationTime() { @@ -146,6 +147,22 @@ public abstract class ResourceCET<T> extends Resource<T> { private void resetCreation() { this.getCreation().setWho(createdBy); - this.getCreation().setWhen(DateTool.swissDateTime2offSetDate(createdAt)); + if (this.createdAt != null) { + this.getCreation().setWhen(DateTool.swissDateTime2offSetDate(createdAt)); + } else { + this.getCreation().setWhen(null); + } } + + @Override + public void updateTime() { + this.setUpdatedAt(LocalDateTime.now()); + setLastUpdate(); + } + + private void setLastUpdate() { + this.getLastUpdate().setWho(this.updatedBy); + this.getLastUpdate().setWhen(DateTool.swissDateTime2offSetDate(this.updatedAt)); + } + } diff --git a/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceDiverse.java b/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceDiverse.java index cf44b5220bd13a6f321a256d9b568b5492a129ae..bfe9f56608212eac2df06292b32d9f4da24c3c73 100644 --- a/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceDiverse.java +++ b/solidify-model/src/main/java/ch/unige/solidify/rest/ResourceDiverse.java @@ -1,12 +1,13 @@ package ch.unige.solidify.rest; -import ch.unige.solidify.listener.CacheListener; -import ch.unige.solidify.model.ChangeInfo; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import javax.persistence.EntityListeners; import javax.persistence.MappedSuperclass; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; + +import ch.unige.solidify.listener.CacheListener; +import ch.unige.solidify.model.ChangeInfo; /** * For the existed tables, the name of historical columns (creationWhen/who lastUpdateWhen/who) are not normalized. @@ -15,7 +16,7 @@ import java.time.ZoneOffset; * This class allows his subclass to define historical columns and set ResId from EntityId(entity primary key) */ @MappedSuperclass -@EntityListeners({CacheListener.class}) +@EntityListeners({ CacheListener.class }) public abstract class ResourceDiverse<T> extends Resource<T> { @Override @@ -39,10 +40,11 @@ public abstract class ResourceDiverse<T> extends Resource<T> { public abstract ChangeInfo getLastUpdate(); - public void updateTime() { - if (this.getLastUpdate() != null) { - this.getLastUpdate().setWhen(OffsetDateTime.now(ZoneOffset.UTC)); + public String getCreatedBy() { + if (this.getCreation() == null) { + return null; } + return this.getCreation().getWho(); } public OffsetDateTime getCreationTime() { @@ -52,39 +54,39 @@ public abstract class ResourceDiverse<T> extends Resource<T> { return this.getCreation().getWhen(); } - public OffsetDateTime getUpdateTime() { + public String getUpdatedBy() { if (this.getLastUpdate() == null) { return null; } - return this.getLastUpdate().getWhen(); + return this.getLastUpdate().getWho(); } - public String getCreatedBy() { - if (this.getCreation() == null) { + public OffsetDateTime getUpdateTime() { + if (this.getLastUpdate() == null) { return null; } - return this.getCreation().getWho(); + return this.getLastUpdate().getWhen(); } public void setCreatedBy(String createdBy) { if (this.getCreation() != null) { this.getCreation().setWho(createdBy); - this.updateTime(); + if (this.getCreation().getWhen() == null) { + this.getCreation().setWhen(OffsetDateTime.now(ZoneOffset.UTC)); + } } } - public String getUpdatedBy() { - if (this.getLastUpdate() == null) { - return null; - } - return this.getLastUpdate().getWho(); - } - public void setUpdatedBy(String updatedBy) { if (this.getLastUpdate() != null) { this.getLastUpdate().setWho(updatedBy); - this.updateTime(); } + updateTime(); } + public void updateTime() { + if (this.getLastUpdate() != null) { + this.getLastUpdate().setWhen(OffsetDateTime.now(ZoneOffset.UTC)); + } + } } diff --git a/solidify-model/src/main/java/ch/unige/solidify/specification/SearchSpecification.java b/solidify-model/src/main/java/ch/unige/solidify/specification/SearchSpecification.java index cd2249f82c54fd42df8c7775a283adea6be56ea9..98a82d334cc355cd228c2ed3760b0f6951811a0d 100644 --- a/solidify-model/src/main/java/ch/unige/solidify/specification/SearchSpecification.java +++ b/solidify-model/src/main/java/ch/unige/solidify/specification/SearchSpecification.java @@ -1,23 +1,31 @@ package ch.unige.solidify.specification; -import ch.unige.solidify.util.SearchCriteria; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.util.StringUtils; +import static ch.unige.solidify.util.SearchOperation.BETWEEN; -import javax.persistence.criteria.*; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.OffsetDateTime; -import static ch.unige.solidify.util.SearchOperation.BETWEEN; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.util.StringUtils; + +import ch.unige.solidify.util.SearchCriteria; /** * Specification generated with a SearchCriteria. - * @see ch.unige.solidify.util.SearchCriteria + * * @param <T> + * @see ch.unige.solidify.util.SearchCriteria */ public abstract class SearchSpecification<T> implements Specification<T> { private static final Logger log = LoggerFactory.getLogger(SearchSpecification.class); @@ -83,7 +91,8 @@ public abstract class SearchSpecification<T> implements Specification<T> { return builder.lessThan(fieldPath, (Comparable) criteriaValue); case STARTS_WITH: - if (!isString(fieldType)) return null; + if (!isString(fieldType)) + return null; if (criteria.isCaseInsensitive() && isString(fieldType)) { return builder.like( builder.lower(fieldPath), @@ -110,6 +119,13 @@ public abstract class SearchSpecification<T> implements Specification<T> { } return builder.like((Expression<String>) fieldPath, "%" + criteria.getValue() + "%"); + case ORACLE_CONTAINS: + Expression<Integer> exp = + builder.function("CONTAINS", Integer.class, fieldPath, + builder.literal(criteria.getValue().toString()), + builder.literal(1)); + return (builder.gt(exp, 0)); + case GREATER_EQUAL: if (criteria.isCaseInsensitive() && isString(fieldType)) { return builder.greaterThanOrEqualTo( @@ -119,7 +135,6 @@ public abstract class SearchSpecification<T> implements Specification<T> { } return builder.greaterThanOrEqualTo(fieldPath, (Comparable) criteriaValue); - case LESS_EQUAL: if (criteria.isCaseInsensitive() && isString(fieldType)) { return builder.lessThanOrEqualTo( @@ -164,7 +179,7 @@ public abstract class SearchSpecification<T> implements Specification<T> { String[] values = StringUtils.split((String) inputValue, "_"); Object first = convertString2Object(fieldType, values[0]); Object second = convertString2Object(fieldType, values[1]); - Object[] o = {first, second}; + Object[] o = { first, second }; return o; } @@ -174,6 +189,11 @@ public abstract class SearchSpecification<T> implements Specification<T> { return new BigDecimal((String) inputValue); } + //Test boolean + if (Boolean.class.isAssignableFrom(fieldType) || boolean.class.isAssignableFrom(fieldType)) { + return Boolean.parseBoolean((String) inputValue); + } + //Obtains an instance of LocalDate from a text string such as "2016-08-16" //The string must represent a valid date-time and is parsed using DateTimeFormatter.ISO_LOCAL_DATE. if (LocalDate.class.isAssignableFrom(fieldType)) { diff --git a/solidify-model/src/main/java/ch/unige/solidify/util/SearchOperation.java b/solidify-model/src/main/java/ch/unige/solidify/util/SearchOperation.java index 94713318e8662e29ea6e3661aa5b641b01b5f7bb..a1b11081591407b59ff48ceab9630ee555be12cb 100644 --- a/solidify-model/src/main/java/ch/unige/solidify/util/SearchOperation.java +++ b/solidify-model/src/main/java/ch/unige/solidify/util/SearchOperation.java @@ -7,10 +7,10 @@ package ch.unige.solidify.util; */ public enum SearchOperation { EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, CONTAINS, STARTS_WITH, ENDS_WITH, GREATER_EQUAL, - LESS_EQUAL, BETWEEN; + LESS_EQUAL, BETWEEN, ORACLE_CONTAINS; protected static final String[] OPERATION_SET = - {":", "!", ">", "<", "~", "¬", "§", "≥", "≤", "∞"}; + { ":", "!", ">", "<", "~", "¬", "§", "≥", "≤", "∞", "¢" }; public static final String OR_PREDICATE_FLAG = "any"; public static final String CASE_INSENSITIVE_FLAG = "i"; @@ -36,6 +36,8 @@ public enum SearchOperation { return LESS_EQUAL; case "∞": return BETWEEN; + case "¢": + return ORACLE_CONTAINS; default: return null; } diff --git a/solidify-model/src/main/java/ch/unige/solidify/util/StringParserTool.java b/solidify-model/src/main/java/ch/unige/solidify/util/StringParserTool.java index 054cc6deb498c43a166ed07ff283637357d099e8..6b59e97e49073042e00dd5cb7f601e5eddd98852 100644 --- a/solidify-model/src/main/java/ch/unige/solidify/util/StringParserTool.java +++ b/solidify-model/src/main/java/ch/unige/solidify/util/StringParserTool.java @@ -1,5 +1,6 @@ package ch.unige.solidify.util; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; @@ -7,11 +8,17 @@ import java.util.regex.Pattern; public class StringParserTool { - - public static List<SearchCriteria> parseSearchString(String search) { - if (search == null || search.trim().isEmpty()) { + public static List<SearchCriteria> parseSearchString(String searchinput) { + if (searchinput == null || searchinput.trim().isEmpty()) { return null; } + String search = null; + try { + search = java.net.URLDecoder.decode(searchinput, StandardCharsets.UTF_8.name()); + } catch (Exception e) { + search = searchinput; + } + String delim = ","; String regex = "(?<!\\\\)" + Pattern.quote(delim); String[] searchList = search.split(regex); diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/ModelTestSuite.java b/solidify-model/src/test/java/ch/unige/solidify/test/ModelTestSuite.java index 8aea130762efcc03c66d39183b33a0cffa5ac047..f976c699201605d074740e07608abbd5e369b75d 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/ModelTestSuite.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/ModelTestSuite.java @@ -1,22 +1,26 @@ package ch.unige.solidify.test; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + import ch.unige.solidify.test.specification.ResourceCETTest; -import ch.unige.solidify.test.specification.ResourceTest; +import ch.unige.solidify.test.specification.ResourceDiversTest; +import ch.unige.solidify.test.specification.ResourceLegacyTest; import ch.unige.solidify.test.specification.SearchSpecificationTest; import ch.unige.solidify.test.util.ChecksumTest; import ch.unige.solidify.test.util.StringCipherToolsTest; import ch.unige.solidify.test.util.StringParserToolTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses(value = { - ResourceTest.class, + ResourceLegacyTest.class, SearchSpecificationTest.class, ChecksumTest.class, StringParserToolTest.class, ResourceCETTest.class, + ResourceDiversTest.class, + ResourceLegacyTest.class, StringCipherToolsTest.class }) public class ModelTestSuite { diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceCETTest.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceCETTest.java index 65d260968e9e69e070d292d63f81d6c5f6c408d0..655d6fb940651b6fb59b94c61827d7f376922b61 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceCETTest.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceCETTest.java @@ -1,8 +1,11 @@ package ch.unige.solidify.test.specification; -import ch.unige.solidify.test.config.MockUserJpaConfig; -import ch.unige.solidify.test.specification.dao.EntityCETMock; -import ch.unige.solidify.test.specification.dao.EntityCetMockRepository; +import java.util.Optional; + +import javax.annotation.Resource; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -11,16 +14,19 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import javax.annotation.Resource; -import java.util.Optional; +import ch.unige.solidify.test.config.MockUserJpaConfig; +import ch.unige.solidify.test.specification.dao.EntityCetMockRepository; +import ch.unige.solidify.test.specification.model.EntityCETMock; @RunWith(SpringRunner.class) @DataJpaTest -@ContextConfiguration(classes = {MockUserJpaConfig.class}) +@ContextConfiguration(classes = { MockUserJpaConfig.class }) public class ResourceCETTest { @Resource private EntityCetMockRepository entityDefaultMockRepository; + @PersistenceContext + private EntityManager entityManager; @Before public void setup() { @@ -32,7 +38,6 @@ public class ResourceCETTest { entityDefaultMockRepository.save(entity); } - public void Test_insert_metaData() { Optional<EntityCETMock> entity2 = entityDefaultMockRepository.findById("1"); @@ -42,14 +47,29 @@ public class ResourceCETTest { } @Test - public void Test_update() { + public void Test_update() throws InterruptedException { Optional<EntityCETMock> entity = entityDefaultMockRepository.findById("1"); - EntityCETMock entityMock = entity.get(); - entityMock.setLabel("changed"); - entityMock.setUpdatedBy("new"); - entityDefaultMockRepository.save(entityMock); - Optional<EntityCETMock> entity2 = entityDefaultMockRepository.findById("1"); - Assert.assertEquals("changed", entity2.get().getLabel()); + EntityCETMock entityCetOriginal = entity.get(); + entityManager.detach(entityCetOriginal); + //add 5 ms between findbyId and update call to guarantee that the updated time is different. + Thread.currentThread().sleep(5); + EntityCETMock newEntity = new EntityCETMock(); + newEntity.setEntityId(entityCetOriginal.getEntityId()); + newEntity.setLabel("changed"); + newEntity.update(entityCetOriginal); + newEntity.setUpdatedBy("new"); + entityDefaultMockRepository.save(newEntity); + entityManager.detach(newEntity); + Optional<EntityCETMock> entityAfterUpdate = entityDefaultMockRepository.findById("1"); + //update meta-info must Be changed + Assert + .assertNotEquals(entityCetOriginal.getUpdatedAt(), entityAfterUpdate.get().getUpdatedAt()); + Assert + .assertNotEquals(entityCetOriginal.getUpdatedBy(), entityAfterUpdate.get().getUpdatedBy()); + Assert.assertEquals("changed", entityAfterUpdate.get().getLabel()); + //creation meta-information must not be changed + Assert.assertEquals(entityCetOriginal.getCreatedAt(), entityAfterUpdate.get().getCreatedAt()); + Assert.assertEquals(entityCetOriginal.getCreatedBy(), entityAfterUpdate.get().getCreatedBy()); } } diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceDiversTest.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceDiversTest.java new file mode 100644 index 0000000000000000000000000000000000000000..138969361b75203bd1894921b9c0b49d48c9c13e --- /dev/null +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceDiversTest.java @@ -0,0 +1,80 @@ +package ch.unige.solidify.test.specification; + +import java.time.OffsetDateTime; +import java.util.Optional; + +import javax.annotation.Resource; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import ch.unige.solidify.test.config.MockUserJpaConfig; +import ch.unige.solidify.test.specification.dao.EntityDiverMockRepository; +import ch.unige.solidify.test.specification.model.EntityDiverMock; + +@RunWith(SpringRunner.class) +@DataJpaTest +@ContextConfiguration(classes = { MockUserJpaConfig.class }) +public class ResourceDiversTest { + @Resource + private EntityDiverMockRepository entityDiverMockRepository; + @PersistenceContext + private EntityManager entityManager; + @Before + + public void setup() { + EntityDiverMock entity = new EntityDiverMock(); + entity.setEntityId("1"); + entity.setLabel("first"); + entity.setCreatedBy("initUser"); + entity.setUpdatedBy("initUser"); + entityDiverMockRepository.save(entity); + } + + @Test + public void Test_insert_metaData() { + Optional<EntityDiverMock> entity2 = entityDiverMockRepository.findById("1"); + Assert.assertNull(entity2.get().getCreationTime()); + Assert.assertNotNull(entity2.get().getUpdateTime()); + } + + @Test + public void Test_update() throws InterruptedException { + Optional<EntityDiverMock> entity = entityDiverMockRepository.findById("1"); + EntityDiverMock entityOriginal = entity.get(); + entityManager.detach(entityOriginal); + //add 5 ms between findbyId and update call to guarantee that the updated time is different. + Thread.currentThread().sleep(5); + EntityDiverMock newEntity = new EntityDiverMock(); + newEntity.setEntityId(entityOriginal.getEntityId()); + newEntity.setLabel("changed"); + newEntity.update(entityOriginal); + newEntity.setUpdatedBy("new"); + entityDiverMockRepository.save(newEntity); + + //label and updated by is changed + Assert.assertNotEquals(entityOriginal.getLabel(), newEntity.getLabel()); + Assert.assertNotEquals(entityOriginal.getUpdateTime(), newEntity.getUpdateTime()); + Assert.assertNotEquals(entityOriginal.getUpdatedBy(), newEntity.getUpdatedBy()); + + //NO creation meta-information + Assert.assertNull(newEntity.getCreationTime()); + Assert.assertNull(newEntity.getCreatedBy()); + + } + + @Test + public void Test_delete() { + entityDiverMockRepository.deleteById("1"); + Optional<EntityDiverMock> entity2 = entityDiverMockRepository.findById("1"); + Assert.assertFalse(entity2.isPresent()); + } +} + diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceLegacyTest.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceLegacyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..409a51409b0d3e5d235ef0c71eb54607519beaa2 --- /dev/null +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceLegacyTest.java @@ -0,0 +1,83 @@ +package ch.unige.solidify.test.specification; + +import java.util.Optional; + +import javax.annotation.Resource; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import ch.unige.solidify.test.config.MockUserJpaConfig; +import ch.unige.solidify.test.specification.dao.EntityLegacyMockRepository; +import ch.unige.solidify.test.specification.model.EntityLegacyMock; + +@RunWith(SpringRunner.class) +@DataJpaTest +@ContextConfiguration(classes = { MockUserJpaConfig.class }) +public class ResourceLegacyTest { + @Resource + private EntityLegacyMockRepository entityMockRepository; + @PersistenceContext + private EntityManager entityManager; + + @Before + public void setup() { + EntityLegacyMock entity = new EntityLegacyMock(); + entity.setEntityId("1"); + entity.setLabel("first"); + entity.setCreatedBy("initUser"); + entity.setUpdatedBy("initUser"); + entityMockRepository.save(entity); + Assert.assertNotNull(entity.getCreationTime()); + Assert.assertNotNull(entity.getUpdatedBy()); + } + + @Test + public void Test_delete() { + entityMockRepository.deleteById("1"); + Optional<EntityLegacyMock> entity2 = entityMockRepository.findById("1"); + Assert.assertFalse(entity2.isPresent()); + } + + @Test + public void Test_insert_metaData() { + Optional<EntityLegacyMock> entity2 = entityMockRepository.findById("1"); + Assert.assertNotNull(entity2.get().getCreationTime()); + Assert.assertNotNull(entity2.get().getUpdateTime()); + } + + @Test + public void Test_update() throws InterruptedException { + Optional<EntityLegacyMock> entity = entityMockRepository.findById("1"); + EntityLegacyMock entityCetOriginal = entity.get(); + entityManager.detach(entityCetOriginal); + //add 5 ms between findbyId and update call to guarantee that the updated time is different. + Thread.currentThread().sleep(5); + EntityLegacyMock newEntity = new EntityLegacyMock(); + newEntity.setEntityId(entityCetOriginal.getEntityId()); + newEntity.setLabel("changed"); + newEntity.update(entityCetOriginal); + newEntity.setUpdatedBy("new"); + entityMockRepository.save(newEntity); + //label and updated by is changed + Assert.assertNotEquals(entityCetOriginal.getLabel(), newEntity.getLabel()); + Assert.assertNotEquals(entityCetOriginal.getUpdateTime(), newEntity.getUpdateTime()); + Assert.assertNotEquals(entityCetOriginal.getUpdatedBy(), newEntity.getUpdatedBy()); + //creation meta-information must not be changed + Assert.assertEquals(entityCetOriginal.getCreationTime(), newEntity.getCreationTime()); + Assert.assertEquals(entityCetOriginal.getCreatedBy(), newEntity.getCreatedBy()); + Assert + .assertEquals(entityCetOriginal.getCreation().getWhen(), newEntity.getCreation().getWhen()); + Assert + .assertEquals(entityCetOriginal.getCreation().getWhen(), newEntity.getCreation().getWhen()); + + } + +} diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceTest.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceTest.java deleted file mode 100644 index 31201ca58bbf67ddb8d7ece97efa357b0a31b074..0000000000000000000000000000000000000000 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/ResourceTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package ch.unige.solidify.test.specification; - -import ch.unige.solidify.test.config.MockUserJpaConfig; -import ch.unige.solidify.test.specification.dao.EntityMock; -import ch.unige.solidify.test.specification.dao.EntityMockRepository; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -import javax.annotation.Resource; -import java.time.OffsetDateTime; -import java.util.Optional; - -@RunWith(SpringRunner.class) -@DataJpaTest -@ContextConfiguration(classes = {MockUserJpaConfig.class}) -public class ResourceTest { - @Resource - private EntityMockRepository entityMockRepository; - - @Before - - public void setup() { - EntityMock entity = new EntityMock(); - entity.setEntityId("1"); - entity.setLabel("first"); - entity.setCreatedBy("unitTEST"); - entityMockRepository.save(entity); - } - - @Test - public void Test_insert_metaData() { - - Optional<EntityMock> entity2 = entityMockRepository.findById("1"); - Assert.assertNotNull(entity2.get().getCreationTime()); - Assert.assertNotNull(entity2.get().getUpdateTime()); - } - - @Test - public void Test_update() { - Optional<EntityMock> entity = entityMockRepository.findById("1"); - EntityMock entityMock = entity.get(); - OffsetDateTime oldUpdateAt = entityMock.getUpdateTime(); - entityMock.setLabel("changed"); - entityMockRepository.save(entityMock); - Optional<EntityMock> entity2 = entityMockRepository.findById("1"); - Assert.assertEquals("changed", entity2.get().getLabel()); - } - - @Test - public void Test_delete() { - entityMockRepository.deleteById("1"); - Optional<EntityMock> entity2 = entityMockRepository.findById("1"); - Assert.assertFalse(entity2.isPresent()); - } -} diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/SearchSpecificationTest.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/SearchSpecificationTest.java index 2de10705240db3fd626a833bda03e17ac0c114e1..867040346d7fd35203b3f3ba52224a4a589859e2 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/SearchSpecificationTest.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/SearchSpecificationTest.java @@ -1,9 +1,15 @@ package ch.unige.solidify.test.specification; -import ch.unige.solidify.test.config.MockUserJpaConfig; -import ch.unige.solidify.test.specification.dao.*; -import ch.unige.solidify.util.SearchCriteria; -import ch.unige.solidify.util.SearchOperation; +import static org.hamcrest.collection.IsIn.isIn; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.util.List; + +import javax.annotation.Resource; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -13,18 +19,18 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import javax.annotation.Resource; -import java.math.BigDecimal; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.OffsetDateTime; -import java.util.List; - -import static org.hamcrest.collection.IsIn.isIn; +import ch.unige.solidify.test.config.MockUserJpaConfig; +import ch.unige.solidify.test.specification.model.MockUser; +import ch.unige.solidify.test.specification.model.MockUserInfo; +import ch.unige.solidify.test.specification.dao.MockUserInfoRepository; +import ch.unige.solidify.test.specification.dao.MockUserRepository; +import ch.unige.solidify.test.specification.dao.MockUserSearchSpecification; +import ch.unige.solidify.util.SearchCriteria; +import ch.unige.solidify.util.SearchOperation; @RunWith(SpringRunner.class) @DataJpaTest -@ContextConfiguration(classes = {MockUserJpaConfig.class}) +@ContextConfiguration(classes = { MockUserJpaConfig.class }) public class SearchSpecificationTest { @Resource @@ -41,9 +47,9 @@ public class SearchSpecificationTest { @Before public void setup() { - MockUserInfo info = new MockUserInfo("1", "John info"); - MockUserInfo info2 = new MockUserInfo("2", "Doe info"); - MockUserInfo info3 = new MockUserInfo("3", "Jo info"); + MockUserInfo info = new MockUserInfo("1", "John info", true); + MockUserInfo info2 = new MockUserInfo("2", "Doe info", false); + MockUserInfo info3 = new MockUserInfo("3", "Jo info", true); mockUserInfoRepository.save(info); mockUserInfoRepository.save(info2); mockUserInfoRepository.save(info3); @@ -89,7 +95,6 @@ public class SearchSpecificationTest { Assert.assertEquals("john", userFound.getName()); } - //Test GREATER THAN OR EQUAL with Long field type @Test public void LongSearch_greateerEquals_thenCorrect() { @@ -114,7 +119,6 @@ public class SearchSpecificationTest { Assert.assertEquals("john", userFound.getName()); } - //Test BETWEEN with LocaledateTime field type @Test public void LocaledateTimeSearch_between_thenCorrect() { @@ -161,6 +165,17 @@ public class SearchSpecificationTest { Assert.assertEquals("Doe info", userFound.getUserInfo().getInfo()); } + @Test + public void searchOne2OneEntity_ByBooleanValue_thenCorrect() { + SearchCriteria criteria1 = + new SearchCriteria("userInfo.adminuser", SearchOperation.EQUALITY, + "true"); + List<MockUser> results = + userRepository.findAll(Specification.where(new MockUserSearchSpecification(criteria1))); + Assert.assertEquals(2, results.size()); + MockUser userFound = results.get(0); + Assert.assertEquals(true, userFound.getUserInfo().isAdminuser()); + } @Test public void givenNameSearch_ByEqual_thenCorrect() { @@ -213,5 +228,4 @@ public class SearchSpecificationTest { Assert.assertEquals("john", userFound.getName()); } - } diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityCetMockRepository.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityCetMockRepository.java index e743dfb96ab754bd1da6a3ec763c8aa4b5819c24..c6f1af74358561fcc871f10e192b81e9b4b66716 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityCetMockRepository.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityCetMockRepository.java @@ -2,6 +2,7 @@ package ch.unige.solidify.test.specification.dao; import org.springframework.data.jpa.repository.JpaRepository; +import ch.unige.solidify.test.specification.model.EntityCETMock; public interface EntityCetMockRepository extends JpaRepository<EntityCETMock, String>{ diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityDiverMockRepository.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityDiverMockRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..406ba347e82196850854348fcb37cfbe5e60c932 --- /dev/null +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityDiverMockRepository.java @@ -0,0 +1,8 @@ +package ch.unige.solidify.test.specification.dao; + +import org.springframework.data.jpa.repository.JpaRepository; + +import ch.unige.solidify.test.specification.model.EntityDiverMock; + +public interface EntityDiverMockRepository extends JpaRepository<EntityDiverMock, String> { +} diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityLegacyMockRepository.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityLegacyMockRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..ca14dc6ebb2834d7792d74efd797ca143cd116cc --- /dev/null +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityLegacyMockRepository.java @@ -0,0 +1,10 @@ +package ch.unige.solidify.test.specification.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +import ch.unige.solidify.test.specification.model.EntityLegacyMock; + +public interface EntityLegacyMockRepository + extends JpaRepository<EntityLegacyMock, String>, JpaSpecificationExecutor<EntityLegacyMock> { +} diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMockRepository.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMockRepository.java deleted file mode 100644 index e8f162ed5b023841966698c81430af1b983b2103..0000000000000000000000000000000000000000 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMockRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package ch.unige.solidify.test.specification.dao; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -public interface EntityMockRepository extends JpaRepository<EntityMock, String>, JpaSpecificationExecutor<EntityMock> { -} diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMockSpecification.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMockSpecification.java index 7b1b8216475ef873ef552481b2b943609aa64306..169ff45efa86cb4893d1df8ceda070353f3aa5bb 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMockSpecification.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMockSpecification.java @@ -9,15 +9,17 @@ import javax.persistence.criteria.Root; import java.util.ArrayList; import java.util.List; -public class EntityMockSpecification implements Specification<EntityMock> { - private final EntityMock criteria; +import ch.unige.solidify.test.specification.model.EntityLegacyMock; - public EntityMockSpecification(EntityMock criteria) { +public class EntityMockSpecification implements Specification<EntityLegacyMock> { + private final EntityLegacyMock criteria; + + public EntityMockSpecification(EntityLegacyMock criteria) { this.criteria = criteria; } @Override - public Predicate toPredicate(Root<EntityMock> root, CriteriaQuery<?> criteriaQuery, + public Predicate toPredicate(Root<EntityLegacyMock> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { List<Predicate> listPredicate = new ArrayList<>(); if (criteria.getLabel() != null) { diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserInfoRepository.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserInfoRepository.java index 8c67227339bdcd79f15e0b677f6df309b7b3d845..ecf115d11d5e9583b0a4900722823af811b061a5 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserInfoRepository.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserInfoRepository.java @@ -2,5 +2,7 @@ package ch.unige.solidify.test.specification.dao; import org.springframework.data.jpa.repository.JpaRepository; +import ch.unige.solidify.test.specification.model.MockUserInfo; + public interface MockUserInfoRepository extends JpaRepository<MockUserInfo, Long> { } diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserRepository.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserRepository.java index a9a0efbd8475ffd60edbd87a0af550bb9ff460b6..edecfb897157ca93c2bbc4e3a4135e579fca518e 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserRepository.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserRepository.java @@ -3,6 +3,8 @@ package ch.unige.solidify.test.specification.dao; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import ch.unige.solidify.test.specification.model.MockUser; + public interface MockUserRepository extends JpaRepository<MockUser, Long>, JpaSpecificationExecutor<MockUser> { diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserSearchSpecification.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserSearchSpecification.java index c2ee9c4fbf1b55e5f21d43ce1ec8362fe1ac30b8..7659c4e68bc7f889cf5ccfe4c551d332fa48f54c 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserSearchSpecification.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserSearchSpecification.java @@ -1,6 +1,7 @@ package ch.unige.solidify.test.specification.dao; import ch.unige.solidify.specification.SearchSpecification; +import ch.unige.solidify.test.specification.model.MockUser; import ch.unige.solidify.util.SearchCriteria; public class MockUserSearchSpecification extends SearchSpecification<MockUser> { diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityCETMock.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityCETMock.java similarity index 88% rename from solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityCETMock.java rename to solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityCETMock.java index cefc277c54c8e20e5dfa752d7f5ce1d0163133b0..26a5fce2d6601fdadee31640b959f87d479550bb 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityCETMock.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityCETMock.java @@ -1,6 +1,8 @@ -package ch.unige.solidify.test.specification.dao; +package ch.unige.solidify.test.specification.model; import ch.unige.solidify.rest.ResourceCET; +import ch.unige.solidify.util.ReflectionTool; + import org.springframework.data.jpa.domain.Specification; import javax.persistence.Column; @@ -32,7 +34,7 @@ public class EntityCETMock extends ResourceCET<EntityCETMock> { } public void setLabel(String label) { - this.label = label; + this.setProperty(ReflectionTool.getCurrentSetterVariableName(), label); } @Override diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityDiverMock.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityDiverMock.java new file mode 100644 index 0000000000000000000000000000000000000000..d1bc242b7d2af2ffda7dec17222e9a8befd06363 --- /dev/null +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityDiverMock.java @@ -0,0 +1,89 @@ +package ch.unige.solidify.test.specification.model; + +import javax.persistence.AttributeOverride; +import javax.persistence.AttributeOverrides; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.validation.Valid; + +import org.springframework.data.jpa.domain.Specification; + +import ch.unige.solidify.model.ChangeInfo; +import ch.unige.solidify.rest.ResourceDiverse; +import ch.unige.solidify.util.ReflectionTool; + +@Entity +@Table(name = "EntityDiversMock") +public class EntityDiverMock extends ResourceDiverse<EntityDiverMock> { + + @AttributeOverrides({ @AttributeOverride(name = "when", column = @Column(name = "d_update")), + @AttributeOverride(name = "who", column = @Column(name = "id_update")) }) + @Embedded + @Valid + protected ChangeInfo lastUpdate = new ChangeInfo(); + + + @Override + public ChangeInfo getCreation() { + return null; + } + + @Override + public ChangeInfo getLastUpdate() { + return lastUpdate; + } + + @Id + @Column(name = "id") + private String entityId; + + private String label; + + @Override + public String getEntityId() { + return this.entityId; + } + + + + public void setEntityId(String entityId) { + this.entityId = entityId; + } + + @Override + public Specification<EntityDiverMock> getSpecification() { + return null; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.setProperty(ReflectionTool.getCurrentSetterVariableName(), label); + } + + @Override + public String toString() { + return "EntityLegacyMock{" + + "entityId='" + entityId + '\'' + + ", label='" + label + '\'' + + ", creation=" + getCreation() + + ", lastUpdate=" + getLastUpdate() + + ", dirtyFields=" + dirtyFields + + '}'; + } + + @Override + public void init() { + + } + + @Override + public String managedBy() { + return null; + } +} diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMock.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityLegacyMock.java similarity index 53% rename from solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMock.java rename to solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityLegacyMock.java index a4f5fcf70a998f33cb161a56e3d10dae03b97cad..988af18e503cae9677534803e6ba16d10cc5c705 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/EntityMock.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/EntityLegacyMock.java @@ -1,38 +1,36 @@ -package ch.unige.solidify.test.specification.dao; - -import ch.unige.solidify.rest.ResourceLegacy; -import org.springframework.data.jpa.domain.Specification; +package ch.unige.solidify.test.specification.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; -@Entity -@Table(name = "EntityMock") -public class EntityMock extends ResourceLegacy<EntityMock> { +import org.springframework.data.jpa.domain.Specification; + +import ch.unige.solidify.rest.ResourceLegacy; +import ch.unige.solidify.util.ReflectionTool; +@Entity +@Table(name = "EntityLegacyMock") +public class EntityLegacyMock extends ResourceLegacy<EntityLegacyMock> { @Id @Column(name = "id") private String entityId; - private String label; - @Override public String getEntityId() { return this.entityId; } - public void setEntityId(String entityId) { this.entityId = entityId; } @Override - public Specification<EntityMock> getSpecification() { + public Specification<EntityLegacyMock> getSpecification() { return null; } @@ -41,7 +39,18 @@ public class EntityMock extends ResourceLegacy<EntityMock> { } public void setLabel(String label) { - this.label = label; + this.setProperty(ReflectionTool.getCurrentSetterVariableName(), label); + } + + @Override + public String toString() { + return "EntityLegacyMock{" + + "entityId='" + entityId + '\'' + + ", label='" + label + '\'' + + ", creation=" + creation + + ", lastUpdate=" + lastUpdate + + ", dirtyFields=" + dirtyFields + + '}'; } @Override diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUser.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/MockUser.java similarity index 98% rename from solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUser.java rename to solidify-model/src/test/java/ch/unige/solidify/test/specification/model/MockUser.java index 792277894b645dc72024da35a3147e41ed840ca0..429fe95546fd210cc826f3590bbe59f7d618549b 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUser.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/MockUser.java @@ -1,4 +1,4 @@ -package ch.unige.solidify.test.specification.dao; +package ch.unige.solidify.test.specification.model; import javax.persistence.*; import java.math.BigDecimal; diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserInfo.java b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/MockUserInfo.java similarity index 61% rename from solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserInfo.java rename to solidify-model/src/test/java/ch/unige/solidify/test/specification/model/MockUserInfo.java index bc4bc274484904a034c33c24f81630882becedfb..ab8b1f817b39b79c1002a7fab6dde70eed029359 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/specification/dao/MockUserInfo.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/specification/model/MockUserInfo.java @@ -1,4 +1,4 @@ -package ch.unige.solidify.test.specification.dao; +package ch.unige.solidify.test.specification.model; import javax.persistence.Column; import javax.persistence.Entity; @@ -11,6 +11,8 @@ public class MockUserInfo { private String infoId; private String info; + private boolean adminuser; + public MockUserInfo() { super(); } @@ -20,6 +22,12 @@ public class MockUserInfo { this.info = info; } + public MockUserInfo(String id, String info, boolean isAdmin) { + this.infoId = id; + this.info = info; + this.adminuser = isAdmin; + } + public String getInfo() { return info; } @@ -28,7 +36,6 @@ public class MockUserInfo { this.info = info; } - public String getInfoId() { return infoId; } @@ -37,5 +44,12 @@ public class MockUserInfo { this.infoId = infoId; } + public boolean isAdminuser() { + return adminuser; + } + + public void setAdminuser(boolean adminuser) { + this.adminuser = adminuser; + } } diff --git a/solidify-model/src/test/java/ch/unige/solidify/test/util/StringParserToolTest.java b/solidify-model/src/test/java/ch/unige/solidify/test/util/StringParserToolTest.java index bd6142bccfd2f7a97d4c0f9b1ecbbc5195aba36f..5ce7225eccfe63d0cbc4cc0177c8291f02449bdf 100644 --- a/solidify-model/src/test/java/ch/unige/solidify/test/util/StringParserToolTest.java +++ b/solidify-model/src/test/java/ch/unige/solidify/test/util/StringParserToolTest.java @@ -1,16 +1,16 @@ package ch.unige.solidify.test.util; -import ch.unige.solidify.util.SearchCriteria; -import ch.unige.solidify.util.StringParserTool; +import java.io.UnsupportedEncodingException; +import java.util.List; + import org.junit.Assert; import org.junit.Test; -import java.util.List; - +import ch.unige.solidify.util.SearchCriteria; +import ch.unige.solidify.util.StringParserTool; public class StringParserToolTest { - @Test public void testString() { String search = "user.lastName:<w!.*\\\\,ang%,age≥30_60,i-my_test_9.is§this@gmail.com"; @@ -21,5 +21,16 @@ public class StringParserToolTest { } } + @Test + public void testStringWithEsacpecharacters() throws UnsupportedEncodingException { + String search = "statut%C2%ACA,isDomPers:true"; + System.out.println(search); + List<SearchCriteria> criterias = StringParserTool.parseSearchString(search); + Assert.assertEquals(2, criterias.size()); + for (SearchCriteria item : criterias) { + System.out.println(item); + } + } + }