From 353258ad684661cc309f12ea27f5779b71cca79a Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Wed, 2 Feb 2022 14:23:28 +0100 Subject: [PATCH 1/9] Implemented API interface of version1 and 2 --- apps/pom.xml | 1 + apps/scholexplorer-api/pom.xml | 45 +++++ .../dnetlib/scholix/api/MainApplication.java | 89 +++++++++ .../scholix/api/controller/DatasourceV1.java | 33 ++++ .../api/controller/LinkProviderV2.java | 35 ++++ .../api/controller/LinkPublisherV2.java | 51 +++++ .../api/controller/ScholixControllerV1.java | 84 +++++++++ .../api/controller/ScholixControllerV2.java | 56 ++++++ .../scholix/api/model/v1/LinkPublisher.java | 97 ++++++++++ .../scholix/api/model/v1/ScholixCreator.java | 102 ++++++++++ .../api/model/v1/ScholixIdentifier.java | 98 ++++++++++ .../scholix/api/model/v1/ScholixItem.java | 178 ++++++++++++++++++ .../scholix/api/model/v1/ScholixProvider.java | 106 +++++++++++ .../api/model/v1/ScholixRelationship.java | 119 ++++++++++++ .../scholix/api/model/v1/ScholixV1.java | 159 ++++++++++++++++ .../api/model/v2/LinkProviderType.java | 123 ++++++++++++ .../scholix/api/model/v2/PageResultType.java | 114 +++++++++++ .../api/model/v2/RelationshipType.java | 86 +++++++++ .../api/model/v2/ScholixCreatorType.java | 66 +++++++ .../api/model/v2/ScholixIdentifierType.java | 92 +++++++++ .../scholix/api/model/v2/ScholixItemType.java | 151 +++++++++++++++ .../api/model/v2/ScholixLinkProviderType.java | 67 +++++++ .../scholix/api/model/v2/ScholixType.java | 170 +++++++++++++++++ .../src/main/resources/application.properties | 48 +++++ .../src/main/resources/static/logo.png | Bin 0 -> 43773 bytes .../main/resources/static/new_swagger.html | 135 +++++++++++++ pom.xml | 3 +- 27 files changed, 2307 insertions(+), 1 deletion(-) create mode 100644 apps/scholexplorer-api/pom.xml create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/LinkPublisher.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/PageResultType.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java create mode 100644 apps/scholexplorer-api/src/main/resources/application.properties create mode 100644 apps/scholexplorer-api/src/main/resources/static/logo.png create mode 100644 apps/scholexplorer-api/src/main/resources/static/new_swagger.html diff --git a/apps/pom.xml b/apps/pom.xml index 3b388dd8..5b589921 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -16,6 +16,7 @@ dhp-broker-public-application dhp-mdstore-manager dnet-orgs-database-application + scholexplorer-api diff --git a/apps/scholexplorer-api/pom.xml b/apps/scholexplorer-api/pom.xml new file mode 100644 index 00000000..93fc45b7 --- /dev/null +++ b/apps/scholexplorer-api/pom.xml @@ -0,0 +1,45 @@ + + + + eu.dnetlib.dhp + apps + 3.2.3-SNAPSHOT + ../pom.xml + + + 4.0.0 + jar + scholexplorer-api + + + + io.springfox + springfox-bean-validators + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + + org.apache.maven.plugins + maven-help-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java new file mode 100644 index 00000000..b7761633 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java @@ -0,0 +1,89 @@ +package eu.dnetlib.scholix.api; + +import eu.dnetlib.common.app.AbstractDnetApp; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@SpringBootApplication +@EnableSwagger2 +@EnableCaching +@EnableScheduling +//@EntityScan("eu.dnetlib.scholix.api.controller") +public class MainApplication extends AbstractDnetApp { + + @Value("${dhp.swagger.api.host}") + private String swaggetHost; + + @Value("${dhp.swagger.api.basePath}") + private String swaggerPath; + + final String descriptionAPI = "

\"ScholeXplorer\"

" + + "The Scholix Swagger API allows clients to run REST queries over the Scholexplorer index in order to fetch links matching given criteria. In the current version, clients can search for:" + + ""; + + public static void main(final String[] args) { + SpringApplication.run(MainApplication.class, args); + } + + @Override + protected void configSwagger(final Docket docket) { + docket + .host(swaggetHost) + .pathMapping(swaggerPath) + .groupName("Scholexplorer V1") + .select() + .apis(RequestHandlerSelectors.any()) + .paths(p -> p.startsWith("/v1")) + .build() + .apiInfo(new ApiInfoBuilder() + .title("Scholexplorer API V1.0") + .description(descriptionAPI) + .version("1.0") + .contact(ApiInfo.DEFAULT_CONTACT) + .license("Apache 2.0") + .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0") + .build()); + } + + + + @Bean (name = "SpringDOcketv2") + public Docket v2Docket() { + + + final Docket docket = new Docket(DocumentationType.SWAGGER_2); + + docket + .host(swaggetHost) + .pathMapping(swaggerPath) + .groupName("Scholexplorer V2") + .select() + .apis(RequestHandlerSelectors.any()) + .paths(p -> p.startsWith("/v2")) + .build() + .apiInfo(new ApiInfoBuilder() + .title("Scholexplorer API V2.0") + .description(descriptionAPI) + .version("2.0") + .contact(ApiInfo.DEFAULT_CONTACT) + .license("Apache 2.0") + .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0") + .build()); + + return docket; + } + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java new file mode 100644 index 00000000..007a6caf --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java @@ -0,0 +1,33 @@ +package eu.dnetlib.scholix.api.controller; + +import eu.dnetlib.common.controller.AbstractDnetController; +import eu.dnetlib.scholix.api.model.v1.LinkPublisher; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.List; + + +@RestController +@RequestMapping("/v1") +@Api(tags = { + "Datasources" +}) +public class DatasourceV1 extends AbstractDnetController { + + @Operation( + summary = "Get all Datasources", + description = "returns a list of all datasources") + @GetMapping("/v1/listDatasources") + public List getDatasources() { + return Arrays.asList( + new LinkPublisher().name("pippo").totalRelationships(30), + new LinkPublisher().name("pluto").totalRelationships(30), + new LinkPublisher().name("peppa").totalRelationships(30) + ); + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java new file mode 100644 index 00000000..3aa1514f --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java @@ -0,0 +1,35 @@ +package eu.dnetlib.scholix.api.controller; +import eu.dnetlib.scholix.api.model.v2.LinkProviderType; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.List; + +@RestController +@RequestMapping("/v2") +@Api(tags = { + "LinkProvider : Operation related to the Link Provider" +}) +public class LinkProviderV2 { + + @Operation( + summary = "Get all Link Providers", + description = "Return a list of link provider and relative number of relations") + @GetMapping("/LinkProvider") + public List getLinkProviders( + @Parameter(in = ParameterIn.QUERY, description = "Filter the link provider name") @RequestParam(required = false) String name + ) { + return Arrays.asList( + new LinkProviderType().name("pippo").totalRelationships(30), + new LinkProviderType().name("pluto").totalRelationships(30), + new LinkProviderType().name("peppa").totalRelationships(30) + ); + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java new file mode 100644 index 00000000..41883343 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java @@ -0,0 +1,51 @@ +package eu.dnetlib.scholix.api.controller; +import eu.dnetlib.scholix.api.model.v2.LinkProviderType; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.List; + +@RestController +@RequestMapping("/v2/LinkPublisher") +@Api(tags = { + "LinkPublisher : Operation related to the Link Publisher" +}) +public class LinkPublisherV2 { + + @Operation( + summary = "Get All Publishers that provide source object", + description = "Return a List of all Publishers that provide source objects in Scholix " + + "links and the total number of links where the source object comes from this publisher") + @GetMapping("/inSource") + public List getInSource( + @Parameter(in = ParameterIn.QUERY, description = "Filter the link publisher name") @RequestParam(required = false) String name + ) { + return Arrays.asList( + new LinkProviderType().name("pippo").totalRelationships(30), + new LinkProviderType().name("pluto").totalRelationships(30), + new LinkProviderType().name("peppa").totalRelationships(30) + ); + } + + @Operation( + summary = "Get All Publishers that provide target object", + description = "Return a List of all Publishers that provide source objects in Scholix " + + "links and the total number of links where the target object comes from this publisher") + @GetMapping("/inTarget") + public List getInTarget( + @Parameter(in = ParameterIn.QUERY, description = "Filter the link publisher name") @RequestParam(required = false) String name + ) { + return Arrays.asList( + new LinkProviderType().name("pippo").totalRelationships(30), + new LinkProviderType().name("pluto").totalRelationships(30), + new LinkProviderType().name("peppa").totalRelationships(30) + ); + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java new file mode 100644 index 00000000..b63d7c2f --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java @@ -0,0 +1,84 @@ +package eu.dnetlib.scholix.api.controller; + + +import eu.dnetlib.common.controller.AbstractDnetController; +import eu.dnetlib.scholix.api.model.v1.ScholixV1; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Schema; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; + + +@RestController +@RequestMapping("/v1") +@Api(tags = { + "Scholix" +}) +public class ScholixControllerV1 extends AbstractDnetController { + + @Operation( + summary = "Get all Scholix relation collected from a publisher", + description = "return a list of scholix object published from a specific publisher" + ) + @GetMapping("/linksFromPublisher") + public List linksFromPublisher( + @Parameter( + in = ParameterIn.QUERY, + description = "Filter Scholix relationships collected from a publisher", + schema = @Schema(), required = true) String publisher, + @Parameter(in = ParameterIn.QUERY, + description = "The page number") @RequestParam(required = false) Integer page + ) { + + return new ArrayList<>(); + } + + @Operation( + summary = "Get all Scholix relation collected from a datasource", + description = "return a list of scholix object collected from a specific datasource" + ) + @GetMapping("/linksFromDatasource") + public List linksFromDatasource( + @Parameter( + in = ParameterIn.QUERY, + description = "Filter Scholix relationships collected from a LinkProvider", + schema = @Schema()) @NotNull String datasource, + @Parameter(in = ParameterIn.QUERY, + description = "The page number") @RequestParam(required = false) Integer page + ) { + + return new ArrayList<>(); + } + + + @Operation( + summary = "Retrieve all scholix links from a persistent identifier", + description = "The linksFromPid endpoint returns a list of scholix object related from a specific persistent identifier" + ) + @GetMapping("/linksFromPid") + public List linksFromPid( + @Parameter(in = ParameterIn.QUERY, description = "persistent Identifier") @NotNull String pid, + @Parameter(in = ParameterIn.QUERY, description = "Persistent Identifier Type") @RequestParam(required = false) String pidType, + @Parameter(in = ParameterIn.QUERY, description = "typology target filter should be publication, dataset or unknown") @RequestParam(required = false) String typologyTarget, + @Parameter(in = ParameterIn.QUERY, description = "a datasource provenance filter of the target relation") @RequestParam(required = false) String datasourceTarget, + @Parameter(in = ParameterIn.QUERY, + description = "The page number") @RequestParam(required = false) Integer page + ) { + + return new ArrayList<>(); + } + + + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java new file mode 100644 index 00000000..ee5fef8a --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java @@ -0,0 +1,56 @@ +package eu.dnetlib.scholix.api.controller; + + +import eu.dnetlib.common.controller.AbstractDnetController; +import eu.dnetlib.scholix.api.model.v2.PageResultType; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.constraints.NotNull; +import java.util.Arrays; + +@RestController +@RequestMapping("/v2") +@Api(tags = { + "Links : Operation related to the Scholix Links" +}) +public class ScholixControllerV2 extends AbstractDnetController { + + @ApiOperation("Get Scholix Links") + @GetMapping("/Links") + public PageResultType links( + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships collected from a LinkProvider") String linkProvider, + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships having a target pid") String targetPid, + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships having a target pid type") String targetPidType, + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships having a target published in a Publisher named targetPublisher") String targetPublisher, + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships having a target type (literature, dataset, unknown)") String targetType, + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships having a source pid") String sourcePid, + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships having a source pid type") String sourcePidType, + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships having a source published in a Publisher named sourcePublisher") String sourcePublisher, + @Parameter(in = ParameterIn.QUERY, + description = "Filter Scholix relationships having a source type (literature, dataset, unknown)") String sourceType, + @Parameter(in = ParameterIn.QUERY, + description = "Filter scholix Links having collected after this date") String harvestedAfter, + @Parameter(in = ParameterIn.QUERY, + description = "select page of result") Integer page) { + + return new PageResultType(); + } + + + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/LinkPublisher.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/LinkPublisher.java new file mode 100644 index 00000000..ae1a1b63 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/LinkPublisher.java @@ -0,0 +1,97 @@ +package eu.dnetlib.scholix.api.model.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.util.Objects; + +public class LinkPublisher { + @NotBlank + @JsonProperty("name") + private String name = null; + + @NotBlank + @JsonProperty("totalRelationships") + private Integer totalRelationships = null; + + public LinkPublisher name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @Schema(description = "The Publisher Name") + + @Size(max=300) public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public LinkPublisher totalRelationships(Integer totalRelationships) { + this.totalRelationships = totalRelationships; + return this; + } + + /** + * Get totalRelationships + * @return totalRelationships + **/ + @Schema(description = "Total number of relationships that the publisher provides") + + public Integer getTotalRelationships() { + return totalRelationships; + } + + public void setTotalRelationships(Integer totalRelationships) { + this.totalRelationships = totalRelationships; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + LinkPublisher linkPublisher = (LinkPublisher) o; + return Objects.equals(this.name, linkPublisher.name) && + Objects.equals(this.totalRelationships, linkPublisher.totalRelationships); + } + + @Override + public int hashCode() { + return Objects.hash(name, totalRelationships); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class LinkPublisher {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" totalRelationships: ").append(toIndentedString(totalRelationships)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java new file mode 100644 index 00000000..97f571b1 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java @@ -0,0 +1,102 @@ +package eu.dnetlib.scholix.api.model.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class ScholixCreator { + + @JsonProperty("name") + private String name = null; + + @JsonProperty("identifier") + private List identifier = null; + + public ScholixCreator name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @Schema(required = true, description = "The name of the Object Creator") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ScholixCreator identifier(List identifier) { + this.identifier = identifier; + return this; + } + + public ScholixCreator addIdentifierItem(ScholixIdentifier identifierItem) { + if (this.identifier == null) { + this.identifier = new ArrayList(); + } + this.identifier.add(identifierItem); + return this; + } + + /** + * Get identifier + * @return identifier + **/ + @Schema(description = "A unique string that identifies the Object Creator") + public List getIdentifier() { + return identifier; + } + + public void setIdentifier(List identifier) { + this.identifier = identifier; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ScholixCreator ScholixCreator = (ScholixCreator) o; + return Objects.equals(this.name, ScholixCreator.name) && + Objects.equals(this.identifier, ScholixCreator.identifier); + } + + @Override + public int hashCode() { + return Objects.hash(name, identifier); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ScholixCreator {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" identifier: ").append(toIndentedString(identifier)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java new file mode 100644 index 00000000..49fb0be6 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java @@ -0,0 +1,98 @@ +package eu.dnetlib.scholix.api.model.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.Objects; + +public class ScholixIdentifier { + + @JsonProperty("identifier") + private String identifier = null; + + @JsonProperty("schema") + private String schema = null; + + + + public ScholixIdentifier Identifier(String ID) { + this.identifier = ID; + return this; + } + + /** + * Get ID + * @return ID + **/ + @Schema(description = "The value of the Identifier") + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public ScholixIdentifier Schema(String idScheme) { + this.schema = idScheme; + return this; + } + + /** + * Get the Schema + * @return Schema + **/ + @Schema(description = "The Schema URL of the identifier type") + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ScholixIdentifier identifierType = (ScholixIdentifier) o; + return Objects.equals(this.identifier, identifierType.identifier) && + Objects.equals(this.schema, identifierType.schema); + } + + @Override + public int hashCode() { + return Objects.hash(identifier, schema); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class IdentifierType {\n"); + + sb.append(" identifier: ").append(toIndentedString(identifier)).append("\n"); + sb.append(" schema: ").append(toIndentedString(schema)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java new file mode 100644 index 00000000..c81b3bd1 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java @@ -0,0 +1,178 @@ +package eu.dnetlib.scholix.api.model.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class ScholixItem { + + @JsonProperty("identifier") + private ScholixIdentifier identifier; + + @JsonProperty("objectType") + private String objectType; + + @JsonProperty("objectSubType") + private String objectSubType; + + @JsonProperty("title") + private String title; + + @JsonProperty("creator") + private List creator; + + @JsonProperty("publicationDate") + private String publicationDate; + + @JsonProperty("publisher") + private ScholixProvider publisher; + + public ScholixItem identifier(ScholixIdentifier identifier) { + this.identifier = identifier; + return this; + } + + @Schema(description = "The identifier string") + public ScholixIdentifier getIdentifier() { + return identifier; + } + + public void setIdentifier(ScholixIdentifier identifier) { + this.identifier = identifier; + } + + public ScholixItem objectType(String objectType) { + this.objectType = objectType; + return this; + } + + @Schema(description = "Describes the nature of the object (its intended usage)") + public String getObjectType() { + return objectType; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public ScholixItem objectSubType(String objectSubType) { + this.objectSubType = objectSubType; + return this; + } + + @Schema(description = "The sub-type of Object") + public String getObjectSubType() { + return objectSubType; + } + + public void setObjectSubType(String objectSubType) { + this.objectSubType = objectSubType; + } + + public ScholixItem title(String title) { + this.title = title; + return this; + } + + @Schema(description = "The name of the object") + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public ScholixItem creator(List creator) { + this.creator = creator; + return this; + } + + public ScholixItem addCreatorInstance(ScholixCreator creatorInstance) { + if(this.creator == null) + this.creator = new ArrayList<>(); + this.creator.add(creatorInstance); + return this; + } + + @Schema(description = "Party responsible for the creation of the object") + public List getCreator() { + return creator; + } + + public void setCreator(List creator) { + this.creator = creator; + } + + @Schema(description = "The date the object was formally issued, published or distributed") + public String getPublicationDate() { + return publicationDate; + } + + public void setPublicationDate(String publicationDate) { + this.publicationDate = publicationDate; + } + + @Schema(description = "The name of the publisher of the object") + public ScholixProvider getPublisher() { + return publisher; + } + + public void setPublisher(ScholixProvider publisher) { + this.publisher = publisher; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ScholixItem scholixItemType = (ScholixItem) o; + return Objects.equals(this.objectType, scholixItemType.objectType) && + Objects.equals(this.objectSubType, scholixItemType.objectSubType) && + Objects.equals(this.identifier, scholixItemType.identifier) && + Objects.equals(this.title, scholixItemType.title) && + Objects.equals(this.creator, scholixItemType.creator) && + Objects.equals(this.publicationDate, scholixItemType.publicationDate) && + Objects.equals(this.publisher, scholixItemType.publisher); + } + + @Override + public int hashCode() { + return Objects.hash(objectType, objectSubType, identifier, title, creator, publicationDate, publisher); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ScholixItemType {\n"); + + sb.append(" objectType: ").append(toIndentedString(objectType)).append("\n"); + sb.append(" objectSubType: ").append(toIndentedString(objectSubType)).append("\n"); + sb.append(" identifier: ").append(toIndentedString(identifier)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" creator: ").append(toIndentedString(creator)).append("\n"); + sb.append(" publicationDate: ").append(toIndentedString(publicationDate)).append("\n"); + sb.append(" publisher: ").append(toIndentedString(publisher)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java new file mode 100644 index 00000000..1436c36d --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java @@ -0,0 +1,106 @@ +package eu.dnetlib.scholix.api.model.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class ScholixProvider { + + @JsonProperty("name") + private String name = null; + + @JsonProperty("identifier") + @Valid + private List identifier = null; + + public ScholixProvider name(String name) { + this.name = name; + return this; + } + + /** + * Get the provider name + * @return name + **/ + @Schema(description = "The provider name") + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ScholixProvider identifier(List identifier) { + this.identifier = identifier; + return this; + } + + public ScholixProvider addIdentifierItem(ScholixIdentifier identifierItem) { + if (this.identifier == null) { + this.identifier = new ArrayList<>(); + } + this.identifier.add(identifierItem); + return this; + } + + /** + * Get identifier + * @return identifier + **/ + @Schema(description = "the identifiers of the provider") + @Valid + public List getIdentifier() { + return identifier; + } + + public void setIdentifier(List identifier) { + this.identifier = identifier; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ScholixProvider scholixProviderType = (ScholixProvider) o; + return Objects.equals(this.name, scholixProviderType.name) && + Objects.equals(this.identifier, scholixProviderType.identifier); + } + + @Override + public int hashCode() { + return Objects.hash(name, identifier); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ScholixProviderType {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" identifiers: ").append(toIndentedString(identifier)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java new file mode 100644 index 00000000..82242d39 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java @@ -0,0 +1,119 @@ +package eu.dnetlib.scholix.api.model.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import java.util.Objects; + +public class ScholixRelationship { + + @JsonProperty("name") + private String name = null; + + @JsonProperty("schema") + private String schema = null; + + @NotBlank + @JsonProperty("inverseRelationship") + private String inverseRelationship = null; + + public ScholixRelationship name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @Schema(required = true, description = "The relationship type chosen from a Scholix controlled vocabulary") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ScholixRelationship schema(String schema) { + this.schema = schema; + return this; + } + + /** + * Get The name of the schema or controlled list from which Relationship Sub-type is sourced + * @return subType + **/ + @Schema(description = "The name of the schema or controlled list from which Relationship Sub-type is sourced") + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public ScholixRelationship inverseRelationship(String inverseRelationship) { + this.inverseRelationship = inverseRelationship; + return this; + } + + /** + * Get inverseRelationship + * @return inverseRelationship + **/ + @Schema(description = "The value of the inverse relation") + + public String getInverseRelationship() { + return inverseRelationship; + } + + public void setInverseRelationship(String inverseRelationship) { + this.inverseRelationship = inverseRelationship; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ScholixRelationship relationshipType = (ScholixRelationship) o; + return Objects.equals(this.name, relationshipType.name) && + Objects.equals(this.schema, relationshipType.schema) && + Objects.equals(this.inverseRelationship, relationshipType.inverseRelationship); + } + + @Override + public int hashCode() { + return Objects.hash(name, schema, inverseRelationship); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RelationshipType {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" subType: ").append(toIndentedString(schema)).append("\n"); + sb.append(" subTypeSchema: ").append(toIndentedString(inverseRelationship)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java new file mode 100644 index 00000000..b12e453c --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java @@ -0,0 +1,159 @@ +package eu.dnetlib.scholix.api.model.v1; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class ScholixV1 { + + @JsonProperty("linkProvider") + private List linkProvider; + + @JsonProperty("publicationDate") + private String publicationDate; + + @NotBlank + @JsonProperty("relationship") + private ScholixRelationship relationship; + + @NotBlank + @JsonProperty("source") + private ScholixItem source; + + @NotBlank + @JsonProperty("target") + private ScholixItem target; + + + + public ScholixV1 linkProvider (final List linkProvider ) { + this.linkProvider = linkProvider; + return this; + } + + @Schema(description = "An entity responsible for making this record available online") + public List getLinkProvider() { + return linkProvider; + } + + public ScholixV1 addLinkProviderItem(ScholixProvider linkProviderItem) { + if (this.linkProvider == null) { + this.linkProvider = new ArrayList<>(); + } + this.linkProvider.add(linkProviderItem); + return this; + } + + public void setLinkProvider(List linkProvider) { + this.linkProvider = linkProvider; + } + + @Schema(description = "date of formal issuance (e.g., publication) of the resource; generally different from source object and target object publication dates") + public String getPublicationDate() { + return publicationDate; + } + + public ScholixV1 publicationDate(String publicationDate) { + this.publicationDate = publicationDate; + return this; + } + + public void setPublicationDate(String publicationDate) { + this.publicationDate = publicationDate; + } + + @Schema(description = "Semantics of the relationship from source to target") + public ScholixRelationship getRelationship() { + return relationship; + } + + public ScholixV1 relationship(ScholixRelationship relationship) { + this.relationship = relationship; + return this; + } + + public void setRelationship(ScholixRelationship relationship) { + this.relationship = relationship; + } + + @Schema(description = "Root element relative to all properties describing the link’s source object.") + public ScholixItem getSource() { + return source; + } + + + public ScholixV1 source(ScholixItem source) { + this.source = source; + return this; + } + public void setSource(ScholixItem source) { + this.source = source; + } + + @Schema(description = "Root element relative to all properties describing the link’s target object.") + public ScholixItem getTarget() { + return target; + } + + public ScholixV1 target(ScholixItem target) { + this.target = target; + return this; + } + + public void setTarget(ScholixItem target) { + this.target = target; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ScholixV1 scholixV1 = (ScholixV1) o; + return Objects.equals(this.linkProvider, scholixV1.getLinkProvider()) && + Objects.equals(this.publicationDate, scholixV1.getPublicationDate()) && + Objects.equals(this.relationship, scholixV1.getRelationship()) && + Objects.equals(this.source, scholixV1.getSource()) && + Objects.equals(this.target, scholixV1.getTarget()); + } + + @Override + public int hashCode() { + return Objects.hash(linkProvider, publicationDate, relationship, source, target); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ScholixV1 {\n"); + + sb.append(" linkProvider: ").append(toIndentedString(linkProvider)).append("\n"); + sb.append(" publicationDate: ").append(toIndentedString(publicationDate)).append("\n"); + sb.append(" relationship: ").append(toIndentedString(relationship)).append("\n"); + sb.append(" source: ").append(toIndentedString(source)).append("\n"); + sb.append(" target: ").append(toIndentedString(target)).append("\n"); + + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java new file mode 100644 index 00000000..4957b4f7 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java @@ -0,0 +1,123 @@ +package eu.dnetlib.scholix.api.model.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.util.Objects; + +/** + * The type Link provider type. + */ +public class LinkProviderType { + @NotBlank + @JsonProperty("name") + private String name = null; + + @NotBlank + @JsonProperty("totalRelationships") + private Integer totalRelationships = null; + + /** + * Name link provider type. + * + * @param name the name + * @return the link provider type + */ + public LinkProviderType name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * + * @return name name + */ + @Schema(description = "The Publisher Name") + @Size(max=300) + public String getName() { + return name; + } + + /** + * Sets name. + * + * @param name the name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Total relationships link provider type. + * + * @param totalRelationships the total relationships + * @return the link provider type + */ + public LinkProviderType totalRelationships(Integer totalRelationships) { + this.totalRelationships = totalRelationships; + return this; + } + + /** + * Get totalRelationships + * + * @return totalRelationships total relationships + */ + @Schema(description = "Total number of relationships that the publisher provides") + public Integer getTotalRelationships() { + return totalRelationships; + } + + /** + * Sets total relationships. + * + * @param totalRelationships the total relationships + */ + public void setTotalRelationships(Integer totalRelationships) { + this.totalRelationships = totalRelationships; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + LinkProviderType linkPublisher = (LinkProviderType) o; + return Objects.equals(this.name, linkPublisher.name) && + Objects.equals(this.totalRelationships, linkPublisher.totalRelationships); + } + + @Override + public int hashCode() { + return Objects.hash(name, totalRelationships); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class LinkPublisher {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" totalRelationships: ").append(toIndentedString(totalRelationships)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/PageResultType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/PageResultType.java new file mode 100644 index 00000000..cb7c262e --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/PageResultType.java @@ -0,0 +1,114 @@ +package eu.dnetlib.scholix.api.model.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * The main class that show the page result from the method + * /l2/links + */ +public class PageResultType implements Serializable { + + @NotBlank + @JsonProperty("currentPage") + @ApiModelProperty(position = 0) + private Integer currentPage = 0; + + @NotBlank + @JsonProperty("totalLinks") + @ApiModelProperty(position = 1) + private Integer totalLinks= 0; + + @NotBlank + @JsonProperty("totalPages") + @ApiModelProperty(position = 2) + private Integer totalPages = 0; + + @NotBlank + @JsonProperty("result") + @ApiModelProperty(position = 3) + private List result = new ArrayList<>(); + + + /** + * Gets current page. + * + * @return the current page + */ + @Schema(description = "The Current page of the results") + public Integer getCurrentPage() { + return currentPage; + } + + /** + * Sets current page. + * + * @param currentPage the current page + */ + public void setCurrentPage(Integer currentPage) { + this.currentPage = currentPage; + } + + /** + * Gets total links. + * + * @return the total links + */ + @Schema(description = "The total number of Links found by the query") + public Integer getTotalLinks() { + return totalLinks; + } + + /** + * Sets total links. + * + * @param totalLinks the total links + */ + public void setTotalLinks(Integer totalLinks) { + this.totalLinks = totalLinks; + } + + /** + * Gets total pages. + * + * @return the total pages + */ + @Schema(description = "The Total number of pages") + public Integer getTotalPages() { + return totalPages; + } + + /** + * Sets total pages. + * + * @param totalPages the total pages + */ + public void setTotalPages(Integer totalPages) { + this.totalPages = totalPages; + } + + /** + * Gets result. + * + * @return the result + */ + @Schema(description = "The First page of Scholix results") + public List getResult() { + return result; + } + + /** + * Sets result. + * + * @param result the result + */ + public void setResult(List result) { + this.result = result; + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java new file mode 100644 index 00000000..87166b25 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java @@ -0,0 +1,86 @@ +package eu.dnetlib.scholix.api.model.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotNull; + +/** + * The type Relationship type. + */ +public class RelationshipType { + + @NotNull + @JsonProperty("Name") + private String name; + + @JsonProperty("SubType") + private String subType; + + @JsonProperty("SubTypeSchema") + private String subTypeSchema; + + + /** + * Gets The relationship type chosen from a Scholix controlled vocabulary + * + * @return the name + */ + @Schema(description = "The relationship type chosen from a Scholix controlled vocabulary") + public String getName() { + return name; + } + + /** + * Sets The relationship type chosen from a Scholix controlled vocabulary + * + * @param name the name + * @return the RelationshipType instance + */ + public RelationshipType setName(String name) { + this.name = name; + return this; + } + + /** + * Gets The sub-type of RelationshipType.Name + * + * @return the sub type + */ + @Schema(description = "The sub-type of RelationshipType.Name") + public String getSubType() { + return subType; + } + + /** + * Sets The sub-type of RelationshipType.Name + * + * @param subType the sub type + * @return the RelationshipType instance + */ + public RelationshipType setSubType(String subType) { + this.subType = subType; + return this; + } + + /** + * Gets The name of the schema or controlled list from which RelationshipSub-type is sourced. + * + * @return the sub type schema + */ + @Schema(description = "The name of the schema or controlled list from which RelationshipSub-type is sourced") + public String getSubTypeSchema() { + return subTypeSchema; + } + + /** + * Sets The name of the schema or controlled list from which RelationshipSub-type is sourced. + * + * @param subTypeSchema the sub type schema + * @return the RelationshipType instance + */ + public RelationshipType setSubTypeSchema(String subTypeSchema) { + this.subTypeSchema = subTypeSchema; + return this; + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java new file mode 100644 index 00000000..61902ade --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java @@ -0,0 +1,66 @@ +package eu.dnetlib.scholix.api.model.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import java.util.ArrayList; +import java.util.List; + +/** + * The type Scholix creator type. + */ +public class ScholixCreatorType { + + @NotBlank + @JsonProperty("name") + private String name = null; + + + @NotBlank + @JsonProperty("identifier") + private List identifier = new ArrayList<>(); + + /** + * Gets A List of unique string that identifies the creator + * + * @return the identifier + */ + @Schema(description = "A List of unique string that identifies the creator") + public List getIdentifier() { + return identifier; + } + + /** + * Sets A List of unique string that identifies the creator + * + * @param identifier the identifier + * @return the identifier + */ + public ScholixCreatorType setIdentifier(List identifier) { + this.identifier = identifier; + return this; + } + + + /** + * Gets The name of the Object Creator + * + * @return the name + */ + @Schema(description = "The name of the Object Creator") + public String getName() { + return name; + } + + /** + * Sets The name of the Object Creator + * + * @param name the name + * @return the name + */ + public ScholixCreatorType setName(String name) { + this.name = name; + return this; + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java new file mode 100644 index 00000000..b023c772 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java @@ -0,0 +1,92 @@ +package eu.dnetlib.scholix.api.model.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import java.util.Objects; + +/** + * The type Scholix identifier type. + */ +public class ScholixIdentifierType { + + @NotBlank + @JsonProperty("ID") + private String id = null; + + @NotBlank + @JsonProperty("IDScheme") + private String idScheme = null; + + @NotBlank + @JsonProperty("IDURL") + private String idURL = null; + + + /** + * Gets The identifier + * + * @return the id + */ + @Schema(description = "The identifier") + public String getId() { + return id; + } + + /** + * Sets The identifier + * + * @param id the id + * @return the id + */ + public ScholixIdentifierType setId(String id) { + this.id = id; + return this; + } + + /** + * Gets The scheme or namespace of the identifier string + * + * @return the id scheme + */ + @Schema(description = "The scheme or namespace of the identifier string") + public String getIdScheme() { + return idScheme; + } + + /** + * Sets The scheme or namespace of the identifier string + * + * @param idScheme the id scheme + * @return the id scheme + */ + public ScholixIdentifierType setIdScheme(String idScheme) { + this.idScheme = idScheme; + return this; + } + + /** + * Gets An internet resolvable form of the identifier + * + * @return the id url + */ + @Schema(description = "An internet resolvable form of the identifier") + public String getIdURL() { + return idURL; + } + + /** + * Sets An internet resolvable form of the identifier + * + * @param idURL the id url + * @return the id url + */ + public ScholixIdentifierType setIdURL(String idURL) { + this.idURL = idURL; + return this; + } + + + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java new file mode 100644 index 00000000..b137a9ac --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java @@ -0,0 +1,151 @@ +package eu.dnetlib.scholix.api.model.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type Scholix item type. + */ +public class ScholixItemType { + + @JsonProperty("Identifier") + private List identifier = new ArrayList(); + + @JsonProperty("Title") + private String title; + + @JsonProperty("Type") + private String type; + + @JsonProperty("Creator") + private List creator = new ArrayList<>(); + + @JsonProperty("PublicationDate") + private String publicationDate; + + @JsonProperty("Publisher") + private List publisher = new ArrayList<>(); + + + /** + * Gets identifier. + * + * @return the identifier + */ + public List getIdentifier() { + return identifier; + } + + /** + * Sets identifier. + * + * @param identifier the identifier + * @return the identifier + */ + public ScholixItemType setIdentifier(List identifier) { + this.identifier = identifier; + return this; + } + + /** + * Gets title. + * + * @return the title + */ + public String getTitle() { + return title; + } + + /** + * Sets title. + * + * @param title the title + * @return the title + */ + public ScholixItemType setTitle(String title) { + this.title = title; + return this; + } + + /** + * Gets type. + * + * @return the type + */ + public String getType() { + return type; + } + + /** + * Sets type. + * + * @param type the type + * @return the type + */ + public ScholixItemType setType(String type) { + this.type = type; + return this; + } + + /** + * Gets creator. + * + * @return the creator + */ + public List getCreator() { + return creator; + } + + /** + * Sets creator. + * + * @param creator the creator + * @return the creator + */ + public ScholixItemType setCreator(List creator) { + this.creator = creator; + return this; + } + + /** + * Gets publication date. + * + * @return the publication date + */ + public String getPublicationDate() { + return publicationDate; + } + + /** + * Sets publication date. + * + * @param publicationDate the publication date + * @return the publication date + */ + public ScholixItemType setPublicationDate(String publicationDate) { + this.publicationDate = publicationDate; + return this; + } + + /** + * Gets publisher. + * + * @return the publisher + */ + public List getPublisher() { + return publisher; + } + + /** + * Sets publisher. + * + * @param publisher the publisher + * @return the publisher + */ + public ScholixItemType setPublisher(List publisher) { + this.publisher = publisher; + return this; + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java new file mode 100644 index 00000000..c14093d3 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java @@ -0,0 +1,67 @@ +package eu.dnetlib.scholix.api.model.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * The type Scholix link provider type. + */ +public class ScholixLinkProviderType { + @NotBlank + @JsonProperty("name") + private String name = null; + + + @NotBlank + @JsonProperty("identifier") + private List identifier = new ArrayList<>(); + + /** + * Gets A List of unique string that identifies the object + * + * @return the identifier + */ + @Schema(description = "A List of unique string that identifies the object") + public List getIdentifier() { + return identifier; + } + + /** + * Sets A List of unique string that identifies the object + * + * @param identifier the identifier + * @return the identifier + */ + public ScholixLinkProviderType setIdentifier(List identifier) { + this.identifier = identifier; + return this; + } + + + /** + * Gets The name of the Provider + * + * @return the name + */ + @Schema(description = "The name of the Provider") + public String getName() { + return name; + } + + /** + * Sets The name of the Provider + * + * @param name the name + * @return the name + */ + public ScholixLinkProviderType setName(String name) { + this.name = name; + return this; + } +} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java new file mode 100644 index 00000000..3c994c96 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java @@ -0,0 +1,170 @@ +package eu.dnetlib.scholix.api.model.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.List; + +/** + * The type Scholix type. + */ +public class ScholixType implements Serializable { + + + @NotBlank + @JsonProperty("RelationshipType") + private RelationshipType relationshipType ; + + @NotBlank + @JsonProperty("source") + private ScholixItemType source ; + + @NotBlank + @JsonProperty("target") + private ScholixItemType target ; + + @JsonProperty("HarvestDate") + private String harvestDate ; + + + @JsonProperty("LicenseURL") + private String licenseURL ; + + @JsonProperty("LinkProvider") + private List linkProvider ; + + @JsonProperty("LinkPublicationDate") + private String linkPublicationDate ; + + + /** + * Gets the nature of the relationship between the source object and target object in this Link Information Package + * + * @return the relationship type + */ + @Schema(description = "The nature of the relationship between the source object and target object in this Link Information Package") + public RelationshipType getRelationshipType() { + return relationshipType; + } + + public void setRelationshipType(RelationshipType relationshipType) { + this.relationshipType = relationshipType; + } + + /** + * Gets Root element relative to all properties describing the link’s source object + * + * @return the source + */ + @Schema(description = "Root element relative to all properties describing the link’s source object") + public ScholixItemType getSource() { + return source; + } + + /** + * Sets source. + * + * @param source the source + */ + public void setSource(ScholixItemType source) { + this.source = source; + } + + /** + * Gets Root element relative to all properties describing the link’s target object + * + * @return the target + */ + @Schema(description = "Gets Root element relative to all properties describing the link’s target object") + public ScholixItemType getTarget() { + return target; + } + + /** + * Sets target. + * + * @param target the target + */ + public void setTarget(ScholixItemType target) { + this.target = target; + } + + /** + * Gets harvest date. + * + * @return the harvest date + */ + public String getHarvestDate() { + return harvestDate; + } + + /** + * Sets harvest date. + * + * @param harvestDate the harvest date + */ + public void setHarvestDate(String harvestDate) { + this.harvestDate = harvestDate; + } + + /** + * Gets The URL of the license for the Scholix Link Information Package + * + * @return the license url + */ + + @Schema(description = "The URL of the license for the Scholix Link Information Package") + public String getLicenseURL() { + return licenseURL; + } + + /** + * Sets license url. + * + * @param licenseURL the license url + */ + public void setLicenseURL(String licenseURL) { + this.licenseURL = licenseURL; + } + + /** + * Gets The source(s) of this Link Information Package. + * + * @return the link provider + */ + @Schema(description = "The source(s) of this Link Information Package") + public List getLinkProvider() { + return linkProvider; + } + + /** + * Sets link provider. + * + * @param linkProvider the link provider + */ + public void setLinkProvider(List linkProvider) { + this.linkProvider = linkProvider; + } + + /** + * Gets Date when this Link Information Package was first formally issued from this current Provider + * + * @return the link publication date + */ + @Schema(description = "Date when this Link Information Package was first formally issued from this current Provider") + + public String getLinkPublicationDate() { + return linkPublicationDate; + } + + /** + * Sets link publication date. + * + * @param linkPublicationDate the link publication date + */ + public void setLinkPublicationDate(String linkPublicationDate) { + this.linkPublicationDate = linkPublicationDate; + } +} diff --git a/apps/scholexplorer-api/src/main/resources/application.properties b/apps/scholexplorer-api/src/main/resources/application.properties new file mode 100644 index 00000000..38401105 --- /dev/null +++ b/apps/scholexplorer-api/src/main/resources/application.properties @@ -0,0 +1,48 @@ +spring.main.banner-mode = console + +logging.level.root = INFO +dhp.swagger.api.host = localhost:8080 +#dhp.swagger.api.host = api.scholexplorer.openaire.eu +dhp.swagger.api.basePath = / + +maven.pom.path = /META-INF/maven/eu.dnetlib.dhp/scholexplorer-api/effective-pom.xml +# +#spring.thymeleaf.cache=false +# +#management.endpoints.web.exposure.include = prometheus,health +#management.endpoints.web.base-path = / +#management.endpoints.web.path-mapping.prometheus = metrics +#management.endpoints.web.path-mapping.health = health +# +#spring.datasource.url=jdbc:postgresql://localhost:5432/mdstoremanager +#spring.datasource.username= +#spring.datasource.password= +# +#spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect +# +## Hibernate ddl auto (create, create-drop, validate, update) +#spring.jpa.hibernate.ddl-auto = validate +#spring.jpa.properties.hibernate.hbm2dll.extra_physical_table_types = MATERIALIZED VIEW +#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true +#spring.jpa.open-in-view=true +# +## logs +#logging.level.io.swagger.models.parameters.AbstractSerializableParameter = error +# +## Hadoop +#dhp.mdstore-manager.hadoop.cluster = GARR +#dhp.mdstore-manager.hdfs.base-path = /data/dnet.dev/mdstore +#dhp.mdstore-manager.hadoop.user = dnet.dev +# +##dhp.mdstore-manager.hadoop.zeppelin.base-url = https://iis-cdh5-test-gw.ocean.icm.edu.pl/zeppelin +##dhp.mdstore-manager.hadoop.zeppelin.login = +##dhp.mdstore-manager.hadoop.zeppelin.password = +#dhp.mdstore-manager.hadoop.zeppelin.base-url = https://hadoop-zeppelin.garr-pa1.d4science.org +#dhp.mdstore-manager.hadoop.zeppelin.login = +#dhp.mdstore-manager.hadoop.zeppelin.password = +# +#dhp.mdstore-manager.hadoop.zeppelin.name-prefix = mdstoreManager +# +#dhp.mdstore-manager.inspector.records.max = 1000 + + diff --git a/apps/scholexplorer-api/src/main/resources/static/logo.png b/apps/scholexplorer-api/src/main/resources/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4614e2d5c6f8d400787f0c6b321e2c88b5bc6439 GIT binary patch literal 43773 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 LNkvXXu0mjfA|>K7 literal 0 HcmV?d00001 diff --git a/apps/scholexplorer-api/src/main/resources/static/new_swagger.html b/apps/scholexplorer-api/src/main/resources/static/new_swagger.html new file mode 100644 index 00000000..a22ffb29 --- /dev/null +++ b/apps/scholexplorer-api/src/main/resources/static/new_swagger.html @@ -0,0 +1,135 @@ + + + + + + Custom Swagger UI + + + + + + + +
+ + X name + +
+
+ + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index d48f11f4..5c9b7070 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,8 @@ libs apps cmd-line-apps - + scholexplorer-api + Redmine -- 2.17.1 From 04ea22b244af26771aa068b9a7874303a2e7d4df Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Wed, 2 Feb 2022 14:55:09 +0100 Subject: [PATCH 2/9] fixed pom deps --- apps/pom.xml | 2 +- apps/scholexplorer-api/pom.xml | 4 ---- pom.xml | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/pom.xml b/apps/pom.xml index 5b589921..877813fe 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -4,7 +4,7 @@ eu.dnetlib.dhp dnet-applications 3.2.3-SNAPSHOT - ../ + ../pom.xml 4.0.0 diff --git a/apps/scholexplorer-api/pom.xml b/apps/scholexplorer-api/pom.xml index 93fc45b7..7ce034c1 100644 --- a/apps/scholexplorer-api/pom.xml +++ b/apps/scholexplorer-api/pom.xml @@ -14,10 +14,6 @@ scholexplorer-api - - io.springfox - springfox-bean-validators - diff --git a/pom.xml b/pom.xml index 5c9b7070..98f32305 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,6 @@ libs apps cmd-line-apps - scholexplorer-api -- 2.17.1 From f505f379af6049aa4854720a93b7f9f5d4d6372d Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Fri, 4 Feb 2022 15:52:49 +0100 Subject: [PATCH 3/9] implemented first test of connection to index elasticSearch --- apps/scholexplorer-api/pom.xml | 8 +++ .../dnetlib/scholix/api/MainApplication.java | 48 ++++++++++++++++- .../dnetlib/scholix/api/RestClientConfig.java | 32 ++++++++++++ .../scholix/api/controller/DatasourceV1.java | 4 +- .../api/controller/ScholixControllerV2.java | 52 +++++++++++++++++-- .../scholix/api/metrics/RequestCounter.java | 13 +++++ .../src/main/resources/application.properties | 45 ++++------------ pom.xml | 8 ++- 8 files changed, 166 insertions(+), 44 deletions(-) create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/metrics/RequestCounter.java diff --git a/apps/scholexplorer-api/pom.xml b/apps/scholexplorer-api/pom.xml index 7ce034c1..04b31ca5 100644 --- a/apps/scholexplorer-api/pom.xml +++ b/apps/scholexplorer-api/pom.xml @@ -15,12 +15,20 @@ + + org.springframework.data + spring-data-elasticsearch + org.springframework.boot spring-boot-starter-test test + + eu.dnetlib.dhp + dhp-schemas + diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java index b7761633..500691c6 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java @@ -1,12 +1,19 @@ package eu.dnetlib.scholix.api; import eu.dnetlib.common.app.AbstractDnetApp; +import io.micrometer.core.aop.TimedAspect; +import io.micrometer.core.instrument.DistributionSummary; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.config.MeterFilter; +import io.micrometer.core.instrument.distribution.DistributionStatisticConfig; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; @@ -15,11 +22,13 @@ import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import java.time.Duration; + @SpringBootApplication @EnableSwagger2 @EnableCaching @EnableScheduling -//@EntityScan("eu.dnetlib.scholix.api.controller") +@ComponentScan(basePackages = "eu.dnetlib") public class MainApplication extends AbstractDnetApp { @Value("${dhp.swagger.api.host}") @@ -38,6 +47,41 @@ public class MainApplication extends AbstractDnetApp { SpringApplication.run(MainApplication.class, args); } + + @Bean + public TimedAspect timedAspect(MeterRegistry meterRegistry) { + + double scale = 1000000; + MeterFilter mf = new MeterFilter() { + @Override + public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) { + if (id.getName().startsWith("scholix")) { + + return DistributionStatisticConfig.builder() + .percentiles(0.20, 0.50, 0.75,0.95) + .percentilesHistogram(false) + .serviceLevelObjectives(5.0*scale, 10.0*scale, 250*scale, 500*scale, 750*scale ,1000.0*scale,2500.0*scale,5000.0*scale,7500.0*scale,10000.0*scale ) + +// .minimumExpectedValue(0.008) +//// .maximumExpectedValue(1000000.0) + .build() + .merge(config); + } + return config; + } + }; + + + meterRegistry.config().meterFilter(mf); + + + + return new TimedAspect(meterRegistry); + } + + + + @Override protected void configSwagger(final Docket docket) { docket diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java new file mode 100644 index 00000000..2abcd0f3 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java @@ -0,0 +1,32 @@ +package eu.dnetlib.scholix.api; + +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.elasticsearch.client.ClientConfiguration; +import org.springframework.data.elasticsearch.client.RestClients; +import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; + +import java.time.Duration; + +@Configuration +public class RestClientConfig extends AbstractElasticsearchConfiguration { + + @Override + @Bean + public RestHighLevelClient elasticsearchClient() { + + final ClientConfiguration clientConfiguration = ClientConfiguration.builder() + .connectedTo("localhost:9200") + .withSocketTimeout(Duration.ofSeconds(60)) + .build(); + + return RestClients.create(clientConfiguration).rest(); + + } + + + + + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java index 007a6caf..684ec92f 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java @@ -2,6 +2,7 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; import eu.dnetlib.scholix.api.model.v1.LinkPublisher; +import io.micrometer.core.annotation.Timed; import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation; import org.springframework.web.bind.annotation.GetMapping; @@ -19,10 +20,11 @@ import java.util.List; }) public class DatasourceV1 extends AbstractDnetController { + @Timed(value = "scholix.v1.datasources", description = "Time taken to return all datasources on Version 1.0 of Scholix") @Operation( summary = "Get all Datasources", description = "returns a list of all datasources") - @GetMapping("/v1/listDatasources") + @GetMapping("/listDatasources") public List getDatasources() { return Arrays.asList( new LinkPublisher().name("pippo").totalRelationships(30), diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java index ee5fef8a..e6fd4f84 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java @@ -2,18 +2,34 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixIdentifier; import eu.dnetlib.scholix.api.model.v2.PageResultType; +import io.micrometer.core.annotation.Timed; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; +import eu.dnetlib.dhp.schema.sx.scholix.Scholix; +import org.apache.lucene.search.join.ScoreMode; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.NestedQueryBuilder; +import org.elasticsearch.index.query.TermQueryBuilder; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.Query; +import org.elasticsearch.index.query.QueryBuilders; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import javax.validation.constraints.NotNull; -import java.util.Arrays; +import java.util.Collections; @RestController @RequestMapping("/v2") @@ -22,6 +38,13 @@ import java.util.Arrays; }) public class ScholixControllerV2 extends AbstractDnetController { + @Autowired + ElasticsearchOperations elasticsearchTemplate; + + + + + @Timed(value = "scholix.v2.links", description = "Time taken to return links on Version 2.0 of Scholix") @ApiOperation("Get Scholix Links") @GetMapping("/Links") public PageResultType links( @@ -46,9 +69,28 @@ public class ScholixControllerV2 extends AbstractDnetController { @Parameter(in = ParameterIn.QUERY, description = "Filter scholix Links having collected after this date") String harvestedAfter, @Parameter(in = ParameterIn.QUERY, - description = "select page of result") Integer page) { + description = "select page of result") Integer page) throws Exception { - return new PageResultType(); + + NestedQueryBuilder nb = new NestedQueryBuilder("source.identifier", new TermQueryBuilder("source.identifier.schema", "pdb"), ScoreMode.None); + + + + NativeSearchQuery doiquery = new NativeSearchQueryBuilder() + .withQuery(nb) + .withPageable(PageRequest.of(1,10)) + .build(); + + long tt = elasticsearchTemplate.count(doiquery, Scholix.class, IndexCoordinates.of("dli_scholix")); + System.out.println(tt); + + SearchHits result = elasticsearchTemplate.search(doiquery, Scholix.class, IndexCoordinates.of("dli_scholix")); + + + final PageResultType pageResult = new PageResultType(); + pageResult.setTotalPages((int) tt ); + + return pageResult; } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/metrics/RequestCounter.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/metrics/RequestCounter.java new file mode 100644 index 00000000..56c9ed2c --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/metrics/RequestCounter.java @@ -0,0 +1,13 @@ +package eu.dnetlib.scholix.api.metrics; + +import eu.dnetlib.common.metrics.MetricInfo; +import org.springframework.stereotype.Component; + + +@Component("scholexplorer_test") +public class RequestCounter implements MetricInfo { + @Override + public double obtainValue() { + return 0L; + } +} diff --git a/apps/scholexplorer-api/src/main/resources/application.properties b/apps/scholexplorer-api/src/main/resources/application.properties index 38401105..6bcb8ef7 100644 --- a/apps/scholexplorer-api/src/main/resources/application.properties +++ b/apps/scholexplorer-api/src/main/resources/application.properties @@ -9,40 +9,15 @@ maven.pom.path = /META-INF/maven/eu.dnetlib.dhp/scholexplorer-api/effective-pom. # #spring.thymeleaf.cache=false # -#management.endpoints.web.exposure.include = prometheus,health -#management.endpoints.web.base-path = / -#management.endpoints.web.path-mapping.prometheus = metrics -#management.endpoints.web.path-mapping.health = health -# -#spring.datasource.url=jdbc:postgresql://localhost:5432/mdstoremanager -#spring.datasource.username= -#spring.datasource.password= -# -#spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect -# -## Hibernate ddl auto (create, create-drop, validate, update) -#spring.jpa.hibernate.ddl-auto = validate -#spring.jpa.properties.hibernate.hbm2dll.extra_physical_table_types = MATERIALIZED VIEW -#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true -#spring.jpa.open-in-view=true -# -## logs -#logging.level.io.swagger.models.parameters.AbstractSerializableParameter = error -# -## Hadoop -#dhp.mdstore-manager.hadoop.cluster = GARR -#dhp.mdstore-manager.hdfs.base-path = /data/dnet.dev/mdstore -#dhp.mdstore-manager.hadoop.user = dnet.dev -# -##dhp.mdstore-manager.hadoop.zeppelin.base-url = https://iis-cdh5-test-gw.ocean.icm.edu.pl/zeppelin -##dhp.mdstore-manager.hadoop.zeppelin.login = -##dhp.mdstore-manager.hadoop.zeppelin.password = -#dhp.mdstore-manager.hadoop.zeppelin.base-url = https://hadoop-zeppelin.garr-pa1.d4science.org -#dhp.mdstore-manager.hadoop.zeppelin.login = -#dhp.mdstore-manager.hadoop.zeppelin.password = -# -#dhp.mdstore-manager.hadoop.zeppelin.name-prefix = mdstoreManager -# -#dhp.mdstore-manager.inspector.records.max = 1000 +management.endpoints.web.exposure.include = prometheus,health +management.endpoints.web.base-path = / +management.endpoints.web.path-mapping.prometheus = metrics +management.endpoints.web.path-mapping.health = health + +management.metrics.distribution.percentiles-histogram.http.server.requests=false +management.metrics.distribution.slo.http.server.requests=50ms, 100ms, 200ms, 400ms +management.metrics.distribution.percentiles.http.server.requests=0.5, 0.9, 0.95, 0.99, 0.999 + + diff --git a/pom.xml b/pom.xml index 98f32305..8f02c9d7 100644 --- a/pom.xml +++ b/pom.xml @@ -232,6 +232,12 @@ springfox-boot-starter 3.0.0 + + + org.springframework.data + spring-data-elasticsearch + 4.3.1 + @@ -390,7 +396,7 @@ UTF-8 3.6.0 1.8 - 2.3.6 + 2.10.24 7.1.0 3.4.2 2.8.0 -- 2.17.1 From 68eed5d5235fc49f2ea920ca3c7060f5a1a3ac62 Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Mon, 7 Feb 2022 16:36:26 +0100 Subject: [PATCH 4/9] - Implemented Entity manager responsible for querying index - Implemented mapping from Scholix model of index into ScholixV2 - Added more metrics --- .../dnetlib/scholix/api/MainApplication.java | 27 ++- .../dnetlib/scholix/api/RestClientConfig.java | 19 +- .../scholix/api/ScholixAPIVersion.java | 8 + .../dnetlib/scholix/api/ScholixException.java | 35 +++ .../eu/dnetlib/scholix/api/TaggedCounter.java | 33 +++ .../api/controller/ScholixControllerV2.java | 27 +-- .../api/index/ElasticSearchProperties.java | 103 ++++++++ .../api/index/ScholixIndexManager.java | 222 ++++++++++++++++++ .../scholix/api/model/v1/ScholixV1.java | 9 +- .../api/model/v2/LinkProviderType.java | 1 + .../api/model/v2/RelationshipType.java | 23 ++ .../api/model/v2/ScholixCreatorType.java | 20 ++ .../api/model/v2/ScholixIdentifierType.java | 13 + .../scholix/api/model/v2/ScholixItemType.java | 43 +++- .../api/model/v2/ScholixLinkProviderType.java | 21 ++ .../scholix/api/model/v2/ScholixType.java | 36 ++- .../src/main/resources/application.properties | 5 +- pom.xml | 7 +- 18 files changed, 603 insertions(+), 49 deletions(-) create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixAPIVersion.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixException.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/TaggedCounter.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchProperties.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java index 500691c6..2ce535e4 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java @@ -2,10 +2,7 @@ package eu.dnetlib.scholix.api; import eu.dnetlib.common.app.AbstractDnetApp; import io.micrometer.core.aop.TimedAspect; -import io.micrometer.core.instrument.DistributionSummary; -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.*; import io.micrometer.core.instrument.config.MeterFilter; import io.micrometer.core.instrument.distribution.DistributionStatisticConfig; import org.springframework.beans.factory.annotation.Value; @@ -23,6 +20,8 @@ import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.time.Duration; +import java.util.Arrays; +import java.util.List; @SpringBootApplication @EnableSwagger2 @@ -31,6 +30,12 @@ import java.time.Duration; @ComponentScan(basePackages = "eu.dnetlib") public class MainApplication extends AbstractDnetApp { + private double scale = 1000000000; + + private double[] histogramValues =new double[]{.005 * scale, .01 * scale, .25 * scale, .5 * scale, .75 * scale, scale, 2.5 * scale, 5.0 * scale, 7.5 * scale, 10.0 * scale}; + + + @Value("${dhp.swagger.api.host}") private String swaggetHost; @@ -48,10 +53,17 @@ public class MainApplication extends AbstractDnetApp { } + + @Bean + public TaggedCounter myCounter(MeterRegistry meterRegistry) { + + return new TaggedCounter("scholixLinkCounter", "links",meterRegistry); + } + @Bean public TimedAspect timedAspect(MeterRegistry meterRegistry) { - double scale = 1000000; + MeterFilter mf = new MeterFilter() { @Override public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) { @@ -60,10 +72,7 @@ public class MainApplication extends AbstractDnetApp { return DistributionStatisticConfig.builder() .percentiles(0.20, 0.50, 0.75,0.95) .percentilesHistogram(false) - .serviceLevelObjectives(5.0*scale, 10.0*scale, 250*scale, 500*scale, 750*scale ,1000.0*scale,2500.0*scale,5000.0*scale,7500.0*scale,10000.0*scale ) - -// .minimumExpectedValue(0.008) -//// .maximumExpectedValue(1000000.0) + .serviceLevelObjectives( histogramValues) .build() .merge(config); } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java index 2abcd0f3..078e489b 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java @@ -1,6 +1,8 @@ package eu.dnetlib.scholix.api; +import eu.dnetlib.scholix.api.index.ElasticSearchProperties; import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.client.ClientConfiguration; @@ -12,21 +14,18 @@ import java.time.Duration; @Configuration public class RestClientConfig extends AbstractElasticsearchConfiguration { + @Autowired + private ElasticSearchProperties elasticSearchProperties; + @Override @Bean - public RestHighLevelClient elasticsearchClient() { + public RestHighLevelClient elasticsearchClient() { final ClientConfiguration clientConfiguration = ClientConfiguration.builder() - .connectedTo("localhost:9200") - .withSocketTimeout(Duration.ofSeconds(60)) + .connectedTo(elasticSearchProperties.getClusterNodes().split(",")) + .withConnectTimeout(elasticSearchProperties.getConnectionTimeout()) + .withSocketTimeout(elasticSearchProperties.getSocketTimeout()) .build(); - return RestClients.create(clientConfiguration).rest(); - } - - - - - } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixAPIVersion.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixAPIVersion.java new file mode 100644 index 00000000..265d33eb --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixAPIVersion.java @@ -0,0 +1,8 @@ +package eu.dnetlib.scholix.api; + +public enum ScholixAPIVersion { + + V1, + V2 + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixException.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixException.java new file mode 100644 index 00000000..21d63b71 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixException.java @@ -0,0 +1,35 @@ +package eu.dnetlib.scholix.api; + + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) +public class ScholixException extends Exception{ + + private static final long serialVersionUID = -3414428892721711308L; + + + public ScholixException() { + super(); + } + + public ScholixException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public ScholixException(String message, Throwable cause) { + super(message, cause); + } + + public ScholixException(String message) { + super(message); + } + + public ScholixException(Throwable cause) { + super(cause); + } + + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/TaggedCounter.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/TaggedCounter.java new file mode 100644 index 00000000..8cf48fba --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/TaggedCounter.java @@ -0,0 +1,33 @@ +package eu.dnetlib.scholix.api; + +import io.micrometer.core.instrument.Counter; + +import io.micrometer.core.instrument.MeterRegistry; +import java.util.HashMap; +import java.util.Map; + + +public class TaggedCounter { + + private String name; + private String tagName; + private MeterRegistry registry; + private Map counters = new HashMap<>(); + + + public TaggedCounter(String name, String tagName, MeterRegistry registry) { + this.name = name; + this.tagName = tagName; + this.registry = registry; + } + + + public void increment(String tagValue){ + Counter counter = counters.get(tagValue); + if(counter == null) { + counter = Counter.builder(name).tags(tagName, tagValue).register(registry); + counters.put(tagValue, counter); + } + counter.increment(); + } +} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java index e6fd4f84..116a1e77 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java @@ -3,13 +3,17 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; import eu.dnetlib.dhp.schema.sx.scholix.ScholixIdentifier; +import eu.dnetlib.scholix.api.ScholixAPIVersion; +import eu.dnetlib.scholix.api.index.ScholixIndexManager; import eu.dnetlib.scholix.api.model.v2.PageResultType; +import eu.dnetlib.scholix.api.model.v2.ScholixType; import io.micrometer.core.annotation.Timed; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import eu.dnetlib.dhp.schema.sx.scholix.Scholix; +import org.apache.commons.lang3.tuple.Pair; import org.apache.lucene.search.join.ScoreMode; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.NestedQueryBuilder; @@ -30,6 +34,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; @RestController @RequestMapping("/v2") @@ -39,7 +45,7 @@ import java.util.Collections; public class ScholixControllerV2 extends AbstractDnetController { @Autowired - ElasticsearchOperations elasticsearchTemplate; + private ScholixIndexManager manager; @@ -72,23 +78,16 @@ public class ScholixControllerV2 extends AbstractDnetController { description = "select page of result") Integer page) throws Exception { - NestedQueryBuilder nb = new NestedQueryBuilder("source.identifier", new TermQueryBuilder("source.identifier.schema", "pdb"), ScoreMode.None); + final int currentPage = page!= null? page : 0; - - NativeSearchQuery doiquery = new NativeSearchQueryBuilder() - .withQuery(nb) - .withPageable(PageRequest.of(1,10)) - .build(); - - long tt = elasticsearchTemplate.count(doiquery, Scholix.class, IndexCoordinates.of("dli_scholix")); - System.out.println(tt); - - SearchHits result = elasticsearchTemplate.search(doiquery, Scholix.class, IndexCoordinates.of("dli_scholix")); - + System.out.println(currentPage); + Pair> scholixResult = manager.linksFromPid(ScholixAPIVersion.V2, linkProvider, targetPid, targetPidType, targetPublisher, targetType, sourcePid, sourcePidType, sourcePublisher, sourceType, harvestedAfter, currentPage); final PageResultType pageResult = new PageResultType(); - pageResult.setTotalPages((int) tt ); + pageResult.setTotalPages(scholixResult.getLeft().intValue() / 10); + pageResult.setTotalLinks(scholixResult.getLeft().intValue()); + pageResult.setResult(scholixResult.getRight().stream().map(ScholixType::fromScholix).collect(Collectors.toList())); return pageResult; } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchProperties.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchProperties.java new file mode 100644 index 00000000..38e7016e --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchProperties.java @@ -0,0 +1,103 @@ +package eu.dnetlib.scholix.api.index; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import javax.validation.constraints.NotNull; + +/** + * The type Elastic search properties. + */ +@Component("elasticSearchProperties") +@ConfigurationProperties(prefix = "scholix.elastic") +public class ElasticSearchProperties { + + @NotNull + private String clusterNodes; + @NotNull + private String indexName; + @NotNull + private long connectionTimeout; + @NotNull + private long socketTimeout; + + /** + * Gets cluster nodes. + * + * @return the cluster nodes + */ + public String getClusterNodes() { + return clusterNodes; + } + + /** + * Sets cluster nodes. + * + * @param clusterNodes the cluster nodes + * @return the cluster nodes + */ + public ElasticSearchProperties setClusterNodes(String clusterNodes) { + this.clusterNodes = clusterNodes; + return this; + } + + /** + * Gets index name. + * + * @return the index name + */ + public String getIndexName() { + return indexName; + } + + /** + * Sets index name. + * + * @param indexName the index name + * @return the index name + */ + public ElasticSearchProperties setIndexName(String indexName) { + this.indexName = indexName; + return this; + } + + /** + * Gets connection timeout. + * + * @return the connection timeout + */ + public long getConnectionTimeout() { + return connectionTimeout; + } + + /** + * Sets connection timeout. + * + * @param connectionTimeout the connection timeout + * @return the connection timeout + */ + public ElasticSearchProperties setConnectionTimeout(long connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + /** + * Gets socket timeout. + * + * @return the socket timeout + */ + public long getSocketTimeout() { + return socketTimeout; + } + + /** + * Sets socket timeout. + * + * @param socketTimeout the socket timeout + * @return the socket timeout + */ + public ElasticSearchProperties setSocketTimeout(long socketTimeout) { + this.socketTimeout = socketTimeout; + return this; + } +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java new file mode 100644 index 00000000..daefcab3 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java @@ -0,0 +1,222 @@ +package eu.dnetlib.scholix.api.index; + + +import eu.dnetlib.dhp.schema.sx.scholix.Scholix; +import eu.dnetlib.scholix.api.ScholixAPIVersion; +import eu.dnetlib.scholix.api.ScholixException; +import eu.dnetlib.scholix.api.TaggedCounter; + +import io.micrometer.core.annotation.Timed; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.lucene.search.join.ScoreMode; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.NestedQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.TermQueryBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.SearchHit; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * The type Scholix index manager. + */ +@Component +public class ScholixIndexManager { + + /** + * The Elastic search properties. + */ + @Autowired + ElasticSearchProperties elasticSearchProperties; + + /** + * The Elasticsearch template. + */ + @Autowired + ElasticsearchOperations elasticsearchTemplate; + + /** + * The My counter. + */ + @Autowired + TaggedCounter myCounter; + + + /** + * The enum Pid type prefix. + */ + enum pidTypePrefix { + /** + * Source pid type prefix. + */ + source, + /** + * Target pid type prefix. + */ + target + } + + + private QueryBuilder createObjectTypeQuery(final pidTypePrefix prefix, final String objectType ) throws ScholixException{ + if (prefix == null){ + throw new ScholixException("prefix cannot be null"); + } + return new NestedQueryBuilder(String.format("%s", prefix), new TermQueryBuilder(String.format("%s.objectType",prefix), objectType), ScoreMode.None); + } + + + private QueryBuilder createPidTypeQuery(final pidTypePrefix prefix, final String pidTypeValue ) throws ScholixException{ + if (prefix == null){ + throw new ScholixException("prefix cannot be null"); + } + return new NestedQueryBuilder(String.format("%s.identifier", prefix), new TermQueryBuilder(String.format("%s.identifier.schema",prefix), pidTypeValue), ScoreMode.None); + } + + + private QueryBuilder createPidValueQuery(final pidTypePrefix prefix, final String pidValue ) throws ScholixException{ + if (prefix == null){ + throw new ScholixException("prefix cannot be null"); + } + return new NestedQueryBuilder(String.format("%s.identifier", prefix), new TermQueryBuilder(String.format("%s.identifier.identifier",prefix), pidValue), ScoreMode.None); + } + + + private QueryBuilder createFinalQuery(final List queries) throws ScholixException{ + + if (queries == null || queries.isEmpty()) + throw new ScholixException("the list of queries must be not empty"); + + + if (queries.size() ==1) { + return queries.get(0); + } + + else { + final BoolQueryBuilder b = new BoolQueryBuilder(); + b.must().addAll(queries); + + return b; + } + + } + + private void incrementPidCounter(pidTypePrefix prefix, String value) { + + + switch (value.toLowerCase()){ + case "doi": { + myCounter.increment(String.format("%s_doi", prefix)); + break; + } + case "pmc": { + myCounter.increment(String.format("%s_pmc", prefix)); + break; + } + default: + myCounter.increment(String.format("%s_other", prefix)); + + } + + } + + + /** + * Links from pid pair. + * + * @param outputVersion the output version + * @param linkProvider the link provider + * @param targetPid the target pid + * @param targetPidType the target pid type + * @param targetPublisher the target publisher + * @param targetType the target type + * @param sourcePid the source pid + * @param sourcePidType the source pid type + * @param sourcePublisher the source publisher + * @param sourceType the source type + * @param harvestedAfter the harvested after + * @param page the page + * @return the pair + * @throws ScholixException the scholix exception + */ + @Timed(value = "scholix.index.request.links", description = "Time taken to request index") + public Pair> linksFromPid (final ScholixAPIVersion outputVersion, final String linkProvider, + final String targetPid, final String targetPidType, final String targetPublisher, + final String targetType, final String sourcePid, final String sourcePidType, + final String sourcePublisher, final String sourceType, final String harvestedAfter, + final Integer page) throws ScholixException { + + if(outputVersion == null) + throw new ScholixException("Error outputVersion not be empty"); + + if (sourcePid==null && sourcePidType==null && targetPid==null && targetPidType==null && sourcePublisher==null && targetPublisher==null && linkProvider==null) + throw new ScholixException("One of sourcePid, targetPid, sourcePublisher, targetPublisher, linkProvider should be not null"); + + final List queries = new ArrayList<>(); + + if (StringUtils.isNoneBlank(targetPid)) { + myCounter.increment("targetPid"); + queries.add(createPidValueQuery(pidTypePrefix.target, targetPid)); + } + if (StringUtils.isNoneBlank(sourcePid)) { + myCounter.increment("sourcePid"); + queries.add(createPidValueQuery(pidTypePrefix.source, sourcePid)); + } + + if (StringUtils.isNoneBlank(targetPidType)) { + assert targetPidType != null; + incrementPidCounter(pidTypePrefix.target,targetPidType); + queries.add(createPidTypeQuery(pidTypePrefix.target, targetPidType)); + } + if (StringUtils.isNoneBlank(sourcePidType)) { + assert sourcePidType != null; + incrementPidCounter(pidTypePrefix.source,sourcePidType); + queries.add(createPidTypeQuery(pidTypePrefix.source, sourcePidType)); + } + + if (StringUtils.isNoneBlank(targetType)) { + if ("dataset".equalsIgnoreCase(targetType) || "publication".equalsIgnoreCase(targetType)) + myCounter.increment(String.format("targetType_%s", targetType)); + queries.add(createObjectTypeQuery(pidTypePrefix.target, targetType)); + } + + if (StringUtils.isNoneBlank(sourceType)) { + if ("dataset".equalsIgnoreCase(sourceType) || "publication".equalsIgnoreCase(sourceType)) { + myCounter.increment(String.format("sourceType_%s", sourceType)); + } + queries.add(createObjectTypeQuery(pidTypePrefix.source, sourceType)); + } + + QueryBuilder result = createFinalQuery(queries); + + NativeSearchQuery finalQuery = new NativeSearchQueryBuilder() + .withQuery(result) + .withPageable(PageRequest.of(page,10)) + .build(); + + long tt = elasticsearchTemplate.count(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + System.out.println(tt); + + SearchHits scholixRes = elasticsearchTemplate.search(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + + System.out.println("SIZE OF HITS ->"+scholixRes.getSearchHits().size()); + + return new ImmutablePair<>(tt,scholixRes.stream().map(SearchHit::getContent).collect(Collectors.toList())); + } + + + + + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java index b12e453c..3e9c5978 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java @@ -1,14 +1,16 @@ package eu.dnetlib.scholix.api.model.v1; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.Scholix; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotBlank; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Objects; -public class ScholixV1 { +public class ScholixV1 implements Serializable { @JsonProperty("linkProvider") private List linkProvider; @@ -156,4 +158,9 @@ public class ScholixV1 { } return o.toString().replace("\n", "\n "); } + + + public static ScholixV1 fromScholix(Scholix input) { + return new ScholixV1(); + } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java index 4957b4f7..d4a5697e 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java @@ -1,6 +1,7 @@ package eu.dnetlib.scholix.api.model.v2; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotBlank; diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java index 87166b25..6651c1b9 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java @@ -1,9 +1,15 @@ package eu.dnetlib.scholix.api.model.v2; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixRelationship; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotNull; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * The type Relationship type. @@ -21,6 +27,14 @@ public class RelationshipType { private String subTypeSchema; + private static Map relationMapping = Stream.of(new String[][] { + { "issupplementto", "IsSupplementTo" }, + { "issupplementedby", "IsSupplementedBy" }, + { "references", "References" }, + { "isreferencedby", "IsReferencedBy" }, + }).collect(Collectors.toMap(data -> data[0], data -> data[1])); + + /** * Gets The relationship type chosen from a Scholix controlled vocabulary * @@ -83,4 +97,13 @@ public class RelationshipType { this.subTypeSchema = subTypeSchema; return this; } + + public static RelationshipType fromScholixRelationship(ScholixRelationship inputRels) { + + return new RelationshipType() + .setName(relationMapping.getOrDefault(inputRels.getName(), "IsRelatedTo")) + .setSubType(inputRels.getName()) + .setSubTypeSchema(inputRels.getSchema()); + + } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java index 61902ade..0f43c77f 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java @@ -1,11 +1,13 @@ package eu.dnetlib.scholix.api.model.v2; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotBlank; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * The type Scholix creator type. @@ -63,4 +65,22 @@ public class ScholixCreatorType { this.name = name; return this; } + + public static ScholixCreatorType fromScholixEntityId(final ScholixEntityId inputCreator) { + if (inputCreator == null) + return null; + ScholixCreatorType instance = new ScholixCreatorType().setName(inputCreator.getName()); + + + if (inputCreator.getIdentifiers()!= null && inputCreator.getIdentifiers().size()>0) + instance.setIdentifier(inputCreator.getIdentifiers() + .stream() + .map(i ->new ScholixIdentifierType() + .setId(i.getIdentifier()) + .setIdScheme(i.getSchema())) + .collect(Collectors.toList())); + return instance; + + + } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java index b023c772..662b9a4f 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java @@ -1,6 +1,7 @@ package eu.dnetlib.scholix.api.model.v2; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixIdentifier; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotBlank; @@ -88,5 +89,17 @@ public class ScholixIdentifierType { } + public static ScholixIdentifierType fromScholixIdentifier(ScholixIdentifier input) { + if (input== null) + return null; + final ScholixIdentifierType instance = new ScholixIdentifierType(); + + instance.setId(input.getIdentifier()); + instance.setIdScheme(input.getSchema()); + instance.setIdURL(input.getUrl()); + return instance; + } + + } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java index b137a9ac..c0fdcc24 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java @@ -1,9 +1,11 @@ package eu.dnetlib.scholix.api.model.v2; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixResource; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * The type Scholix item type. @@ -26,7 +28,7 @@ public class ScholixItemType { private String publicationDate; @JsonProperty("Publisher") - private List publisher = new ArrayList<>(); + private List publisher = new ArrayList<>(); /** @@ -134,7 +136,7 @@ public class ScholixItemType { * * @return the publisher */ - public List getPublisher() { + public List getPublisher() { return publisher; } @@ -144,8 +146,43 @@ public class ScholixItemType { * @param publisher the publisher * @return the publisher */ - public ScholixItemType setPublisher(List publisher) { + public ScholixItemType setPublisher(List publisher) { this.publisher = publisher; return this; } + + + + public static ScholixItemType fromScholixResource(final ScholixResource input) { + if (input == null) + return null; + final ScholixItemType instance = new ScholixItemType(); + instance.setType("publication".equalsIgnoreCase(input.getObjectType())?"literature": "dataset"); + instance.setTitle(input.getTitle()); + + if (input.getIdentifier()!= null) + instance.setIdentifier(input.getIdentifier() + .stream() + .map(ScholixIdentifierType::fromScholixIdentifier ) + .collect(Collectors.toList()) + ); + + + if (input.getPublisher()!= null) { + instance.setPublisher( + input.getPublisher().stream() + .map(ScholixLinkProviderType::fromScholixEntityId) + .collect(Collectors.toList()) + ); + } + + instance.setPublicationDate(input.getPublicationDate()); + if(input.getCreator()!=null) + instance.setCreator(input.getCreator() + .stream() + .map(ScholixCreatorType::fromScholixEntityId) + .collect(Collectors.toList())); + + return instance; + } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java index c14093d3..2fcab411 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java @@ -1,6 +1,7 @@ package eu.dnetlib.scholix.api.model.v2; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotBlank; @@ -8,6 +9,7 @@ import javax.validation.constraints.Size; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; /** * The type Scholix link provider type. @@ -64,4 +66,23 @@ public class ScholixLinkProviderType { this.name = name; return this; } + + + public static ScholixLinkProviderType fromScholixEntityId(final ScholixEntityId provider) { + if (provider == null) + return null; + ScholixLinkProviderType instance = new ScholixLinkProviderType().setName(provider.getName()); + + + if (provider.getIdentifiers()!= null && provider.getIdentifiers().size()>0) + instance.setIdentifier(provider.getIdentifiers() + .stream() + .map(i ->new ScholixIdentifierType() + .setId(i.getIdentifier()) + .setIdScheme(i.getSchema())) + .collect(Collectors.toList())); + return instance; + + + } } \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java index 3c994c96..9deaa803 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java @@ -1,11 +1,12 @@ package eu.dnetlib.scholix.api.model.v2; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.Scholix; import io.swagger.v3.oas.annotations.media.Schema; - import javax.validation.constraints.NotBlank; import java.io.Serializable; import java.util.List; +import java.util.stream.Collectors; /** * The type Scholix type. @@ -33,7 +34,7 @@ public class ScholixType implements Serializable { private String licenseURL ; @JsonProperty("LinkProvider") - private List linkProvider ; + private List linkProvider ; @JsonProperty("LinkPublicationDate") private String linkPublicationDate ; @@ -49,6 +50,11 @@ public class ScholixType implements Serializable { return relationshipType; } + /** + * Sets relationship type. + * + * @param relationshipType the relationship type + */ public void setRelationshipType(RelationshipType relationshipType) { this.relationshipType = relationshipType; } @@ -114,7 +120,6 @@ public class ScholixType implements Serializable { * * @return the license url */ - @Schema(description = "The URL of the license for the Scholix Link Information Package") public String getLicenseURL() { return licenseURL; @@ -135,7 +140,7 @@ public class ScholixType implements Serializable { * @return the link provider */ @Schema(description = "The source(s) of this Link Information Package") - public List getLinkProvider() { + public List getLinkProvider() { return linkProvider; } @@ -144,7 +149,7 @@ public class ScholixType implements Serializable { * * @param linkProvider the link provider */ - public void setLinkProvider(List linkProvider) { + public void setLinkProvider(List linkProvider) { this.linkProvider = linkProvider; } @@ -167,4 +172,25 @@ public class ScholixType implements Serializable { public void setLinkPublicationDate(String linkPublicationDate) { this.linkPublicationDate = linkPublicationDate; } + + + + public static ScholixType fromScholix(Scholix input) { + final ScholixType instance = new ScholixType(); + instance.setLinkPublicationDate(input.getPublicationDate()); + instance.setHarvestDate(input.getPublicationDate()); + instance.setRelationshipType(RelationshipType.fromScholixRelationship(input.getRelationship())); + + if(input.getLinkprovider()!= null && input.getLinkprovider().size()>0) + instance.setLinkProvider(input.getLinkprovider() + .stream() + .map(ScholixLinkProviderType::fromScholixEntityId) + .collect(Collectors.toList()) + ); + + + instance.setSource(ScholixItemType.fromScholixResource(input.getSource())); + instance.setTarget(ScholixItemType.fromScholixResource(input.getTarget())); + return instance; + } } diff --git a/apps/scholexplorer-api/src/main/resources/application.properties b/apps/scholexplorer-api/src/main/resources/application.properties index 6bcb8ef7..beb6bf51 100644 --- a/apps/scholexplorer-api/src/main/resources/application.properties +++ b/apps/scholexplorer-api/src/main/resources/application.properties @@ -20,4 +20,7 @@ management.metrics.distribution.percentiles.http.server.requests=0.5, 0.9, 0.95, - +scholix.elastic.clusterNodes = localhost:9200 +scholix.elastic.indexName = dli_scholix +scholix.elastic.socketTimeout = 60000 +scholix.elastic.connectionTimeout= 60000 diff --git a/pom.xml b/pom.xml index 8f02c9d7..34ea20d2 100644 --- a/pom.xml +++ b/pom.xml @@ -233,12 +233,7 @@ 3.0.0 - - org.springframework.data - spring-data-elasticsearch - 4.3.1 - - + org.apache.hadoop -- 2.17.1 From b776a3c7cd258fd32050dd5b269fd4dd2e52da2d Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Tue, 8 Feb 2022 09:57:45 +0100 Subject: [PATCH 5/9] Implemented ElasticSearch Connection Pool --- apps/scholexplorer-api/pom.xml | 5 + .../dnetlib/scholix/api/MainApplication.java | 36 ++--- .../dnetlib/scholix/api/RestClientConfig.java | 30 ++-- .../scholix/api/ScholixAPIConstants.java | 23 +++ .../api/controller/ScholixControllerV2.java | 27 ++-- .../api/index/ElasticSearchClientFactory.java | 66 +++++++++ .../scholix/api/index/ElasticSearchPool.java | 19 +++ .../api/index/ElasticSearchProperties.java | 3 +- .../eu/dnetlib/scholix/api/index/Pool.java | 138 ++++++++++++++++++ .../api/index/ScholixIndexManager.java | 14 +- pom.xml | 7 + 11 files changed, 312 insertions(+), 56 deletions(-) create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixAPIConstants.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchClientFactory.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchPool.java create mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/Pool.java diff --git a/apps/scholexplorer-api/pom.xml b/apps/scholexplorer-api/pom.xml index 04b31ca5..58eb06ea 100644 --- a/apps/scholexplorer-api/pom.xml +++ b/apps/scholexplorer-api/pom.xml @@ -30,6 +30,11 @@ dhp-schemas + + org.apache.commons + commons-pool2 + + diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java index 2ce535e4..98de0853 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/MainApplication.java @@ -42,11 +42,6 @@ public class MainApplication extends AbstractDnetApp { @Value("${dhp.swagger.api.basePath}") private String swaggerPath; - final String descriptionAPI = "

\"ScholeXplorer\"

" + - "The Scholix Swagger API allows clients to run REST queries over the Scholexplorer index in order to fetch links matching given criteria. In the current version, clients can search for:" + - "
  • Links whose source object has a given PID or PID type
  • " + - "
  • Links whose source object has been published by a given data source (\"data source as publisher\")
  • " + - "
  • Links that were collected from a given data source (\"data source as provider\").
"; public static void main(final String[] args) { SpringApplication.run(MainApplication.class, args); @@ -57,20 +52,17 @@ public class MainApplication extends AbstractDnetApp { @Bean public TaggedCounter myCounter(MeterRegistry meterRegistry) { - return new TaggedCounter("scholixLinkCounter", "links",meterRegistry); + return new TaggedCounter(ScholixAPIConstants.SCHOLIX_MANAGER_COUNTER_NAME, ScholixAPIConstants.SCHOLIX_MANAGER_TAG_NAME,meterRegistry); } @Bean public TimedAspect timedAspect(MeterRegistry meterRegistry) { - - MeterFilter mf = new MeterFilter() { @Override public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) { - if (id.getName().startsWith("scholix")) { + if (id.getName().startsWith(ScholixAPIConstants.SCHOLIX_COUNTER_PREFIX)) { return DistributionStatisticConfig.builder() - .percentiles(0.20, 0.50, 0.75,0.95) .percentilesHistogram(false) .serviceLevelObjectives( histogramValues) .build() @@ -79,31 +71,24 @@ public class MainApplication extends AbstractDnetApp { return config; } }; - - meterRegistry.config().meterFilter(mf); - - - return new TimedAspect(meterRegistry); } - - @Override protected void configSwagger(final Docket docket) { docket .host(swaggetHost) .pathMapping(swaggerPath) - .groupName("Scholexplorer V1") + .groupName(ScholixAPIConstants.API_V1_NAME) .select() .apis(RequestHandlerSelectors.any()) .paths(p -> p.startsWith("/v1")) .build() .apiInfo(new ApiInfoBuilder() - .title("Scholexplorer API V1.0") - .description(descriptionAPI) + .title(ScholixAPIConstants.API_V1_NAME) + .description(ScholixAPIConstants.API_DESCRIPTION) .version("1.0") .contact(ApiInfo.DEFAULT_CONTACT) .license("Apache 2.0") @@ -113,23 +98,20 @@ public class MainApplication extends AbstractDnetApp { - @Bean (name = "SpringDOcketv2") + @Bean (name = "SpringDocketv2") public Docket v2Docket() { - - final Docket docket = new Docket(DocumentationType.SWAGGER_2); - docket .host(swaggetHost) .pathMapping(swaggerPath) - .groupName("Scholexplorer V2") + .groupName(ScholixAPIConstants.API_V2_NAME) .select() .apis(RequestHandlerSelectors.any()) .paths(p -> p.startsWith("/v2")) .build() .apiInfo(new ApiInfoBuilder() - .title("Scholexplorer API V2.0") - .description(descriptionAPI) + .title(ScholixAPIConstants.API_V2_NAME) + .description(ScholixAPIConstants.API_DESCRIPTION) .version("2.0") .contact(ApiInfo.DEFAULT_CONTACT) .license("Apache 2.0") diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java index 078e489b..92b9a27f 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java @@ -1,5 +1,6 @@ package eu.dnetlib.scholix.api; +import eu.dnetlib.scholix.api.index.ElasticSearchPool; import eu.dnetlib.scholix.api.index.ElasticSearchProperties; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Autowired; @@ -12,20 +13,29 @@ import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfig import java.time.Duration; @Configuration -public class RestClientConfig extends AbstractElasticsearchConfiguration { +public class RestClientConfig { @Autowired private ElasticSearchProperties elasticSearchProperties; - @Override - @Bean - public RestHighLevelClient elasticsearchClient() { - final ClientConfiguration clientConfiguration = ClientConfiguration.builder() - .connectedTo(elasticSearchProperties.getClusterNodes().split(",")) - .withConnectTimeout(elasticSearchProperties.getConnectionTimeout()) - .withSocketTimeout(elasticSearchProperties.getSocketTimeout()) - .build(); - return RestClients.create(clientConfiguration).rest(); + @Bean + public ElasticSearchPool connectionPool() { + + ElasticSearchPool pool = new ElasticSearchPool(elasticSearchProperties); + return pool; } + + +// @Override +// @Bean +// public RestHighLevelClient elasticsearchClient() { +// +// final ClientConfiguration clientConfiguration = ClientConfiguration.builder() +// .connectedTo(elasticSearchProperties.getClusterNodes().split(",")) +// .withConnectTimeout(elasticSearchProperties.getConnectionTimeout()) +// .withSocketTimeout(elasticSearchProperties.getSocketTimeout()) +// .build(); +// return RestClients.create(clientConfiguration).rest(); +// } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixAPIConstants.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixAPIConstants.java new file mode 100644 index 00000000..6f0b8a2d --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/ScholixAPIConstants.java @@ -0,0 +1,23 @@ +package eu.dnetlib.scholix.api; + +public class ScholixAPIConstants { + + public static final String API_V1_NAME = "Scholexplorer API V1.0"; + public static final String API_V2_NAME = "Scholexplorer API V2.0"; + + public static String API_DESCRIPTION ="

\"ScholeXplorer\"

" + + "The Scholix Swagger API allows clients to run REST queries over the Scholexplorer index in order to fetch links matching given criteria. In the current version, clients can search for:" + + "
  • Links whose source object has a given PID or PID type
  • " + + "
  • Links whose source object has been published by a given data source (\"data source as publisher\")
  • " + + "
  • Links that were collected from a given data source (\"data source as provider\").
"; + + + public static String SCHOLIX_MANAGER_COUNTER_NAME= "scholixLinkCounter"; + public static final String SCHOLIX_MANAGER_TAG_NAME = "links"; + + public static String SCHOLIX_COUNTER_PREFIX = "scholix"; + + + + +} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java index 116a1e77..b54a65cb 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java @@ -4,6 +4,7 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; import eu.dnetlib.dhp.schema.sx.scholix.ScholixIdentifier; import eu.dnetlib.scholix.api.ScholixAPIVersion; +import eu.dnetlib.scholix.api.ScholixException; import eu.dnetlib.scholix.api.index.ScholixIndexManager; import eu.dnetlib.scholix.api.model.v2.PageResultType; import eu.dnetlib.scholix.api.model.v2.ScholixType; @@ -13,6 +14,7 @@ import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import eu.dnetlib.dhp.schema.sx.scholix.Scholix; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.lucene.search.join.ScoreMode; import org.elasticsearch.index.query.BoolQueryBuilder; @@ -77,19 +79,20 @@ public class ScholixControllerV2 extends AbstractDnetController { @Parameter(in = ParameterIn.QUERY, description = "select page of result") Integer page) throws Exception { + if (StringUtils.isEmpty(sourcePid) && StringUtils.isEmpty(targetPid) && StringUtils.isEmpty(sourcePublisher)&& StringUtils.isEmpty(targetPublisher)&& StringUtils.isEmpty(linkProvider)) + throw new ScholixException("The method requires one of the following parameters: sourcePid, targetPid, sourcePublisher, targetPublisher, linkProvider"); - - final int currentPage = page!= null? page : 0; - - System.out.println(currentPage); - Pair> scholixResult = manager.linksFromPid(ScholixAPIVersion.V2, linkProvider, targetPid, targetPidType, targetPublisher, targetType, sourcePid, sourcePidType, sourcePublisher, sourceType, harvestedAfter, currentPage); - - final PageResultType pageResult = new PageResultType(); - pageResult.setTotalPages(scholixResult.getLeft().intValue() / 10); - pageResult.setTotalLinks(scholixResult.getLeft().intValue()); - pageResult.setResult(scholixResult.getRight().stream().map(ScholixType::fromScholix).collect(Collectors.toList())); - - return pageResult; + try { + final int currentPage = page != null ? page : 0; + Pair> scholixResult = manager.linksFromPid(ScholixAPIVersion.V2, linkProvider, targetPid, targetPidType, targetPublisher, targetType, sourcePid, sourcePidType, sourcePublisher, sourceType, harvestedAfter, currentPage); + final PageResultType pageResult = new PageResultType(); + pageResult.setTotalPages(scholixResult.getLeft().intValue() / 10); + pageResult.setTotalLinks(scholixResult.getLeft().intValue()); + pageResult.setResult(scholixResult.getRight().stream().map(ScholixType::fromScholix).collect(Collectors.toList())); + return pageResult; + } catch (Throwable e) { + throw new ScholixException("Error on requesting url ", e); + } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchClientFactory.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchClientFactory.java new file mode 100644 index 00000000..85893680 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchClientFactory.java @@ -0,0 +1,66 @@ +package eu.dnetlib.scholix.api.index; + +import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.PooledObjectFactory; +import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.data.elasticsearch.client.ClientConfiguration; +import org.springframework.data.elasticsearch.client.RestClients; + +public class ElasticSearchClientFactory implements PooledObjectFactory { + + private ElasticSearchProperties elasticSearchProperties; + + + public ElasticSearchClientFactory(final ElasticSearchProperties elasticSearchProperties){ + this.elasticSearchProperties = elasticSearchProperties; + + } + + public PooledObject makeObject() throws Exception { + + + + final ClientConfiguration clientConfiguration = ClientConfiguration.builder() + .connectedTo(elasticSearchProperties.getClusterNodes().split(",")) + .withConnectTimeout(elasticSearchProperties.getConnectionTimeout()) + .withSocketTimeout(elasticSearchProperties.getSocketTimeout()) + .build(); + RestHighLevelClient cc = RestClients.create(clientConfiguration).rest(); + + + return new DefaultPooledObject(cc); + } + + public void destroyObject(PooledObject pooledObject) throws Exception { + RestHighLevelClient client = pooledObject.getObject(); + if(client!=null&&client.ping(RequestOptions.DEFAULT)){ + try { + client.close(); + }catch (Exception e){ + //ignore + } + } + } + + public boolean validateObject(PooledObject pooledObject) { + RestHighLevelClient client = pooledObject.getObject(); + try { + return client.ping(RequestOptions.DEFAULT); + }catch(Exception e){ + return false; + } + } + + public void activateObject(PooledObject pooledObject) throws Exception { + RestHighLevelClient client = pooledObject.getObject(); + boolean response = client.ping(RequestOptions.DEFAULT); + } + + public void passivateObject(PooledObject pooledObject) throws Exception { + //nothing + } + + +} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchPool.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchPool.java new file mode 100644 index 00000000..6bf79fd3 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchPool.java @@ -0,0 +1,19 @@ +package eu.dnetlib.scholix.api.index; + +import org.elasticsearch.client.RestHighLevelClient; + +public class ElasticSearchPool extends Pool { + + private final ElasticSearchProperties elasticSearchProperties; + + public ElasticSearchPool(ElasticSearchProperties elasticSearchProperties){ + super(elasticSearchProperties, new ElasticSearchClientFactory(elasticSearchProperties)); + this.elasticSearchProperties = elasticSearchProperties; + } + + public ElasticSearchProperties getElasticSearchProperties() { + return elasticSearchProperties; + } +} + + diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchProperties.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchProperties.java index 38e7016e..15f53154 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchProperties.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchProperties.java @@ -1,5 +1,6 @@ package eu.dnetlib.scholix.api.index; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -10,7 +11,7 @@ import javax.validation.constraints.NotNull; */ @Component("elasticSearchProperties") @ConfigurationProperties(prefix = "scholix.elastic") -public class ElasticSearchProperties { +public class ElasticSearchProperties extends GenericObjectPoolConfig { @NotNull private String clusterNodes; diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/Pool.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/Pool.java new file mode 100644 index 00000000..53647ac7 --- /dev/null +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/Pool.java @@ -0,0 +1,138 @@ +package eu.dnetlib.scholix.api.index; + +import eu.dnetlib.scholix.api.ScholixException; +import org.apache.commons.pool2.PooledObjectFactory; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; + +public class Pool implements Cloneable { + + protected GenericObjectPool internalPool ; + + public Pool(){ + super(); + } + + public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory factory){ + initPool(poolConfig, factory); + } + + public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory factory) { + + if (this.internalPool != null) { + try { + closeInternalPool(); + } catch (Exception e) { + } + } + + this.internalPool = new GenericObjectPool(factory, poolConfig); + } + + protected void closeInternalPool() throws ScholixException { + try { + internalPool.close(); + } catch (Exception e) { + throw new ScholixException("Could not destroy the pool", e); + } + } + + public T getResource() throws ScholixException { + try { + return internalPool.borrowObject(); + } catch (Exception e) { + throw new ScholixException("Could not get a resource from the pool", e); + } + } + + + public void returnResource(final T resource) throws ScholixException { + if (resource != null) { + returnResourceObject(resource); + } + } + + private void returnResourceObject(final T resource) throws ScholixException { + if (resource == null) { + return; + } + try { + internalPool.returnObject(resource); + } catch (Exception e) { + throw new ScholixException("Could not return the resource to the pool", e); + } + } + + public void returnBrokenResource(final T resource) throws ScholixException { + if (resource != null) { + returnBrokenResourceObject(resource); + } + } + + private void returnBrokenResourceObject(T resource) throws ScholixException { + try { + internalPool.invalidateObject(resource); + } catch (Exception e) { + throw new ScholixException("Could not return the resource to the pool", e); + } + } + + public void destroy() throws ScholixException { + closeInternalPool(); + } + + + public int getNumActive() { + if (poolInactive()) { + return -1; + } + + return this.internalPool.getNumActive(); + } + + public int getNumIdle() { + if (poolInactive()) { + return -1; + } + + return this.internalPool.getNumIdle(); + } + + public int getNumWaiters() { + if (poolInactive()) { + return -1; + } + + return this.internalPool.getNumWaiters(); + } + + public long getMeanBorrowWaitTimeMillis() { + if (poolInactive()) { + return -1; + } + + return this.internalPool.getMeanBorrowWaitTimeMillis(); + } + + public long getMaxBorrowWaitTimeMillis() { + if (poolInactive()) { + return -1; + } + + return this.internalPool.getMaxBorrowWaitTimeMillis(); + } + + private boolean poolInactive() { + return this.internalPool == null || this.internalPool.isClosed(); + } + + public void addObjects(int count) throws Exception { + try { + for (int i = 0; i < count; i++) { + this.internalPool.addObject(); + } + } catch (Exception e) { + throw new Exception("Error trying to add idle objects", e); + } + } +} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java index daefcab3..c958aa53 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java @@ -11,13 +11,14 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.apache.lucene.search.join.ScoreMode; +import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.NestedQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.TermQueryBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; @@ -45,7 +46,7 @@ public class ScholixIndexManager { * The Elasticsearch template. */ @Autowired - ElasticsearchOperations elasticsearchTemplate; + ElasticSearchPool connectionPool; /** * The My counter. @@ -205,12 +206,13 @@ public class ScholixIndexManager { .withPageable(PageRequest.of(page,10)) .build(); - long tt = elasticsearchTemplate.count(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); - System.out.println(tt); + RestHighLevelClient client = connectionPool.getResource(); + ElasticsearchRestTemplate template = new ElasticsearchRestTemplate(client); + long tt = template.count(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); - SearchHits scholixRes = elasticsearchTemplate.search(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + SearchHits scholixRes = template.search(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); - System.out.println("SIZE OF HITS ->"+scholixRes.getSearchHits().size()); + connectionPool.returnResource(client); return new ImmutablePair<>(tt,scholixRes.stream().map(SearchHit::getContent).collect(Collectors.toList())); } diff --git a/pom.xml b/pom.xml index 34ea20d2..d3e31c1e 100644 --- a/pom.xml +++ b/pom.xml @@ -142,6 +142,13 @@ test + + org.apache.commons + commons-pool2 + 2.11.1 + + +
-- 2.17.1 From fc74c86ba9da7331888377f65c58592a6efcc643 Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Wed, 9 Feb 2022 11:33:09 +0100 Subject: [PATCH 6/9] Implemented LinkProvider aggregations --- .../dnetlib/scholix/api/RestClientConfig.java | 19 +--- .../api/controller/LinkProviderV2.java | 26 ++++-- .../api/index/ElasticSearchClientFactory.java | 36 ++++--- .../scholix/api/index/ElasticSearchPool.java | 17 +++- .../eu/dnetlib/scholix/api/index/Pool.java | 93 +++++++++++++++++++ .../api/index/ScholixIndexManager.java | 63 ++++++++++--- 6 files changed, 203 insertions(+), 51 deletions(-) diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java index 92b9a27f..1e9eab85 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/RestClientConfig.java @@ -2,15 +2,9 @@ package eu.dnetlib.scholix.api; import eu.dnetlib.scholix.api.index.ElasticSearchPool; import eu.dnetlib.scholix.api.index.ElasticSearchProperties; -import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.elasticsearch.client.ClientConfiguration; -import org.springframework.data.elasticsearch.client.RestClients; -import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; - -import java.time.Duration; @Configuration public class RestClientConfig { @@ -22,20 +16,11 @@ public class RestClientConfig { @Bean public ElasticSearchPool connectionPool() { + elasticSearchProperties.setMaxIdle(5); + elasticSearchProperties.setMaxTotal(10); ElasticSearchPool pool = new ElasticSearchPool(elasticSearchProperties); return pool; } -// @Override -// @Bean -// public RestHighLevelClient elasticsearchClient() { -// -// final ClientConfiguration clientConfiguration = ClientConfiguration.builder() -// .connectedTo(elasticSearchProperties.getClusterNodes().split(",")) -// .withConnectTimeout(elasticSearchProperties.getConnectionTimeout()) -// .withSocketTimeout(elasticSearchProperties.getSocketTimeout()) -// .build(); -// return RestClients.create(clientConfiguration).rest(); -// } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java index 3aa1514f..73014644 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java @@ -1,16 +1,22 @@ package eu.dnetlib.scholix.api.controller; +import eu.dnetlib.scholix.api.ScholixException; +import eu.dnetlib.scholix.api.index.ScholixIndexManager; import eu.dnetlib.scholix.api.model.v2.LinkProviderType; import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; @RestController @RequestMapping("/v2") @@ -19,17 +25,25 @@ import java.util.List; }) public class LinkProviderV2 { + @Autowired + ScholixIndexManager manager; + @Operation( summary = "Get all Link Providers", description = "Return a list of link provider and relative number of relations") @GetMapping("/LinkProvider") public List getLinkProviders( @Parameter(in = ParameterIn.QUERY, description = "Filter the link provider name") @RequestParam(required = false) String name - ) { - return Arrays.asList( - new LinkProviderType().name("pippo").totalRelationships(30), - new LinkProviderType().name("pluto").totalRelationships(30), - new LinkProviderType().name("peppa").totalRelationships(30) - ); + ) throws ScholixException { + + List> result = manager.linksByProvider(null); + + if (result==null) + return new ArrayList<>(); + + return result.stream().map(s -> new LinkProviderType().name(s.getLeft()).totalRelationships(s.getValue().intValue())).collect(Collectors.toList()); + + + } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchClientFactory.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchClientFactory.java index 85893680..b00b6dc3 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchClientFactory.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchClientFactory.java @@ -1,5 +1,7 @@ package eu.dnetlib.scholix.api.index; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; @@ -7,20 +9,27 @@ import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.data.elasticsearch.client.ClientConfiguration; import org.springframework.data.elasticsearch.client.RestClients; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; -public class ElasticSearchClientFactory implements PooledObjectFactory { +/** + * The type Elastic search client factory. + */ +public class ElasticSearchClientFactory implements PooledObjectFactory> { - private ElasticSearchProperties elasticSearchProperties; + private final ElasticSearchProperties elasticSearchProperties; + /** + * Instantiates a new Elastic search client factory. + * + * @param elasticSearchProperties the elastic search properties + */ public ElasticSearchClientFactory(final ElasticSearchProperties elasticSearchProperties){ this.elasticSearchProperties = elasticSearchProperties; } - public PooledObject makeObject() throws Exception { - - + public PooledObject> makeObject() throws Exception { final ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo(elasticSearchProperties.getClusterNodes().split(",")) @@ -29,12 +38,11 @@ public class ElasticSearchClientFactory implements PooledObjectFactory(new ImmutablePair<>(cc, new ElasticsearchRestTemplate(cc))); } - public void destroyObject(PooledObject pooledObject) throws Exception { - RestHighLevelClient client = pooledObject.getObject(); + public void destroyObject(PooledObject> pooledObject) throws Exception { + RestHighLevelClient client = pooledObject.getObject().getLeft(); if(client!=null&&client.ping(RequestOptions.DEFAULT)){ try { client.close(); @@ -44,8 +52,8 @@ public class ElasticSearchClientFactory implements PooledObjectFactory pooledObject) { - RestHighLevelClient client = pooledObject.getObject(); + public boolean validateObject(PooledObject> pooledObject) { + RestHighLevelClient client = pooledObject.getObject().getLeft(); try { return client.ping(RequestOptions.DEFAULT); }catch(Exception e){ @@ -53,12 +61,12 @@ public class ElasticSearchClientFactory implements PooledObjectFactory pooledObject) throws Exception { - RestHighLevelClient client = pooledObject.getObject(); + public void activateObject(PooledObject> pooledObject) throws Exception { + RestHighLevelClient client = pooledObject.getObject().getLeft(); boolean response = client.ping(RequestOptions.DEFAULT); } - public void passivateObject(PooledObject pooledObject) throws Exception { + public void passivateObject(PooledObject> pooledObject) throws Exception { //nothing } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchPool.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchPool.java index 6bf79fd3..04a88afb 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchPool.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ElasticSearchPool.java @@ -1,16 +1,31 @@ package eu.dnetlib.scholix.api.index; +import org.apache.commons.lang3.tuple.Pair; import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; -public class ElasticSearchPool extends Pool { +/** + * The type Elastic search pool. + */ +public class ElasticSearchPool extends Pool> { private final ElasticSearchProperties elasticSearchProperties; + /** + * Instantiates a new Elastic search pool. + * + * @param elasticSearchProperties the elastic search properties + */ public ElasticSearchPool(ElasticSearchProperties elasticSearchProperties){ super(elasticSearchProperties, new ElasticSearchClientFactory(elasticSearchProperties)); this.elasticSearchProperties = elasticSearchProperties; } + /** + * Gets elastic search properties. + * + * @return the elastic search properties + */ public ElasticSearchProperties getElasticSearchProperties() { return elasticSearchProperties; } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/Pool.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/Pool.java index 53647ac7..b5e3849f 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/Pool.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/Pool.java @@ -5,18 +5,52 @@ import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +/** + * When using the Java High Level REST Client provided by the Elasticsearch official website, it is found that there is no in the client API. + * Connecting to connect the pool, create a new connection every time, this is impact in high concurrency situation, so it is ready to be on the client + * API increases the concept of pool. + * + * Fortunately, we don't need to turn your weight to write the implementation of the connection pool, because Apache provides us with the general framework of the connection pool. + * Commons-pool2, and we only need to implement some logic according to the frame design. Used in the REDIS client API + * Jedispool is based on Commons-pool2 implementation. + * + * Let's take a look at how to achieve it. + * + * First we have to create a pool class, this pool introduces GenericObjectPool in Commons-pool2 through dependent manner. In this class + * In, we define how to borrow objects and returns objects from the pool. + * + * @param the type parameter + */ public class Pool implements Cloneable { + /** + * The Internal pool. + */ protected GenericObjectPool internalPool ; + /** + * Instantiates a new Pool. + */ public Pool(){ super(); } + /** + * Instantiates a new Pool. + * + * @param poolConfig the pool config + * @param factory the factory + */ public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory factory){ initPool(poolConfig, factory); } + /** + * Init pool. + * + * @param poolConfig the pool config + * @param factory the factory + */ public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory factory) { if (this.internalPool != null) { @@ -29,6 +63,11 @@ public class Pool implements Cloneable { this.internalPool = new GenericObjectPool(factory, poolConfig); } + /** + * Close internal pool. + * + * @throws ScholixException the scholix exception + */ protected void closeInternalPool() throws ScholixException { try { internalPool.close(); @@ -37,6 +76,12 @@ public class Pool implements Cloneable { } } + /** + * Gets resource. + * + * @return the resource + * @throws ScholixException the scholix exception + */ public T getResource() throws ScholixException { try { return internalPool.borrowObject(); @@ -46,6 +91,12 @@ public class Pool implements Cloneable { } + /** + * Return resource. + * + * @param resource the resource + * @throws ScholixException the scholix exception + */ public void returnResource(final T resource) throws ScholixException { if (resource != null) { returnResourceObject(resource); @@ -63,6 +114,12 @@ public class Pool implements Cloneable { } } + /** + * Return broken resource. + * + * @param resource the resource + * @throws ScholixException the scholix exception + */ public void returnBrokenResource(final T resource) throws ScholixException { if (resource != null) { returnBrokenResourceObject(resource); @@ -77,11 +134,21 @@ public class Pool implements Cloneable { } } + /** + * Destroy. + * + * @throws ScholixException the scholix exception + */ public void destroy() throws ScholixException { closeInternalPool(); } + /** + * Gets num active. + * + * @return the num active + */ public int getNumActive() { if (poolInactive()) { return -1; @@ -90,6 +157,11 @@ public class Pool implements Cloneable { return this.internalPool.getNumActive(); } + /** + * Gets num idle. + * + * @return the num idle + */ public int getNumIdle() { if (poolInactive()) { return -1; @@ -98,6 +170,11 @@ public class Pool implements Cloneable { return this.internalPool.getNumIdle(); } + /** + * Gets num waiters. + * + * @return the num waiters + */ public int getNumWaiters() { if (poolInactive()) { return -1; @@ -106,6 +183,11 @@ public class Pool implements Cloneable { return this.internalPool.getNumWaiters(); } + /** + * Gets mean borrow wait time millis. + * + * @return the mean borrow wait time millis + */ public long getMeanBorrowWaitTimeMillis() { if (poolInactive()) { return -1; @@ -114,6 +196,11 @@ public class Pool implements Cloneable { return this.internalPool.getMeanBorrowWaitTimeMillis(); } + /** + * Gets max borrow wait time millis. + * + * @return the max borrow wait time millis + */ public long getMaxBorrowWaitTimeMillis() { if (poolInactive()) { return -1; @@ -126,6 +213,12 @@ public class Pool implements Cloneable { return this.internalPool == null || this.internalPool.isClosed(); } + /** + * Add objects. + * + * @param count the count + * @throws Exception the exception + */ public void addObjects(int count) throws Exception { try { for (int i = 0; i < count; i++) { diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java index c958aa53..f93f8d02 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java @@ -11,11 +11,14 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.apache.lucene.search.join.ScoreMode; +import org.elasticsearch.action.search.SearchType; import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.NestedQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.index.query.TermQueryBuilder; +import org.elasticsearch.index.query.*; +import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.AggregationBuilders; +import org.elasticsearch.search.aggregations.Aggregations; +import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested; +import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; @@ -114,8 +117,6 @@ public class ScholixIndexManager { } private void incrementPidCounter(pidTypePrefix prefix, String value) { - - switch (value.toLowerCase()){ case "doi": { myCounter.increment(String.format("%s_doi", prefix)); @@ -127,12 +128,46 @@ public class ScholixIndexManager { } default: myCounter.increment(String.format("%s_other", prefix)); - } - } + public List> linksByProvider(final String filterName) throws ScholixException { + + final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(QueryBuilders.matchAllQuery()) + .withSearchType(SearchType.DEFAULT) + .withPageable(PageRequest.of(0,10)) + .addAggregation(AggregationBuilders.nested("nested", "linkprovider") + .subAggregation(AggregationBuilders.terms("by_map").field("linkprovider.name").size(100).minDocCount(1))) + .build(); + + + Pair resource = connectionPool.getResource(); + ElasticsearchRestTemplate client = resource.getValue(); + final SearchHits hits = client.search(searchQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + + final Aggregations aggregations = hits.getAggregations(); + + + if(aggregations == null) + return null; + + final Aggregation aggByMap = ((ParsedNested) aggregations.asMap().get("nested")).getAggregations().asMap().get("by_map"); + + + return ((ParsedStringTerms) aggByMap).getBuckets() + .stream() + .map(b -> new ImmutablePair<>(b.getKeyAsString(), b.getDocCount())) + .collect(Collectors.toList()); + } + + + + + + + /** * Links from pid pair. * @@ -206,13 +241,15 @@ public class ScholixIndexManager { .withPageable(PageRequest.of(page,10)) .build(); - RestHighLevelClient client = connectionPool.getResource(); - ElasticsearchRestTemplate template = new ElasticsearchRestTemplate(client); - long tt = template.count(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); - SearchHits scholixRes = template.search(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + Pair resource = connectionPool.getResource(); + ElasticsearchRestTemplate client = resource.getValue(); - connectionPool.returnResource(client); + long tt = client.count(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + + SearchHits scholixRes = client.search(finalQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + + connectionPool.returnResource(resource); return new ImmutablePair<>(tt,scholixRes.stream().map(SearchHit::getContent).collect(Collectors.toList())); } -- 2.17.1 From d5a089869c7d46fdae5bbf28d5ba00ecfd6c0886 Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Mon, 14 Feb 2022 09:16:37 +0100 Subject: [PATCH 7/9] implemented Scholix V1 APIs --- apps/scholexplorer-api/pom.xml | 6 - .../scholix/api/controller/DatasourceV1.java | 26 ++++- .../api/controller/LinkProviderV2.java | 3 +- .../api/controller/LinkPublisherV2.java | 36 +++--- .../api/controller/ScholixControllerV1.java | 54 +++++++-- .../api/controller/ScholixControllerV2.java | 26 +---- .../api/index/ScholixIndexManager.java | 102 +++++++++++++---- .../scholix/api/model/v1/ScholixCreator.java | 67 +++-------- .../api/model/v1/ScholixIdentifier.java | 61 +++------- .../scholix/api/model/v1/ScholixItem.java | 105 ++++++++---------- .../scholix/api/model/v1/ScholixProvider.java | 27 ++++- .../api/model/v1/ScholixRelationship.java | 15 +++ .../scholix/api/model/v1/ScholixV1.java | 20 +++- .../api/model/v2/RelationshipType.java | 2 +- .../eu/dnetlib/scholix/test/QueryTest.java | 18 +++ 15 files changed, 323 insertions(+), 245 deletions(-) create mode 100644 apps/scholexplorer-api/src/test/java/eu/dnetlib/scholix/test/QueryTest.java diff --git a/apps/scholexplorer-api/pom.xml b/apps/scholexplorer-api/pom.xml index 58eb06ea..687a6c1e 100644 --- a/apps/scholexplorer-api/pom.xml +++ b/apps/scholexplorer-api/pom.xml @@ -14,12 +14,10 @@ scholexplorer-api - org.springframework.data spring-data-elasticsearch - org.springframework.boot spring-boot-starter-test @@ -29,15 +27,11 @@ eu.dnetlib.dhp dhp-schemas - org.apache.commons commons-pool2 - - - diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java index 684ec92f..87616b2b 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java @@ -1,16 +1,22 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; +import eu.dnetlib.scholix.api.ScholixException; +import eu.dnetlib.scholix.api.index.ScholixIndexManager; import eu.dnetlib.scholix.api.model.v1.LinkPublisher; import io.micrometer.core.annotation.Timed; import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; @RestController @@ -20,16 +26,24 @@ import java.util.List; }) public class DatasourceV1 extends AbstractDnetController { + @Autowired + private ScholixIndexManager manager; + @Timed(value = "scholix.v1.datasources", description = "Time taken to return all datasources on Version 1.0 of Scholix") @Operation( summary = "Get all Datasources", description = "returns a list of all datasources") @GetMapping("/listDatasources") - public List getDatasources() { - return Arrays.asList( - new LinkPublisher().name("pippo").totalRelationships(30), - new LinkPublisher().name("pluto").totalRelationships(30), - new LinkPublisher().name("peppa").totalRelationships(30) - ); + public List getDatasources() throws ScholixException { + + + final List> result = manager.totalLinksByProvider(null); + + if (result == null) + return new ArrayList<>(); + + return result.stream().map(p -> new LinkPublisher().name(p.getKey()).totalRelationships(p.getValue().intValue())).collect(Collectors.toList()); + + } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java index 73014644..286e0eb9 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java @@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -36,7 +35,7 @@ public class LinkProviderV2 { @Parameter(in = ParameterIn.QUERY, description = "Filter the link provider name") @RequestParam(required = false) String name ) throws ScholixException { - List> result = manager.linksByProvider(null); + List> result = manager.totalLinksByProvider(name); if (result==null) return new ArrayList<>(); diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java index 41883343..88e2e6a6 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java @@ -1,16 +1,21 @@ package eu.dnetlib.scholix.api.controller; +import eu.dnetlib.scholix.api.ScholixException; +import eu.dnetlib.scholix.api.index.ScholixIndexManager; import eu.dnetlib.scholix.api.model.v2.LinkProviderType; import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @RestController @RequestMapping("/v2/LinkPublisher") @@ -19,6 +24,9 @@ import java.util.List; }) public class LinkPublisherV2 { + @Autowired + ScholixIndexManager manager; + @Operation( summary = "Get All Publishers that provide source object", description = "Return a List of all Publishers that provide source objects in Scholix " + @@ -26,12 +34,13 @@ public class LinkPublisherV2 { @GetMapping("/inSource") public List getInSource( @Parameter(in = ParameterIn.QUERY, description = "Filter the link publisher name") @RequestParam(required = false) String name - ) { - return Arrays.asList( - new LinkProviderType().name("pippo").totalRelationships(30), - new LinkProviderType().name("pluto").totalRelationships(30), - new LinkProviderType().name("peppa").totalRelationships(30) - ); + ) throws ScholixException { + List> result = manager.totalLinksPublisher(ScholixIndexManager.RelationPrefix.source,name); + + if (result==null) + return new ArrayList<>(); + + return result.stream().map(s -> new LinkProviderType().name(s.getLeft()).totalRelationships(s.getValue().intValue())).collect(Collectors.toList()); } @Operation( @@ -41,11 +50,12 @@ public class LinkPublisherV2 { @GetMapping("/inTarget") public List getInTarget( @Parameter(in = ParameterIn.QUERY, description = "Filter the link publisher name") @RequestParam(required = false) String name - ) { - return Arrays.asList( - new LinkProviderType().name("pippo").totalRelationships(30), - new LinkProviderType().name("pluto").totalRelationships(30), - new LinkProviderType().name("peppa").totalRelationships(30) - ); + ) throws ScholixException { + List> result = manager.totalLinksPublisher(ScholixIndexManager.RelationPrefix.target,name); + + if (result==null) + return new ArrayList<>(); + + return result.stream().map(s -> new LinkProviderType().name(s.getLeft()).totalRelationships(s.getValue().intValue())).collect(Collectors.toList()); } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java index b63d7c2f..b81d0e87 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java @@ -2,36 +2,42 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; +import eu.dnetlib.dhp.schema.sx.scholix.Scholix; +import eu.dnetlib.scholix.api.ScholixException; +import eu.dnetlib.scholix.api.index.ScholixIndexManager; import eu.dnetlib.scholix.api.model.v1.ScholixV1; +import io.micrometer.core.annotation.Timed; import io.swagger.annotations.Api; -import io.swagger.annotations.ApiModelProperty; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @RestController @RequestMapping("/v1") -@Api(tags = { - "Scholix" -}) +@Api(tags = {"Scholix"}) public class ScholixControllerV1 extends AbstractDnetController { + @Autowired + ScholixIndexManager manager; + @Operation( summary = "Get all Scholix relation collected from a publisher", description = "return a list of scholix object published from a specific publisher" ) @GetMapping("/linksFromPublisher") + @Timed(value = "scholix.v1.linksFromPublisher", description = "Time taken to return links on Version 1.0 of Scholix collected from a publisher") public List linksFromPublisher( @Parameter( in = ParameterIn.QUERY, @@ -39,9 +45,17 @@ public class ScholixControllerV1 extends AbstractDnetController { schema = @Schema(), required = true) String publisher, @Parameter(in = ParameterIn.QUERY, description = "The page number") @RequestParam(required = false) Integer page - ) { + ) throws ScholixException { - return new ArrayList<>(); + final int currentPage = page != null ? page : 0; + + Pair> scholixResult =manager.linksFromPid(null,null,null,publisher, + null,null,null,null,null,null, currentPage + ); + List scholixData = scholixResult.getValue(); + if (scholixData== null) + return null; + return scholixData.stream().map(ScholixV1::fromScholix).collect(Collectors.toList()); } @Operation( @@ -49,6 +63,7 @@ public class ScholixControllerV1 extends AbstractDnetController { description = "return a list of scholix object collected from a specific datasource" ) @GetMapping("/linksFromDatasource") + @Timed(value = "scholix.v1.linksFromDatasource", description = "Time taken to return links on Version 1.0 of Scholix collected from a LinkProvider") public List linksFromDatasource( @Parameter( in = ParameterIn.QUERY, @@ -56,9 +71,16 @@ public class ScholixControllerV1 extends AbstractDnetController { schema = @Schema()) @NotNull String datasource, @Parameter(in = ParameterIn.QUERY, description = "The page number") @RequestParam(required = false) Integer page - ) { + ) throws ScholixException { - return new ArrayList<>(); + final int currentPage = page != null ? page : 0; + Pair> scholixResult =manager.linksFromPid(datasource,null,null,null, + null,null,null,null,null,null, currentPage + ); + List scholixData = scholixResult.getValue(); + if (scholixData== null) + return null; + return scholixData.stream().map(ScholixV1::fromScholix).collect(Collectors.toList()); } @@ -67,6 +89,7 @@ public class ScholixControllerV1 extends AbstractDnetController { description = "The linksFromPid endpoint returns a list of scholix object related from a specific persistent identifier" ) @GetMapping("/linksFromPid") + @Timed(value = "scholix.v1.linksFromPid", description = "Time taken to return links on Version 1.0 of Scholix related from a specific persistent identifier") public List linksFromPid( @Parameter(in = ParameterIn.QUERY, description = "persistent Identifier") @NotNull String pid, @Parameter(in = ParameterIn.QUERY, description = "Persistent Identifier Type") @RequestParam(required = false) String pidType, @@ -74,9 +97,16 @@ public class ScholixControllerV1 extends AbstractDnetController { @Parameter(in = ParameterIn.QUERY, description = "a datasource provenance filter of the target relation") @RequestParam(required = false) String datasourceTarget, @Parameter(in = ParameterIn.QUERY, description = "The page number") @RequestParam(required = false) Integer page - ) { + ) throws ScholixException { - return new ArrayList<>(); + final int currentPage = page != null ? page : 0; + Pair> scholixResult =manager.linksFromPid(datasourceTarget,null,null,null, + typologyTarget,pid,pidType,null,null,null, currentPage + ); + List scholixData = scholixResult.getValue(); + if (scholixData== null) + return null; + return scholixData.stream().map(ScholixV1::fromScholix).collect(Collectors.toList()); } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java index b54a65cb..895d50c2 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java @@ -2,7 +2,7 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixIdentifier; +import eu.dnetlib.dhp.schema.sx.scholix.Scholix; import eu.dnetlib.scholix.api.ScholixAPIVersion; import eu.dnetlib.scholix.api.ScholixException; import eu.dnetlib.scholix.api.index.ScholixIndexManager; @@ -13,29 +13,13 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; -import eu.dnetlib.dhp.schema.sx.scholix.Scholix; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.apache.lucene.search.join.ScoreMode; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.NestedQueryBuilder; -import org.elasticsearch.index.query.TermQueryBuilder; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; -import org.springframework.data.elasticsearch.core.query.Query; -import org.elasticsearch.index.query.QueryBuilders; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.SearchHits; -import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -49,9 +33,6 @@ public class ScholixControllerV2 extends AbstractDnetController { @Autowired private ScholixIndexManager manager; - - - @Timed(value = "scholix.v2.links", description = "Time taken to return links on Version 2.0 of Scholix") @ApiOperation("Get Scholix Links") @GetMapping("/Links") @@ -84,7 +65,7 @@ public class ScholixControllerV2 extends AbstractDnetController { try { final int currentPage = page != null ? page : 0; - Pair> scholixResult = manager.linksFromPid(ScholixAPIVersion.V2, linkProvider, targetPid, targetPidType, targetPublisher, targetType, sourcePid, sourcePidType, sourcePublisher, sourceType, harvestedAfter, currentPage); + Pair> scholixResult = manager.linksFromPid( linkProvider, targetPid, targetPidType, targetPublisher, targetType, sourcePid, sourcePidType, sourcePublisher, sourceType, harvestedAfter, currentPage); final PageResultType pageResult = new PageResultType(); pageResult.setTotalPages(scholixResult.getLeft().intValue() / 10); pageResult.setTotalLinks(scholixResult.getLeft().intValue()); @@ -94,7 +75,4 @@ public class ScholixControllerV2 extends AbstractDnetController { throw new ScholixException("Error on requesting url ", e); } } - - - } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java index f93f8d02..d1f8b54a 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java @@ -61,7 +61,7 @@ public class ScholixIndexManager { /** * The enum Pid type prefix. */ - enum pidTypePrefix { + public enum RelationPrefix { /** * Source pid type prefix. */ @@ -73,7 +73,7 @@ public class ScholixIndexManager { } - private QueryBuilder createObjectTypeQuery(final pidTypePrefix prefix, final String objectType ) throws ScholixException{ + private QueryBuilder createObjectTypeQuery(final RelationPrefix prefix, final String objectType ) throws ScholixException{ if (prefix == null){ throw new ScholixException("prefix cannot be null"); } @@ -81,7 +81,7 @@ public class ScholixIndexManager { } - private QueryBuilder createPidTypeQuery(final pidTypePrefix prefix, final String pidTypeValue ) throws ScholixException{ + private QueryBuilder createPidTypeQuery(final RelationPrefix prefix, final String pidTypeValue ) throws ScholixException{ if (prefix == null){ throw new ScholixException("prefix cannot be null"); } @@ -89,7 +89,21 @@ public class ScholixIndexManager { } - private QueryBuilder createPidValueQuery(final pidTypePrefix prefix, final String pidValue ) throws ScholixException{ + private QueryBuilder createLinkProviderQuery(final String providerName ) throws ScholixException{ + if (providerName == null){ + throw new ScholixException("prefix cannot be null"); + } + return new NestedQueryBuilder("linkprovider", new TermQueryBuilder("linkprovider.name",providerName), ScoreMode.None); + } + + private QueryBuilder createLinkPublisherQuery(final RelationPrefix prefix, final String publisher ) throws ScholixException{ + if (prefix == null){ + throw new ScholixException("prefix cannot be null"); + } + return new NestedQueryBuilder(String.format("%s.publisher", prefix), new TermQueryBuilder(String.format("%s.publisher.name",prefix), publisher), ScoreMode.None); + } + + private QueryBuilder createPidValueQuery(final RelationPrefix prefix, final String pidValue ) throws ScholixException{ if (prefix == null){ throw new ScholixException("prefix cannot be null"); } @@ -116,7 +130,7 @@ public class ScholixIndexManager { } - private void incrementPidCounter(pidTypePrefix prefix, String value) { + private void incrementPidCounter(RelationPrefix prefix, String value) { switch (value.toLowerCase()){ case "doi": { myCounter.increment(String.format("%s_doi", prefix)); @@ -132,10 +146,13 @@ public class ScholixIndexManager { } - public List> linksByProvider(final String filterName) throws ScholixException { + public List> totalLinksByProvider(final String filterName) throws ScholixException { + + + final QueryBuilder query = StringUtils.isNoneBlank(filterName)?createLinkProviderQuery(filterName):QueryBuilders.matchAllQuery(); final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() - .withQuery(QueryBuilders.matchAllQuery()) + .withQuery(query) .withSearchType(SearchType.DEFAULT) .withPageable(PageRequest.of(0,10)) .addAggregation(AggregationBuilders.nested("nested", "linkprovider") @@ -148,7 +165,41 @@ public class ScholixIndexManager { final SearchHits hits = client.search(searchQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); final Aggregations aggregations = hits.getAggregations(); + connectionPool.returnResource(resource); + if(aggregations == null) + return null; + + final Aggregation aggByMap = ((ParsedNested) aggregations.asMap().get("nested")).getAggregations().asMap().get("by_map"); + + + return ((ParsedStringTerms) aggByMap).getBuckets() + .stream() + .map(b -> new ImmutablePair<>(b.getKeyAsString(), b.getDocCount())) + .collect(Collectors.toList()); + } + + + public List> totalLinksPublisher(final RelationPrefix prefix, final String filterName) throws ScholixException { + + + final QueryBuilder query = StringUtils.isNoneBlank(filterName)?createLinkPublisherQuery(prefix,filterName):QueryBuilders.matchAllQuery(); + + final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(query) + .withSearchType(SearchType.DEFAULT) + .withPageable(PageRequest.of(0,10)) + .addAggregation(AggregationBuilders.nested("nested", String.format("%s.publisher", prefix )) + .subAggregation(AggregationBuilders.terms("by_map").field(String.format("%s.publisher.name", prefix )).size(100).minDocCount(1))) + .build(); + + + Pair resource = connectionPool.getResource(); + ElasticsearchRestTemplate client = resource.getValue(); + final SearchHits hits = client.search(searchQuery, Scholix.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + + final Aggregations aggregations = hits.getAggregations(); + connectionPool.returnResource(resource); if(aggregations == null) return null; @@ -171,7 +222,6 @@ public class ScholixIndexManager { /** * Links from pid pair. * - * @param outputVersion the output version * @param linkProvider the link provider * @param targetPid the target pid * @param targetPidType the target pid type @@ -187,51 +237,61 @@ public class ScholixIndexManager { * @throws ScholixException the scholix exception */ @Timed(value = "scholix.index.request.links", description = "Time taken to request index") - public Pair> linksFromPid (final ScholixAPIVersion outputVersion, final String linkProvider, + public Pair> linksFromPid ( final String linkProvider, final String targetPid, final String targetPidType, final String targetPublisher, final String targetType, final String sourcePid, final String sourcePidType, final String sourcePublisher, final String sourceType, final String harvestedAfter, final Integer page) throws ScholixException { - if(outputVersion == null) - throw new ScholixException("Error outputVersion not be empty"); + if (sourcePid==null && sourcePidType==null && targetPid==null && targetPidType==null && sourcePublisher==null && targetPublisher==null && linkProvider==null) throw new ScholixException("One of sourcePid, targetPid, sourcePublisher, targetPublisher, linkProvider should be not null"); final List queries = new ArrayList<>(); + if (StringUtils.isNoneBlank(linkProvider)) { + myCounter.increment("linkProvider"); + queries.add(createLinkProviderQuery(linkProvider)); + } + if (StringUtils.isNoneBlank(targetPid)) { myCounter.increment("targetPid"); - queries.add(createPidValueQuery(pidTypePrefix.target, targetPid)); + queries.add(createPidValueQuery(RelationPrefix.target, targetPid)); } if (StringUtils.isNoneBlank(sourcePid)) { myCounter.increment("sourcePid"); - queries.add(createPidValueQuery(pidTypePrefix.source, sourcePid)); + queries.add(createPidValueQuery(RelationPrefix.source, sourcePid)); } if (StringUtils.isNoneBlank(targetPidType)) { assert targetPidType != null; - incrementPidCounter(pidTypePrefix.target,targetPidType); - queries.add(createPidTypeQuery(pidTypePrefix.target, targetPidType)); + incrementPidCounter(RelationPrefix.target,targetPidType); + queries.add(createPidTypeQuery(RelationPrefix.target, targetPidType)); } if (StringUtils.isNoneBlank(sourcePidType)) { assert sourcePidType != null; - incrementPidCounter(pidTypePrefix.source,sourcePidType); - queries.add(createPidTypeQuery(pidTypePrefix.source, sourcePidType)); + incrementPidCounter(RelationPrefix.source,sourcePidType); + queries.add(createPidTypeQuery(RelationPrefix.source, sourcePidType)); } if (StringUtils.isNoneBlank(targetType)) { if ("dataset".equalsIgnoreCase(targetType) || "publication".equalsIgnoreCase(targetType)) myCounter.increment(String.format("targetType_%s", targetType)); - queries.add(createObjectTypeQuery(pidTypePrefix.target, targetType)); + queries.add(createObjectTypeQuery(RelationPrefix.target, targetType)); } if (StringUtils.isNoneBlank(sourceType)) { if ("dataset".equalsIgnoreCase(sourceType) || "publication".equalsIgnoreCase(sourceType)) { myCounter.increment(String.format("sourceType_%s", sourceType)); } - queries.add(createObjectTypeQuery(pidTypePrefix.source, sourceType)); + queries.add(createObjectTypeQuery(RelationPrefix.source, sourceType)); + } + + if (StringUtils.isNoneBlank(targetPublisher)) { + myCounter.increment("targetPublisher"); + + queries.add(createLinkPublisherQuery(RelationPrefix.target,targetPublisher)); } QueryBuilder result = createFinalQuery(queries); @@ -254,8 +314,4 @@ public class ScholixIndexManager { return new ImmutablePair<>(tt,scholixRes.stream().map(SearchHit::getContent).collect(Collectors.toList())); } - - - - } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java index 97f571b1..53c39cf4 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java @@ -1,11 +1,11 @@ package eu.dnetlib.scholix.api.model.v1; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; import io.swagger.v3.oas.annotations.media.Schema; -import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.stream.Collectors; public class ScholixCreator { @@ -29,22 +29,11 @@ public class ScholixCreator { return name; } - public void setName(String name) { + public ScholixCreator setName(String name) { this.name = name; - } - - public ScholixCreator identifier(List identifier) { - this.identifier = identifier; return this; } - public ScholixCreator addIdentifierItem(ScholixIdentifier identifierItem) { - if (this.identifier == null) { - this.identifier = new ArrayList(); - } - this.identifier.add(identifierItem); - return this; - } /** * Get identifier @@ -55,48 +44,26 @@ public class ScholixCreator { return identifier; } - public void setIdentifier(List identifier) { + public ScholixCreator setIdentifier(List identifier) { this.identifier = identifier; + return this; } + public static ScholixCreator fromScholixEntityId(final ScholixEntityId provider) { + if (provider == null) + return null; + ScholixCreator instance = new ScholixCreator().setName(provider.getName()); - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ScholixCreator ScholixCreator = (ScholixCreator) o; - return Objects.equals(this.name, ScholixCreator.name) && - Objects.equals(this.identifier, ScholixCreator.identifier); - } - @Override - public int hashCode() { - return Objects.hash(name, identifier); - } + if (provider.getIdentifiers()!= null && provider.getIdentifiers().size()>0) + instance.setIdentifier(provider.getIdentifiers() + .stream() + .map(i ->new ScholixIdentifier() + .setIdentifier(i.getIdentifier()) + .setSchema(i.getSchema())) + .collect(Collectors.toList())); + return instance; - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class ScholixCreator {\n"); - sb.append(" name: ").append(toIndentedString(name)).append("\n"); - sb.append(" identifier: ").append(toIndentedString(identifier)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java index 49fb0be6..70f7c50f 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java @@ -29,8 +29,9 @@ public class ScholixIdentifier { return identifier; } - public void setIdentifier(String identifier) { + public ScholixIdentifier setIdentifier(String identifier) { this.identifier = identifier; + return this; } public ScholixIdentifier Schema(String idScheme) { @@ -48,51 +49,23 @@ public class ScholixIdentifier { return schema; } - public void setSchema(String schema) { + public ScholixIdentifier setSchema(String schema) { this.schema = schema; + return this; + } + + public static ScholixIdentifier fromScholixIdentifier(eu.dnetlib.dhp.schema.sx.scholix.ScholixIdentifier input) { + if (input == null) + return null; + + final ScholixIdentifier result = new ScholixIdentifier(); + result.setSchema(input.getSchema()); + result.setIdentifier(input.getIdentifier()); + return result; + + + } - - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ScholixIdentifier identifierType = (ScholixIdentifier) o; - return Objects.equals(this.identifier, identifierType.identifier) && - Objects.equals(this.schema, identifierType.schema); - } - - @Override - public int hashCode() { - return Objects.hash(identifier, schema); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class IdentifierType {\n"); - - sb.append(" identifier: ").append(toIndentedString(identifier)).append("\n"); - sb.append(" schema: ").append(toIndentedString(schema)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java index c81b3bd1..fb0af52b 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java @@ -1,16 +1,18 @@ package eu.dnetlib.scholix.api.model.v1; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixResource; import io.swagger.v3.oas.annotations.media.Schema; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; public class ScholixItem { - @JsonProperty("identifier") - private ScholixIdentifier identifier; + @JsonProperty("identifiers") + private List identifiers; @JsonProperty("objectType") private String objectType; @@ -28,22 +30,18 @@ public class ScholixItem { private String publicationDate; @JsonProperty("publisher") - private ScholixProvider publisher; + private List publisher; - public ScholixItem identifier(ScholixIdentifier identifier) { - this.identifier = identifier; + @Schema(description = "The list of identifiers") + public List getIdentifiers() { + return identifiers; + } + + public ScholixItem setIdentifiers(List identifiers) { + this.identifiers = identifiers; return this; } - @Schema(description = "The identifier string") - public ScholixIdentifier getIdentifier() { - return identifier; - } - - public void setIdentifier(ScholixIdentifier identifier) { - this.identifier = identifier; - } - public ScholixItem objectType(String objectType) { this.objectType = objectType; return this; @@ -116,63 +114,48 @@ public class ScholixItem { this.publicationDate = publicationDate; } - @Schema(description = "The name of the publisher of the object") - public ScholixProvider getPublisher() { + @Schema(description = "The list name of the publisher of the object") + public List getPublisher() { return publisher; } - public void setPublisher(ScholixProvider publisher) { + public ScholixItem setPublisher(List publisher) { this.publisher = publisher; + return this; } + public static ScholixItem fromScholixResource(final ScholixResource input) { + if (input == null) + return null; - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ScholixItem scholixItemType = (ScholixItem) o; - return Objects.equals(this.objectType, scholixItemType.objectType) && - Objects.equals(this.objectSubType, scholixItemType.objectSubType) && - Objects.equals(this.identifier, scholixItemType.identifier) && - Objects.equals(this.title, scholixItemType.title) && - Objects.equals(this.creator, scholixItemType.creator) && - Objects.equals(this.publicationDate, scholixItemType.publicationDate) && - Objects.equals(this.publisher, scholixItemType.publisher); - } - @Override - public int hashCode() { - return Objects.hash(objectType, objectSubType, identifier, title, creator, publicationDate, publisher); - } + final ScholixItem result = new ScholixItem(); - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class ScholixItemType {\n"); + if (input.getIdentifier()!= null) + result.setIdentifiers( + input.getIdentifier().stream() + .map(ScholixIdentifier::fromScholixIdentifier) + .collect(Collectors.toList()) + ); - sb.append(" objectType: ").append(toIndentedString(objectType)).append("\n"); - sb.append(" objectSubType: ").append(toIndentedString(objectSubType)).append("\n"); - sb.append(" identifier: ").append(toIndentedString(identifier)).append("\n"); - sb.append(" title: ").append(toIndentedString(title)).append("\n"); - sb.append(" creator: ").append(toIndentedString(creator)).append("\n"); - sb.append(" publicationDate: ").append(toIndentedString(publicationDate)).append("\n"); - sb.append(" publisher: ").append(toIndentedString(publisher)).append("\n"); - sb.append("}"); - return sb.toString(); - } + result.setTitle(input.getTitle()); + result.setObjectType(input.getObjectType()); + result.setObjectSubType(input.getObjectSubType()); + result.setPublicationDate(input.getPublicationDate()); + if(input.getPublisher()!= null) + result.setPublisher(input.getPublisher().stream() + .map(ScholixProvider::fromScholixEntityId) + .collect(Collectors.toList()) + ); + + + if (input.getCreator()!= null) + result.setCreator(input.getCreator().stream() + .map(ScholixCreator::fromScholixEntityId) + .collect(Collectors.toList()) + ); + + return result; - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java index 1436c36d..21a50ce2 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java @@ -1,15 +1,36 @@ package eu.dnetlib.scholix.api.model.v1; import com.fasterxml.jackson.annotation.JsonProperty; +import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.Valid; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; public class ScholixProvider { + public static ScholixProvider fromScholixEntityId(final ScholixEntityId provider) { + if (provider == null) + return null; + ScholixProvider instance = new ScholixProvider().setName(provider.getName()); + + + if (provider.getIdentifiers()!= null && provider.getIdentifiers().size()>0) + instance.setIdentifier(provider.getIdentifiers() + .stream() + .map(i ->new ScholixIdentifier() + .setIdentifier(i.getIdentifier()) + .setSchema(i.getSchema())) + .collect(Collectors.toList())); + return instance; + + + } + + @JsonProperty("name") private String name = null; @@ -32,8 +53,9 @@ public class ScholixProvider { return name; } - public void setName(String name) { + public ScholixProvider setName(String name) { this.name = name; + return this; } public ScholixProvider identifier(List identifier) { @@ -59,8 +81,9 @@ public class ScholixProvider { return identifier; } - public void setIdentifier(List identifier) { + public ScholixProvider setIdentifier(List identifier) { this.identifier = identifier; + return this; } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java index 82242d39..da58c956 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java @@ -6,6 +6,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotBlank; import java.util.Objects; +import static eu.dnetlib.scholix.api.model.v2.RelationshipType.relationMapping; + public class ScholixRelationship { @JsonProperty("name") @@ -116,4 +118,17 @@ public class ScholixRelationship { return o.toString().replace("\n", "\n "); } + public static ScholixRelationship fromScholixIndexRelationship(eu.dnetlib.dhp.schema.sx.scholix.ScholixRelationship inputRel) { + if(inputRel==null) + return null; + + ScholixRelationship result = new ScholixRelationship(); + + result.setName(relationMapping.getOrDefault(inputRel.getName(), "IsRelatedTo")); + result.setInverseRelationship(relationMapping.getOrDefault(inputRel.getInverse(), "IsRelatedTo")); + result.setSchema(inputRel.getSchema()); + return result; + + } + } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java index 3e9c5978..42f30acd 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java @@ -9,6 +9,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; public class ScholixV1 implements Serializable { @@ -161,6 +162,23 @@ public class ScholixV1 implements Serializable { public static ScholixV1 fromScholix(Scholix input) { - return new ScholixV1(); + if (input == null) + return null; + final ScholixV1 result = new ScholixV1(); + + + if (input.getLinkprovider()!= null) + result.setLinkProvider(input.getLinkprovider() + .stream() + .map(ScholixProvider::fromScholixEntityId) + .collect(Collectors.toList())); + + result.setPublicationDate(input.getPublicationDate()); + + result.setRelationship(ScholixRelationship.fromScholixIndexRelationship(input.getRelationship())); + + result.setSource(ScholixItem.fromScholixResource(input.getSource())); + result.setTarget(ScholixItem.fromScholixResource(input.getTarget())); + return result; } } diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java index 6651c1b9..807b3e3f 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java @@ -27,7 +27,7 @@ public class RelationshipType { private String subTypeSchema; - private static Map relationMapping = Stream.of(new String[][] { + public static Map relationMapping = Stream.of(new String[][] { { "issupplementto", "IsSupplementTo" }, { "issupplementedby", "IsSupplementedBy" }, { "references", "References" }, diff --git a/apps/scholexplorer-api/src/test/java/eu/dnetlib/scholix/test/QueryTest.java b/apps/scholexplorer-api/src/test/java/eu/dnetlib/scholix/test/QueryTest.java new file mode 100644 index 00000000..f0e3bd1b --- /dev/null +++ b/apps/scholexplorer-api/src/test/java/eu/dnetlib/scholix/test/QueryTest.java @@ -0,0 +1,18 @@ +package eu.dnetlib.scholix.test; + + + +import org.junit.jupiter.api.Test; + + +public class QueryTest { + + + @Test + public void featureToTest() { + + + + + } +} -- 2.17.1 From 786449a43ca6c1b2b5ce581f31ee2c4c079d78ab Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Mon, 28 Feb 2022 11:27:07 +0100 Subject: [PATCH 8/9] code refactor properties changed --- .../eu/dnetlib/scholix/api/index/ScholixIndexManager.java | 2 -- .../src/main/resources/application.properties | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java index d1f8b54a..23aa2d47 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/index/ScholixIndexManager.java @@ -2,10 +2,8 @@ package eu.dnetlib.scholix.api.index; import eu.dnetlib.dhp.schema.sx.scholix.Scholix; -import eu.dnetlib.scholix.api.ScholixAPIVersion; import eu.dnetlib.scholix.api.ScholixException; import eu.dnetlib.scholix.api.TaggedCounter; - import io.micrometer.core.annotation.Timed; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; diff --git a/apps/scholexplorer-api/src/main/resources/application.properties b/apps/scholexplorer-api/src/main/resources/application.properties index beb6bf51..03eedf2b 100644 --- a/apps/scholexplorer-api/src/main/resources/application.properties +++ b/apps/scholexplorer-api/src/main/resources/application.properties @@ -20,7 +20,7 @@ management.metrics.distribution.percentiles.http.server.requests=0.5, 0.9, 0.95, -scholix.elastic.clusterNodes = localhost:9200 -scholix.elastic.indexName = dli_scholix -scholix.elastic.socketTimeout = 60000 -scholix.elastic.connectionTimeout= 60000 +scholix.elastic.clusterNodes = localhost:9200 +scholix.elastic.indexName = dli_shadow_scholix +scholix.elastic.socketTimeout = 60000 +scholix.elastic.connectionTimeout= 60000 -- 2.17.1 From 7abf6af997a1f2168e8acd0c9c67144d10fb5f31 Mon Sep 17 00:00:00 2001 From: Sandro La Bruzzo Date: Mon, 28 Feb 2022 14:26:55 +0100 Subject: [PATCH 9/9] moved data model of API into dhp-schemas --- .../scholix/api/controller/DatasourceV1.java | 3 +- .../api/controller/LinkProviderV2.java | 2 +- .../api/controller/LinkPublisherV2.java | 2 +- .../api/controller/ScholixControllerV1.java | 2 +- .../api/controller/ScholixControllerV2.java | 5 +- .../scholix/api/model/v1/LinkPublisher.java | 97 --------- .../scholix/api/model/v1/ScholixCreator.java | 69 ------ .../api/model/v1/ScholixIdentifier.java | 71 ------- .../scholix/api/model/v1/ScholixItem.java | 161 -------------- .../scholix/api/model/v1/ScholixProvider.java | 129 ------------ .../api/model/v1/ScholixRelationship.java | 134 ------------ .../scholix/api/model/v1/ScholixV1.java | 184 ---------------- .../api/model/v2/LinkProviderType.java | 124 ----------- .../scholix/api/model/v2/PageResultType.java | 114 ---------- .../api/model/v2/RelationshipType.java | 109 ---------- .../api/model/v2/ScholixCreatorType.java | 86 -------- .../api/model/v2/ScholixIdentifierType.java | 105 ---------- .../scholix/api/model/v2/ScholixItemType.java | 188 ----------------- .../api/model/v2/ScholixLinkProviderType.java | 88 -------- .../scholix/api/model/v2/ScholixType.java | 196 ------------------ pom.xml | 2 +- 21 files changed, 8 insertions(+), 1863 deletions(-) delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/LinkPublisher.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/PageResultType.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java delete mode 100644 apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java index 87616b2b..ea5f58a1 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/DatasourceV1.java @@ -1,9 +1,10 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; +import eu.dnetlib.dhp.schema.sx.api.model.v1.LinkPublisher; import eu.dnetlib.scholix.api.ScholixException; import eu.dnetlib.scholix.api.index.ScholixIndexManager; -import eu.dnetlib.scholix.api.model.v1.LinkPublisher; + import io.micrometer.core.annotation.Timed; import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation; diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java index 286e0eb9..ecce061e 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkProviderV2.java @@ -1,7 +1,7 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.scholix.api.ScholixException; import eu.dnetlib.scholix.api.index.ScholixIndexManager; -import eu.dnetlib.scholix.api.model.v2.LinkProviderType; +import eu.dnetlib.dhp.schema.sx.api.model.v2.LinkProviderType; import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java index 88e2e6a6..e1a9210c 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/LinkPublisherV2.java @@ -1,7 +1,7 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.scholix.api.ScholixException; import eu.dnetlib.scholix.api.index.ScholixIndexManager; -import eu.dnetlib.scholix.api.model.v2.LinkProviderType; +import eu.dnetlib.dhp.schema.sx.api.model.v2.LinkProviderType; import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java index b81d0e87..85c76531 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV1.java @@ -5,7 +5,7 @@ import eu.dnetlib.common.controller.AbstractDnetController; import eu.dnetlib.dhp.schema.sx.scholix.Scholix; import eu.dnetlib.scholix.api.ScholixException; import eu.dnetlib.scholix.api.index.ScholixIndexManager; -import eu.dnetlib.scholix.api.model.v1.ScholixV1; +import eu.dnetlib.dhp.schema.sx.api.model.v1.ScholixV1; import io.micrometer.core.annotation.Timed; import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation; diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java index 895d50c2..a0d5d3b2 100644 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java +++ b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/controller/ScholixControllerV2.java @@ -2,12 +2,11 @@ package eu.dnetlib.scholix.api.controller; import eu.dnetlib.common.controller.AbstractDnetController; +import eu.dnetlib.dhp.schema.sx.api.model.v2.PageResultType; +import eu.dnetlib.dhp.schema.sx.api.model.v2.ScholixType; import eu.dnetlib.dhp.schema.sx.scholix.Scholix; -import eu.dnetlib.scholix.api.ScholixAPIVersion; import eu.dnetlib.scholix.api.ScholixException; import eu.dnetlib.scholix.api.index.ScholixIndexManager; -import eu.dnetlib.scholix.api.model.v2.PageResultType; -import eu.dnetlib.scholix.api.model.v2.ScholixType; import io.micrometer.core.annotation.Timed; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/LinkPublisher.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/LinkPublisher.java deleted file mode 100644 index ae1a1b63..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/LinkPublisher.java +++ /dev/null @@ -1,97 +0,0 @@ -package eu.dnetlib.scholix.api.model.v1; - -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import java.util.Objects; - -public class LinkPublisher { - @NotBlank - @JsonProperty("name") - private String name = null; - - @NotBlank - @JsonProperty("totalRelationships") - private Integer totalRelationships = null; - - public LinkPublisher name(String name) { - this.name = name; - return this; - } - - /** - * Get name - * @return name - **/ - @Schema(description = "The Publisher Name") - - @Size(max=300) public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public LinkPublisher totalRelationships(Integer totalRelationships) { - this.totalRelationships = totalRelationships; - return this; - } - - /** - * Get totalRelationships - * @return totalRelationships - **/ - @Schema(description = "Total number of relationships that the publisher provides") - - public Integer getTotalRelationships() { - return totalRelationships; - } - - public void setTotalRelationships(Integer totalRelationships) { - this.totalRelationships = totalRelationships; - } - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - LinkPublisher linkPublisher = (LinkPublisher) o; - return Objects.equals(this.name, linkPublisher.name) && - Objects.equals(this.totalRelationships, linkPublisher.totalRelationships); - } - - @Override - public int hashCode() { - return Objects.hash(name, totalRelationships); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class LinkPublisher {\n"); - - sb.append(" name: ").append(toIndentedString(name)).append("\n"); - sb.append(" totalRelationships: ").append(toIndentedString(totalRelationships)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } -} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java deleted file mode 100644 index 53c39cf4..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixCreator.java +++ /dev/null @@ -1,69 +0,0 @@ -package eu.dnetlib.scholix.api.model.v1; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.List; -import java.util.stream.Collectors; - -public class ScholixCreator { - - @JsonProperty("name") - private String name = null; - - @JsonProperty("identifier") - private List identifier = null; - - public ScholixCreator name(String name) { - this.name = name; - return this; - } - - /** - * Get name - * @return name - **/ - @Schema(required = true, description = "The name of the Object Creator") - public String getName() { - return name; - } - - public ScholixCreator setName(String name) { - this.name = name; - return this; - } - - - /** - * Get identifier - * @return identifier - **/ - @Schema(description = "A unique string that identifies the Object Creator") - public List getIdentifier() { - return identifier; - } - - public ScholixCreator setIdentifier(List identifier) { - this.identifier = identifier; - return this; - } - - public static ScholixCreator fromScholixEntityId(final ScholixEntityId provider) { - if (provider == null) - return null; - ScholixCreator instance = new ScholixCreator().setName(provider.getName()); - - - if (provider.getIdentifiers()!= null && provider.getIdentifiers().size()>0) - instance.setIdentifier(provider.getIdentifiers() - .stream() - .map(i ->new ScholixIdentifier() - .setIdentifier(i.getIdentifier()) - .setSchema(i.getSchema())) - .collect(Collectors.toList())); - return instance; - - - } -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java deleted file mode 100644 index 70f7c50f..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixIdentifier.java +++ /dev/null @@ -1,71 +0,0 @@ -package eu.dnetlib.scholix.api.model.v1; - -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.Objects; - -public class ScholixIdentifier { - - @JsonProperty("identifier") - private String identifier = null; - - @JsonProperty("schema") - private String schema = null; - - - - public ScholixIdentifier Identifier(String ID) { - this.identifier = ID; - return this; - } - - /** - * Get ID - * @return ID - **/ - @Schema(description = "The value of the Identifier") - public String getIdentifier() { - return identifier; - } - - public ScholixIdentifier setIdentifier(String identifier) { - this.identifier = identifier; - return this; - } - - public ScholixIdentifier Schema(String idScheme) { - this.schema = idScheme; - return this; - } - - /** - * Get the Schema - * @return Schema - **/ - @Schema(description = "The Schema URL of the identifier type") - - public String getSchema() { - return schema; - } - - public ScholixIdentifier setSchema(String schema) { - this.schema = schema; - return this; - } - - public static ScholixIdentifier fromScholixIdentifier(eu.dnetlib.dhp.schema.sx.scholix.ScholixIdentifier input) { - if (input == null) - return null; - - final ScholixIdentifier result = new ScholixIdentifier(); - result.setSchema(input.getSchema()); - result.setIdentifier(input.getIdentifier()); - return result; - - - - } - - -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java deleted file mode 100644 index fb0af52b..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixItem.java +++ /dev/null @@ -1,161 +0,0 @@ -package eu.dnetlib.scholix.api.model.v1; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixResource; -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -public class ScholixItem { - - @JsonProperty("identifiers") - private List identifiers; - - @JsonProperty("objectType") - private String objectType; - - @JsonProperty("objectSubType") - private String objectSubType; - - @JsonProperty("title") - private String title; - - @JsonProperty("creator") - private List creator; - - @JsonProperty("publicationDate") - private String publicationDate; - - @JsonProperty("publisher") - private List publisher; - - @Schema(description = "The list of identifiers") - public List getIdentifiers() { - return identifiers; - } - - public ScholixItem setIdentifiers(List identifiers) { - this.identifiers = identifiers; - return this; - } - - public ScholixItem objectType(String objectType) { - this.objectType = objectType; - return this; - } - - @Schema(description = "Describes the nature of the object (its intended usage)") - public String getObjectType() { - return objectType; - } - - public void setObjectType(String objectType) { - this.objectType = objectType; - } - - public ScholixItem objectSubType(String objectSubType) { - this.objectSubType = objectSubType; - return this; - } - - @Schema(description = "The sub-type of Object") - public String getObjectSubType() { - return objectSubType; - } - - public void setObjectSubType(String objectSubType) { - this.objectSubType = objectSubType; - } - - public ScholixItem title(String title) { - this.title = title; - return this; - } - - @Schema(description = "The name of the object") - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public ScholixItem creator(List creator) { - this.creator = creator; - return this; - } - - public ScholixItem addCreatorInstance(ScholixCreator creatorInstance) { - if(this.creator == null) - this.creator = new ArrayList<>(); - this.creator.add(creatorInstance); - return this; - } - - @Schema(description = "Party responsible for the creation of the object") - public List getCreator() { - return creator; - } - - public void setCreator(List creator) { - this.creator = creator; - } - - @Schema(description = "The date the object was formally issued, published or distributed") - public String getPublicationDate() { - return publicationDate; - } - - public void setPublicationDate(String publicationDate) { - this.publicationDate = publicationDate; - } - - @Schema(description = "The list name of the publisher of the object") - public List getPublisher() { - return publisher; - } - - public ScholixItem setPublisher(List publisher) { - this.publisher = publisher; - return this; - } - - public static ScholixItem fromScholixResource(final ScholixResource input) { - if (input == null) - return null; - - - final ScholixItem result = new ScholixItem(); - - if (input.getIdentifier()!= null) - result.setIdentifiers( - input.getIdentifier().stream() - .map(ScholixIdentifier::fromScholixIdentifier) - .collect(Collectors.toList()) - ); - - result.setTitle(input.getTitle()); - result.setObjectType(input.getObjectType()); - result.setObjectSubType(input.getObjectSubType()); - result.setPublicationDate(input.getPublicationDate()); - if(input.getPublisher()!= null) - result.setPublisher(input.getPublisher().stream() - .map(ScholixProvider::fromScholixEntityId) - .collect(Collectors.toList()) - ); - - - if (input.getCreator()!= null) - result.setCreator(input.getCreator().stream() - .map(ScholixCreator::fromScholixEntityId) - .collect(Collectors.toList()) - ); - - return result; - - } -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java deleted file mode 100644 index 21a50ce2..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixProvider.java +++ /dev/null @@ -1,129 +0,0 @@ -package eu.dnetlib.scholix.api.model.v1; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -public class ScholixProvider { - - public static ScholixProvider fromScholixEntityId(final ScholixEntityId provider) { - if (provider == null) - return null; - ScholixProvider instance = new ScholixProvider().setName(provider.getName()); - - - if (provider.getIdentifiers()!= null && provider.getIdentifiers().size()>0) - instance.setIdentifier(provider.getIdentifiers() - .stream() - .map(i ->new ScholixIdentifier() - .setIdentifier(i.getIdentifier()) - .setSchema(i.getSchema())) - .collect(Collectors.toList())); - return instance; - - - } - - - @JsonProperty("name") - private String name = null; - - @JsonProperty("identifier") - @Valid - private List identifier = null; - - public ScholixProvider name(String name) { - this.name = name; - return this; - } - - /** - * Get the provider name - * @return name - **/ - @Schema(description = "The provider name") - - public String getName() { - return name; - } - - public ScholixProvider setName(String name) { - this.name = name; - return this; - } - - public ScholixProvider identifier(List identifier) { - this.identifier = identifier; - return this; - } - - public ScholixProvider addIdentifierItem(ScholixIdentifier identifierItem) { - if (this.identifier == null) { - this.identifier = new ArrayList<>(); - } - this.identifier.add(identifierItem); - return this; - } - - /** - * Get identifier - * @return identifier - **/ - @Schema(description = "the identifiers of the provider") - @Valid - public List getIdentifier() { - return identifier; - } - - public ScholixProvider setIdentifier(List identifier) { - this.identifier = identifier; - return this; - } - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ScholixProvider scholixProviderType = (ScholixProvider) o; - return Objects.equals(this.name, scholixProviderType.name) && - Objects.equals(this.identifier, scholixProviderType.identifier); - } - - @Override - public int hashCode() { - return Objects.hash(name, identifier); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class ScholixProviderType {\n"); - - sb.append(" name: ").append(toIndentedString(name)).append("\n"); - sb.append(" identifiers: ").append(toIndentedString(identifier)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java deleted file mode 100644 index da58c956..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixRelationship.java +++ /dev/null @@ -1,134 +0,0 @@ -package eu.dnetlib.scholix.api.model.v1; - -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotBlank; -import java.util.Objects; - -import static eu.dnetlib.scholix.api.model.v2.RelationshipType.relationMapping; - -public class ScholixRelationship { - - @JsonProperty("name") - private String name = null; - - @JsonProperty("schema") - private String schema = null; - - @NotBlank - @JsonProperty("inverseRelationship") - private String inverseRelationship = null; - - public ScholixRelationship name(String name) { - this.name = name; - return this; - } - - /** - * Get name - * @return name - **/ - @Schema(required = true, description = "The relationship type chosen from a Scholix controlled vocabulary") - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public ScholixRelationship schema(String schema) { - this.schema = schema; - return this; - } - - /** - * Get The name of the schema or controlled list from which Relationship Sub-type is sourced - * @return subType - **/ - @Schema(description = "The name of the schema or controlled list from which Relationship Sub-type is sourced") - public String getSchema() { - return schema; - } - - public void setSchema(String schema) { - this.schema = schema; - } - - public ScholixRelationship inverseRelationship(String inverseRelationship) { - this.inverseRelationship = inverseRelationship; - return this; - } - - /** - * Get inverseRelationship - * @return inverseRelationship - **/ - @Schema(description = "The value of the inverse relation") - - public String getInverseRelationship() { - return inverseRelationship; - } - - public void setInverseRelationship(String inverseRelationship) { - this.inverseRelationship = inverseRelationship; - } - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ScholixRelationship relationshipType = (ScholixRelationship) o; - return Objects.equals(this.name, relationshipType.name) && - Objects.equals(this.schema, relationshipType.schema) && - Objects.equals(this.inverseRelationship, relationshipType.inverseRelationship); - } - - @Override - public int hashCode() { - return Objects.hash(name, schema, inverseRelationship); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class RelationshipType {\n"); - - sb.append(" name: ").append(toIndentedString(name)).append("\n"); - sb.append(" subType: ").append(toIndentedString(schema)).append("\n"); - sb.append(" subTypeSchema: ").append(toIndentedString(inverseRelationship)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - public static ScholixRelationship fromScholixIndexRelationship(eu.dnetlib.dhp.schema.sx.scholix.ScholixRelationship inputRel) { - if(inputRel==null) - return null; - - ScholixRelationship result = new ScholixRelationship(); - - result.setName(relationMapping.getOrDefault(inputRel.getName(), "IsRelatedTo")); - result.setInverseRelationship(relationMapping.getOrDefault(inputRel.getInverse(), "IsRelatedTo")); - result.setSchema(inputRel.getSchema()); - return result; - - } - -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java deleted file mode 100644 index 42f30acd..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v1/ScholixV1.java +++ /dev/null @@ -1,184 +0,0 @@ -package eu.dnetlib.scholix.api.model.v1; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.Scholix; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotBlank; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -public class ScholixV1 implements Serializable { - - @JsonProperty("linkProvider") - private List linkProvider; - - @JsonProperty("publicationDate") - private String publicationDate; - - @NotBlank - @JsonProperty("relationship") - private ScholixRelationship relationship; - - @NotBlank - @JsonProperty("source") - private ScholixItem source; - - @NotBlank - @JsonProperty("target") - private ScholixItem target; - - - - public ScholixV1 linkProvider (final List linkProvider ) { - this.linkProvider = linkProvider; - return this; - } - - @Schema(description = "An entity responsible for making this record available online") - public List getLinkProvider() { - return linkProvider; - } - - public ScholixV1 addLinkProviderItem(ScholixProvider linkProviderItem) { - if (this.linkProvider == null) { - this.linkProvider = new ArrayList<>(); - } - this.linkProvider.add(linkProviderItem); - return this; - } - - public void setLinkProvider(List linkProvider) { - this.linkProvider = linkProvider; - } - - @Schema(description = "date of formal issuance (e.g., publication) of the resource; generally different from source object and target object publication dates") - public String getPublicationDate() { - return publicationDate; - } - - public ScholixV1 publicationDate(String publicationDate) { - this.publicationDate = publicationDate; - return this; - } - - public void setPublicationDate(String publicationDate) { - this.publicationDate = publicationDate; - } - - @Schema(description = "Semantics of the relationship from source to target") - public ScholixRelationship getRelationship() { - return relationship; - } - - public ScholixV1 relationship(ScholixRelationship relationship) { - this.relationship = relationship; - return this; - } - - public void setRelationship(ScholixRelationship relationship) { - this.relationship = relationship; - } - - @Schema(description = "Root element relative to all properties describing the link’s source object.") - public ScholixItem getSource() { - return source; - } - - - public ScholixV1 source(ScholixItem source) { - this.source = source; - return this; - } - public void setSource(ScholixItem source) { - this.source = source; - } - - @Schema(description = "Root element relative to all properties describing the link’s target object.") - public ScholixItem getTarget() { - return target; - } - - public ScholixV1 target(ScholixItem target) { - this.target = target; - return this; - } - - public void setTarget(ScholixItem target) { - this.target = target; - } - - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ScholixV1 scholixV1 = (ScholixV1) o; - return Objects.equals(this.linkProvider, scholixV1.getLinkProvider()) && - Objects.equals(this.publicationDate, scholixV1.getPublicationDate()) && - Objects.equals(this.relationship, scholixV1.getRelationship()) && - Objects.equals(this.source, scholixV1.getSource()) && - Objects.equals(this.target, scholixV1.getTarget()); - } - - @Override - public int hashCode() { - return Objects.hash(linkProvider, publicationDate, relationship, source, target); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class ScholixV1 {\n"); - - sb.append(" linkProvider: ").append(toIndentedString(linkProvider)).append("\n"); - sb.append(" publicationDate: ").append(toIndentedString(publicationDate)).append("\n"); - sb.append(" relationship: ").append(toIndentedString(relationship)).append("\n"); - sb.append(" source: ").append(toIndentedString(source)).append("\n"); - sb.append(" target: ").append(toIndentedString(target)).append("\n"); - - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - - public static ScholixV1 fromScholix(Scholix input) { - if (input == null) - return null; - final ScholixV1 result = new ScholixV1(); - - - if (input.getLinkprovider()!= null) - result.setLinkProvider(input.getLinkprovider() - .stream() - .map(ScholixProvider::fromScholixEntityId) - .collect(Collectors.toList())); - - result.setPublicationDate(input.getPublicationDate()); - - result.setRelationship(ScholixRelationship.fromScholixIndexRelationship(input.getRelationship())); - - result.setSource(ScholixItem.fromScholixResource(input.getSource())); - result.setTarget(ScholixItem.fromScholixResource(input.getTarget())); - return result; - } -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java deleted file mode 100644 index d4a5697e..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/LinkProviderType.java +++ /dev/null @@ -1,124 +0,0 @@ -package eu.dnetlib.scholix.api.model.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import java.util.Objects; - -/** - * The type Link provider type. - */ -public class LinkProviderType { - @NotBlank - @JsonProperty("name") - private String name = null; - - @NotBlank - @JsonProperty("totalRelationships") - private Integer totalRelationships = null; - - /** - * Name link provider type. - * - * @param name the name - * @return the link provider type - */ - public LinkProviderType name(String name) { - this.name = name; - return this; - } - - /** - * Get name - * - * @return name name - */ - @Schema(description = "The Publisher Name") - @Size(max=300) - public String getName() { - return name; - } - - /** - * Sets name. - * - * @param name the name - */ - public void setName(String name) { - this.name = name; - } - - /** - * Total relationships link provider type. - * - * @param totalRelationships the total relationships - * @return the link provider type - */ - public LinkProviderType totalRelationships(Integer totalRelationships) { - this.totalRelationships = totalRelationships; - return this; - } - - /** - * Get totalRelationships - * - * @return totalRelationships total relationships - */ - @Schema(description = "Total number of relationships that the publisher provides") - public Integer getTotalRelationships() { - return totalRelationships; - } - - /** - * Sets total relationships. - * - * @param totalRelationships the total relationships - */ - public void setTotalRelationships(Integer totalRelationships) { - this.totalRelationships = totalRelationships; - } - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - LinkProviderType linkPublisher = (LinkProviderType) o; - return Objects.equals(this.name, linkPublisher.name) && - Objects.equals(this.totalRelationships, linkPublisher.totalRelationships); - } - - @Override - public int hashCode() { - return Objects.hash(name, totalRelationships); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class LinkPublisher {\n"); - - sb.append(" name: ").append(toIndentedString(name)).append("\n"); - sb.append(" totalRelationships: ").append(toIndentedString(totalRelationships)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } -} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/PageResultType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/PageResultType.java deleted file mode 100644 index cb7c262e..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/PageResultType.java +++ /dev/null @@ -1,114 +0,0 @@ -package eu.dnetlib.scholix.api.model.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotBlank; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -/** - * The main class that show the page result from the method - * /l2/links - */ -public class PageResultType implements Serializable { - - @NotBlank - @JsonProperty("currentPage") - @ApiModelProperty(position = 0) - private Integer currentPage = 0; - - @NotBlank - @JsonProperty("totalLinks") - @ApiModelProperty(position = 1) - private Integer totalLinks= 0; - - @NotBlank - @JsonProperty("totalPages") - @ApiModelProperty(position = 2) - private Integer totalPages = 0; - - @NotBlank - @JsonProperty("result") - @ApiModelProperty(position = 3) - private List result = new ArrayList<>(); - - - /** - * Gets current page. - * - * @return the current page - */ - @Schema(description = "The Current page of the results") - public Integer getCurrentPage() { - return currentPage; - } - - /** - * Sets current page. - * - * @param currentPage the current page - */ - public void setCurrentPage(Integer currentPage) { - this.currentPage = currentPage; - } - - /** - * Gets total links. - * - * @return the total links - */ - @Schema(description = "The total number of Links found by the query") - public Integer getTotalLinks() { - return totalLinks; - } - - /** - * Sets total links. - * - * @param totalLinks the total links - */ - public void setTotalLinks(Integer totalLinks) { - this.totalLinks = totalLinks; - } - - /** - * Gets total pages. - * - * @return the total pages - */ - @Schema(description = "The Total number of pages") - public Integer getTotalPages() { - return totalPages; - } - - /** - * Sets total pages. - * - * @param totalPages the total pages - */ - public void setTotalPages(Integer totalPages) { - this.totalPages = totalPages; - } - - /** - * Gets result. - * - * @return the result - */ - @Schema(description = "The First page of Scholix results") - public List getResult() { - return result; - } - - /** - * Sets result. - * - * @param result the result - */ - public void setResult(List result) { - this.result = result; - } -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java deleted file mode 100644 index 807b3e3f..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/RelationshipType.java +++ /dev/null @@ -1,109 +0,0 @@ -package eu.dnetlib.scholix.api.model.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixRelationship; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotNull; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * The type Relationship type. - */ -public class RelationshipType { - - @NotNull - @JsonProperty("Name") - private String name; - - @JsonProperty("SubType") - private String subType; - - @JsonProperty("SubTypeSchema") - private String subTypeSchema; - - - public static Map relationMapping = Stream.of(new String[][] { - { "issupplementto", "IsSupplementTo" }, - { "issupplementedby", "IsSupplementedBy" }, - { "references", "References" }, - { "isreferencedby", "IsReferencedBy" }, - }).collect(Collectors.toMap(data -> data[0], data -> data[1])); - - - /** - * Gets The relationship type chosen from a Scholix controlled vocabulary - * - * @return the name - */ - @Schema(description = "The relationship type chosen from a Scholix controlled vocabulary") - public String getName() { - return name; - } - - /** - * Sets The relationship type chosen from a Scholix controlled vocabulary - * - * @param name the name - * @return the RelationshipType instance - */ - public RelationshipType setName(String name) { - this.name = name; - return this; - } - - /** - * Gets The sub-type of RelationshipType.Name - * - * @return the sub type - */ - @Schema(description = "The sub-type of RelationshipType.Name") - public String getSubType() { - return subType; - } - - /** - * Sets The sub-type of RelationshipType.Name - * - * @param subType the sub type - * @return the RelationshipType instance - */ - public RelationshipType setSubType(String subType) { - this.subType = subType; - return this; - } - - /** - * Gets The name of the schema or controlled list from which RelationshipSub-type is sourced. - * - * @return the sub type schema - */ - @Schema(description = "The name of the schema or controlled list from which RelationshipSub-type is sourced") - public String getSubTypeSchema() { - return subTypeSchema; - } - - /** - * Sets The name of the schema or controlled list from which RelationshipSub-type is sourced. - * - * @param subTypeSchema the sub type schema - * @return the RelationshipType instance - */ - public RelationshipType setSubTypeSchema(String subTypeSchema) { - this.subTypeSchema = subTypeSchema; - return this; - } - - public static RelationshipType fromScholixRelationship(ScholixRelationship inputRels) { - - return new RelationshipType() - .setName(relationMapping.getOrDefault(inputRels.getName(), "IsRelatedTo")) - .setSubType(inputRels.getName()) - .setSubTypeSchema(inputRels.getSchema()); - - } -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java deleted file mode 100644 index 0f43c77f..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixCreatorType.java +++ /dev/null @@ -1,86 +0,0 @@ -package eu.dnetlib.scholix.api.model.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotBlank; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * The type Scholix creator type. - */ -public class ScholixCreatorType { - - @NotBlank - @JsonProperty("name") - private String name = null; - - - @NotBlank - @JsonProperty("identifier") - private List identifier = new ArrayList<>(); - - /** - * Gets A List of unique string that identifies the creator - * - * @return the identifier - */ - @Schema(description = "A List of unique string that identifies the creator") - public List getIdentifier() { - return identifier; - } - - /** - * Sets A List of unique string that identifies the creator - * - * @param identifier the identifier - * @return the identifier - */ - public ScholixCreatorType setIdentifier(List identifier) { - this.identifier = identifier; - return this; - } - - - /** - * Gets The name of the Object Creator - * - * @return the name - */ - @Schema(description = "The name of the Object Creator") - public String getName() { - return name; - } - - /** - * Sets The name of the Object Creator - * - * @param name the name - * @return the name - */ - public ScholixCreatorType setName(String name) { - this.name = name; - return this; - } - - public static ScholixCreatorType fromScholixEntityId(final ScholixEntityId inputCreator) { - if (inputCreator == null) - return null; - ScholixCreatorType instance = new ScholixCreatorType().setName(inputCreator.getName()); - - - if (inputCreator.getIdentifiers()!= null && inputCreator.getIdentifiers().size()>0) - instance.setIdentifier(inputCreator.getIdentifiers() - .stream() - .map(i ->new ScholixIdentifierType() - .setId(i.getIdentifier()) - .setIdScheme(i.getSchema())) - .collect(Collectors.toList())); - return instance; - - - } -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java deleted file mode 100644 index 662b9a4f..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixIdentifierType.java +++ /dev/null @@ -1,105 +0,0 @@ -package eu.dnetlib.scholix.api.model.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixIdentifier; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotBlank; -import java.util.Objects; - -/** - * The type Scholix identifier type. - */ -public class ScholixIdentifierType { - - @NotBlank - @JsonProperty("ID") - private String id = null; - - @NotBlank - @JsonProperty("IDScheme") - private String idScheme = null; - - @NotBlank - @JsonProperty("IDURL") - private String idURL = null; - - - /** - * Gets The identifier - * - * @return the id - */ - @Schema(description = "The identifier") - public String getId() { - return id; - } - - /** - * Sets The identifier - * - * @param id the id - * @return the id - */ - public ScholixIdentifierType setId(String id) { - this.id = id; - return this; - } - - /** - * Gets The scheme or namespace of the identifier string - * - * @return the id scheme - */ - @Schema(description = "The scheme or namespace of the identifier string") - public String getIdScheme() { - return idScheme; - } - - /** - * Sets The scheme or namespace of the identifier string - * - * @param idScheme the id scheme - * @return the id scheme - */ - public ScholixIdentifierType setIdScheme(String idScheme) { - this.idScheme = idScheme; - return this; - } - - /** - * Gets An internet resolvable form of the identifier - * - * @return the id url - */ - @Schema(description = "An internet resolvable form of the identifier") - public String getIdURL() { - return idURL; - } - - /** - * Sets An internet resolvable form of the identifier - * - * @param idURL the id url - * @return the id url - */ - public ScholixIdentifierType setIdURL(String idURL) { - this.idURL = idURL; - return this; - } - - - public static ScholixIdentifierType fromScholixIdentifier(ScholixIdentifier input) { - if (input== null) - return null; - final ScholixIdentifierType instance = new ScholixIdentifierType(); - - instance.setId(input.getIdentifier()); - instance.setIdScheme(input.getSchema()); - instance.setIdURL(input.getUrl()); - return instance; - } - - - -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java deleted file mode 100644 index c0fdcc24..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixItemType.java +++ /dev/null @@ -1,188 +0,0 @@ -package eu.dnetlib.scholix.api.model.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixResource; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * The type Scholix item type. - */ -public class ScholixItemType { - - @JsonProperty("Identifier") - private List identifier = new ArrayList(); - - @JsonProperty("Title") - private String title; - - @JsonProperty("Type") - private String type; - - @JsonProperty("Creator") - private List creator = new ArrayList<>(); - - @JsonProperty("PublicationDate") - private String publicationDate; - - @JsonProperty("Publisher") - private List publisher = new ArrayList<>(); - - - /** - * Gets identifier. - * - * @return the identifier - */ - public List getIdentifier() { - return identifier; - } - - /** - * Sets identifier. - * - * @param identifier the identifier - * @return the identifier - */ - public ScholixItemType setIdentifier(List identifier) { - this.identifier = identifier; - return this; - } - - /** - * Gets title. - * - * @return the title - */ - public String getTitle() { - return title; - } - - /** - * Sets title. - * - * @param title the title - * @return the title - */ - public ScholixItemType setTitle(String title) { - this.title = title; - return this; - } - - /** - * Gets type. - * - * @return the type - */ - public String getType() { - return type; - } - - /** - * Sets type. - * - * @param type the type - * @return the type - */ - public ScholixItemType setType(String type) { - this.type = type; - return this; - } - - /** - * Gets creator. - * - * @return the creator - */ - public List getCreator() { - return creator; - } - - /** - * Sets creator. - * - * @param creator the creator - * @return the creator - */ - public ScholixItemType setCreator(List creator) { - this.creator = creator; - return this; - } - - /** - * Gets publication date. - * - * @return the publication date - */ - public String getPublicationDate() { - return publicationDate; - } - - /** - * Sets publication date. - * - * @param publicationDate the publication date - * @return the publication date - */ - public ScholixItemType setPublicationDate(String publicationDate) { - this.publicationDate = publicationDate; - return this; - } - - /** - * Gets publisher. - * - * @return the publisher - */ - public List getPublisher() { - return publisher; - } - - /** - * Sets publisher. - * - * @param publisher the publisher - * @return the publisher - */ - public ScholixItemType setPublisher(List publisher) { - this.publisher = publisher; - return this; - } - - - - public static ScholixItemType fromScholixResource(final ScholixResource input) { - if (input == null) - return null; - final ScholixItemType instance = new ScholixItemType(); - instance.setType("publication".equalsIgnoreCase(input.getObjectType())?"literature": "dataset"); - instance.setTitle(input.getTitle()); - - if (input.getIdentifier()!= null) - instance.setIdentifier(input.getIdentifier() - .stream() - .map(ScholixIdentifierType::fromScholixIdentifier ) - .collect(Collectors.toList()) - ); - - - if (input.getPublisher()!= null) { - instance.setPublisher( - input.getPublisher().stream() - .map(ScholixLinkProviderType::fromScholixEntityId) - .collect(Collectors.toList()) - ); - } - - instance.setPublicationDate(input.getPublicationDate()); - if(input.getCreator()!=null) - instance.setCreator(input.getCreator() - .stream() - .map(ScholixCreatorType::fromScholixEntityId) - .collect(Collectors.toList())); - - return instance; - } -} diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java deleted file mode 100644 index 2fcab411..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixLinkProviderType.java +++ /dev/null @@ -1,88 +0,0 @@ -package eu.dnetlib.scholix.api.model.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.ScholixEntityId; -import io.swagger.v3.oas.annotations.media.Schema; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * The type Scholix link provider type. - */ -public class ScholixLinkProviderType { - @NotBlank - @JsonProperty("name") - private String name = null; - - - @NotBlank - @JsonProperty("identifier") - private List identifier = new ArrayList<>(); - - /** - * Gets A List of unique string that identifies the object - * - * @return the identifier - */ - @Schema(description = "A List of unique string that identifies the object") - public List getIdentifier() { - return identifier; - } - - /** - * Sets A List of unique string that identifies the object - * - * @param identifier the identifier - * @return the identifier - */ - public ScholixLinkProviderType setIdentifier(List identifier) { - this.identifier = identifier; - return this; - } - - - /** - * Gets The name of the Provider - * - * @return the name - */ - @Schema(description = "The name of the Provider") - public String getName() { - return name; - } - - /** - * Sets The name of the Provider - * - * @param name the name - * @return the name - */ - public ScholixLinkProviderType setName(String name) { - this.name = name; - return this; - } - - - public static ScholixLinkProviderType fromScholixEntityId(final ScholixEntityId provider) { - if (provider == null) - return null; - ScholixLinkProviderType instance = new ScholixLinkProviderType().setName(provider.getName()); - - - if (provider.getIdentifiers()!= null && provider.getIdentifiers().size()>0) - instance.setIdentifier(provider.getIdentifiers() - .stream() - .map(i ->new ScholixIdentifierType() - .setId(i.getIdentifier()) - .setIdScheme(i.getSchema())) - .collect(Collectors.toList())); - return instance; - - - } -} \ No newline at end of file diff --git a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java b/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java deleted file mode 100644 index 9deaa803..00000000 --- a/apps/scholexplorer-api/src/main/java/eu/dnetlib/scholix/api/model/v2/ScholixType.java +++ /dev/null @@ -1,196 +0,0 @@ -package eu.dnetlib.scholix.api.model.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import eu.dnetlib.dhp.schema.sx.scholix.Scholix; -import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.NotBlank; -import java.io.Serializable; -import java.util.List; -import java.util.stream.Collectors; - -/** - * The type Scholix type. - */ -public class ScholixType implements Serializable { - - - @NotBlank - @JsonProperty("RelationshipType") - private RelationshipType relationshipType ; - - @NotBlank - @JsonProperty("source") - private ScholixItemType source ; - - @NotBlank - @JsonProperty("target") - private ScholixItemType target ; - - @JsonProperty("HarvestDate") - private String harvestDate ; - - - @JsonProperty("LicenseURL") - private String licenseURL ; - - @JsonProperty("LinkProvider") - private List linkProvider ; - - @JsonProperty("LinkPublicationDate") - private String linkPublicationDate ; - - - /** - * Gets the nature of the relationship between the source object and target object in this Link Information Package - * - * @return the relationship type - */ - @Schema(description = "The nature of the relationship between the source object and target object in this Link Information Package") - public RelationshipType getRelationshipType() { - return relationshipType; - } - - /** - * Sets relationship type. - * - * @param relationshipType the relationship type - */ - public void setRelationshipType(RelationshipType relationshipType) { - this.relationshipType = relationshipType; - } - - /** - * Gets Root element relative to all properties describing the link’s source object - * - * @return the source - */ - @Schema(description = "Root element relative to all properties describing the link’s source object") - public ScholixItemType getSource() { - return source; - } - - /** - * Sets source. - * - * @param source the source - */ - public void setSource(ScholixItemType source) { - this.source = source; - } - - /** - * Gets Root element relative to all properties describing the link’s target object - * - * @return the target - */ - @Schema(description = "Gets Root element relative to all properties describing the link’s target object") - public ScholixItemType getTarget() { - return target; - } - - /** - * Sets target. - * - * @param target the target - */ - public void setTarget(ScholixItemType target) { - this.target = target; - } - - /** - * Gets harvest date. - * - * @return the harvest date - */ - public String getHarvestDate() { - return harvestDate; - } - - /** - * Sets harvest date. - * - * @param harvestDate the harvest date - */ - public void setHarvestDate(String harvestDate) { - this.harvestDate = harvestDate; - } - - /** - * Gets The URL of the license for the Scholix Link Information Package - * - * @return the license url - */ - @Schema(description = "The URL of the license for the Scholix Link Information Package") - public String getLicenseURL() { - return licenseURL; - } - - /** - * Sets license url. - * - * @param licenseURL the license url - */ - public void setLicenseURL(String licenseURL) { - this.licenseURL = licenseURL; - } - - /** - * Gets The source(s) of this Link Information Package. - * - * @return the link provider - */ - @Schema(description = "The source(s) of this Link Information Package") - public List getLinkProvider() { - return linkProvider; - } - - /** - * Sets link provider. - * - * @param linkProvider the link provider - */ - public void setLinkProvider(List linkProvider) { - this.linkProvider = linkProvider; - } - - /** - * Gets Date when this Link Information Package was first formally issued from this current Provider - * - * @return the link publication date - */ - @Schema(description = "Date when this Link Information Package was first formally issued from this current Provider") - - public String getLinkPublicationDate() { - return linkPublicationDate; - } - - /** - * Sets link publication date. - * - * @param linkPublicationDate the link publication date - */ - public void setLinkPublicationDate(String linkPublicationDate) { - this.linkPublicationDate = linkPublicationDate; - } - - - - public static ScholixType fromScholix(Scholix input) { - final ScholixType instance = new ScholixType(); - instance.setLinkPublicationDate(input.getPublicationDate()); - instance.setHarvestDate(input.getPublicationDate()); - instance.setRelationshipType(RelationshipType.fromScholixRelationship(input.getRelationship())); - - if(input.getLinkprovider()!= null && input.getLinkprovider().size()>0) - instance.setLinkProvider(input.getLinkprovider() - .stream() - .map(ScholixLinkProviderType::fromScholixEntityId) - .collect(Collectors.toList()) - ); - - - instance.setSource(ScholixItemType.fromScholixResource(input.getSource())); - instance.setTarget(ScholixItemType.fromScholixResource(input.getTarget())); - return instance; - } -} diff --git a/pom.xml b/pom.xml index d3e31c1e..92837a02 100644 --- a/pom.xml +++ b/pom.xml @@ -398,7 +398,7 @@ UTF-8 3.6.0 1.8 - 2.10.24 + 2.10.30-SCHOLEXPLORER-SNAPSHOT 7.1.0 3.4.2 2.8.0 -- 2.17.1