diff --git a/apps/bioschemas-api/pom.xml b/apps/bioschemas-api/pom.xml index 0e529de5..8310774b 100644 --- a/apps/bioschemas-api/pom.xml +++ b/apps/bioschemas-api/pom.xml @@ -3,7 +3,7 @@ eu.dnetlib.dhp apps - 3.2.9-SNAPSHOT + 3.3.3-SNAPSHOT ../pom.xml diff --git a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/MainApplication.java b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/MainApplication.java index 53713a06..d8078ce9 100644 --- a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/MainApplication.java +++ b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/MainApplication.java @@ -1,42 +1,52 @@ package eu.dnetlib.bioschemas.api; -import eu.dnetlib.common.app.AbstractDnetApp; +import io.swagger.v3.oas.models.tags.Tag; +import org.springdoc.core.GroupedOpenApi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; 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; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import eu.dnetlib.common.app.AbstractDnetApp; + +import java.util.Arrays; +import java.util.List; @SpringBootApplication -@EnableSwagger2 @EnableCaching @EnableScheduling @ComponentScan(basePackages = "eu.dnetlib") public class MainApplication extends AbstractDnetApp { + public static final String BIOSCHEMAS_APIS = "D-Net Bioschemas Service APIs"; + public static void main(final String[] args) { SpringApplication.run(MainApplication.class, args); } + @Bean + public GroupedOpenApi publicApi() { + return GroupedOpenApi.builder() + .group(BIOSCHEMAS_APIS) + .pathsToMatch("/api/**") + .build(); + } + @Override - protected void configSwagger(final Docket docket) { - docket.select() - .apis(RequestHandlerSelectors.any()) - .paths(p -> p.contains("/api/")) - .build() - .apiInfo(new ApiInfoBuilder() - .title("D-Net Bioschemas Service APIs") - .description("APIs documentation") - .version("1.1") - .contact(ApiInfo.DEFAULT_CONTACT) - .license("Apache 2.0") - .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0") - .build()); + protected String swaggerTitle() { + return BIOSCHEMAS_APIS; + } + + @Override + protected List swaggerTags() { + return Arrays.asList(new Tag().name(BIOSCHEMAS_APIS).description(BIOSCHEMAS_APIS)); + } + + @Override + protected String swaggerDesc() { + return BIOSCHEMAS_APIS; } } diff --git a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/ServiceScrapeDriver.java b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/ServiceScrapeDriver.java index bbe7adc8..aec1e185 100644 --- a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/ServiceScrapeDriver.java +++ b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/ServiceScrapeDriver.java @@ -44,19 +44,12 @@ public class ServiceScrapeDriver { private static final Log logger = LogFactory.getLog(ServiceScrapeDriver.class); - public ServiceScrapeDriver(String sitemapUrl, String sitemapURLKey, String maxScrapedPages, String outputFilename) { + public ServiceScrapeDriver(String sitemapUrl, String sitemapURLKey, String maxScrapedPages, String outputFilename, String outputFolder) { this.sitemapUrl = sitemapUrl; this.sitemapURLKey = sitemapURLKey; this.maxScrapedPages = maxScrapedPages; this.outputFilename = outputFilename; - } - - /** - * Runs the scrape process - * - */ - public void start() throws IOException { - runScrape(); + this.outputFolder = outputFolder; } /** @@ -66,7 +59,7 @@ public class ServiceScrapeDriver { * as been left in situ in case it is useful in the future. * */ - private void runScrape() throws IOException { + public void runScrape() throws IOException { processProperties(); String url = sitemapUrl.toLowerCase(); Elements urls = UrlParser.getSitemapList(getSitemapUrl(), getSitemapURLKey()); @@ -189,8 +182,6 @@ public class ServiceScrapeDriver { waitTime = Integer.parseInt(prop.getProperty("waitTime").trim()); logger.info(" waitTime: " + waitTime); - outputFolder = prop.getProperty("outputFolder").trim(); - logger.info(" outputFolder: " + outputFolder); numberOfPagesToCrawlInALoop = Integer.parseInt(prop.getProperty("numberOfPagesToCrawlInALoop").trim()); logger.info(" numberOfPagesToCrawl: " + numberOfPagesToCrawlInALoop); totalNumberOfPagesToCrawlInASession = Integer.parseInt(prop.getProperty("totalNumberOfPagesToCrawlInASession").trim()); diff --git a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/controller/BioschemasAPIController.java b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/controller/BioschemasAPIController.java index b810e0ef..2deed3fa 100644 --- a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/controller/BioschemasAPIController.java +++ b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/controller/BioschemasAPIController.java @@ -1,9 +1,14 @@ package eu.dnetlib.bioschemas.api.controller; +import eu.dnetlib.bioschemas.api.MainApplication; import eu.dnetlib.bioschemas.api.scraper.ScrapingExecution; import eu.dnetlib.bioschemas.api.scraper.ScrapingExecutor; import eu.dnetlib.bioschemas.api.utils.BioschemasException; import eu.dnetlib.common.controller.AbstractDnetController; +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.tags.Tag; import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; import org.apache.commons.logging.Log; @@ -27,6 +32,7 @@ import java.nio.charset.StandardCharsets; @RestController @RequestMapping("/api") +@Tag(name = MainApplication.BIOSCHEMAS_APIS) public class BioschemasAPIController extends AbstractDnetController { @Value("${outputFolder}") @@ -41,19 +47,24 @@ public class BioschemasAPIController extends AbstractDnetController { private static final Log log = LogFactory.getLog(BioschemasAPIController.class); + @Operation(summary = "start the scraping operation", description = "

Working input values are in the following table


datasourceKeysitemapUrl
pedhttps://proteinensemble.org/sitemap2.xml.gz
disprothttps://disprot.org/sitemap2.xml.gz
mobidbhttps://mobidb.org/sitemap2.xml.gz
") @GetMapping("/startScraping") - public ScrapingExecution startScraping(@RequestParam final String datasourceKey, @RequestParam final String sitemapUrl, final HttpServletRequest req) { + public ScrapingExecution startScraping(@Parameter(name = "datasourceKey") @RequestParam final String datasourceKey, + @Parameter(name = "sitemapUrl") @RequestParam final String sitemapUrl, + final HttpServletRequest req) { logger.info(" datasourceKey: "+datasourceKey+" sitemapUrl:"+sitemapUrl); - return scrapingExecutor.startScraping(datasourceKey, sitemapUrl, getOutputDataPattern(), req.getRemoteAddr()); + return scrapingExecutor.startScraping(datasourceKey, sitemapUrl, getOutputDataPattern(), req.getRemoteAddr(), getOutputFolder()); } + @Operation(summary = "check the status of last scraping operation") @GetMapping("/startScraping/status") public final ScrapingExecution statusScraping() { return scrapingExecutor.getLastScrapingExecution(); } + @Operation(summary = "retrieve the nquads downloaded for one specific provider") @RequestMapping(value = "/getNQuads", method = RequestMethod.GET) - public String getNQuads(@RequestParam final String datasourceKey, HttpServletResponse response) throws BioschemasException, IOException { + public String getNQuads(@Parameter(name = "datasourceKey") @RequestParam final String datasourceKey, HttpServletResponse response) throws BioschemasException, IOException { logger.info(" datasourceKey: "+datasourceKey); @@ -76,4 +87,12 @@ public class BioschemasAPIController extends AbstractDnetController { public String getOutputDataPattern() { return outputDataPattern; } + + public void setOutputFolder(String outputFolder) { + this.outputFolder = outputFolder; + } + + public void setOutputDataPattern(String outputDataPattern) { + this.outputDataPattern = outputDataPattern; + } } \ No newline at end of file diff --git a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/controller/HomeController.java b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/controller/HomeController.java index 8796f280..8f09a125 100644 --- a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/controller/HomeController.java +++ b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/controller/HomeController.java @@ -11,7 +11,7 @@ public class HomeController extends AbstractDnetController { "/doc", "/swagger" }) public String apiDoc() { - return "redirect:swagger-ui/"; + return "redirect:swagger-ui/index.html"; } } diff --git a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/scraper/ScrapingExecutor.java b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/scraper/ScrapingExecutor.java index e3ccb6ff..341f0d20 100644 --- a/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/scraper/ScrapingExecutor.java +++ b/apps/bioschemas-api/src/main/java/eu/dnetlib/bioschemas/api/scraper/ScrapingExecutor.java @@ -14,7 +14,7 @@ public class ScrapingExecutor { return lastScrapingExecution; } - public ScrapingExecution startScraping(final String datasourceKey, final String sitemapUrl, final String outputDataPattern, final String remoteAddr) { + public ScrapingExecution startScraping(final String datasourceKey, final String sitemapUrl, final String outputDataPattern, final String remoteAddr, final String outputFolder) { synchronized (lastScrapingExecution) { if (lastScrapingExecution.getStatus() != ScrapingStatus.RUNNING) { lastScrapingExecution.startNew("Scraping for " + datasourceKey + " " + sitemapUrl + " - request from " + remoteAddr); @@ -22,8 +22,8 @@ public class ScrapingExecutor { try { String sitemapUrlKey = "loc"; String outputFilename = datasourceKey.concat(outputDataPattern); - ServiceScrapeDriver service = new ServiceScrapeDriver(sitemapUrl, sitemapUrlKey, null, outputFilename); - service.start(); + ServiceScrapeDriver service = new ServiceScrapeDriver(sitemapUrl, sitemapUrlKey, null, outputFilename, outputFolder); + service.runScrape(); lastScrapingExecution.complete(); } catch (final Throwable e) { lastScrapingExecution.fail(e); diff --git a/apps/bioschemas-api/src/main/resources/application.properties b/apps/bioschemas-api/src/main/resources/application.properties index 43ac7dad..57bf37a9 100644 --- a/apps/bioschemas-api/src/main/resources/application.properties +++ b/apps/bioschemas-api/src/main/resources/application.properties @@ -1,9 +1,12 @@ -server.servlet.context-path=/bioschemas +server.servlet.context-path=/bioschemas-api server.port=8281 +server.public_url = http://localhost:8281/bioschemas-api +server.public_desc = API Base URL + spring.profiles.active=garr -logging.file.name = /var/log/bioschemas/log/bioschemas-api.log +logging.file.name = /var/log/bioschemas-api/bioschemas.log maven.pom.path = /META-INF/maven/eu.dnetlib.dhp/bioschemas-api/effective-pom.xml @@ -17,9 +20,8 @@ management.endpoints.web.path-mapping.prometheus = metrics management.endpoints.web.path-mapping.health = health waitTime=5 -outputFolder=/data +outputFolder=/data/bioschemas-harvest outputDataPattern=_base64_gzipped_nquads.txt numberOfPagesToCrawlInALoop=8 totalNumberOfPagesToCrawlInASession=32 -chromiumDriverLocation = /usr/local/bin/chromedriver scrapeVersion=1 \ No newline at end of file diff --git a/apps/dhp-broker-application/pom.xml b/apps/dhp-broker-application/pom.xml index 9c9b4795..931b0c70 100644 --- a/apps/dhp-broker-application/pom.xml +++ b/apps/dhp-broker-application/pom.xml @@ -4,7 +4,7 @@ eu.dnetlib.dhp apps - 3.2.9-SNAPSHOT + 3.3.3-SNAPSHOT ../pom.xml @@ -18,14 +18,6 @@ - - - javax.mail - mail - 1.4.7 - - - eu.dnetlib.dhp diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/LiteratureBrokerServiceApplication.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/LiteratureBrokerServiceApplication.java index 763299ca..034f0331 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/LiteratureBrokerServiceApplication.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/LiteratureBrokerServiceApplication.java @@ -1,14 +1,15 @@ package eu.dnetlib.broker; +import java.util.ArrayList; +import java.util.List; + +import org.springdoc.core.GroupedOpenApi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; import eu.dnetlib.common.app.AbstractDnetApp; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.Tag; -import springfox.documentation.spring.web.plugins.Docket; +import io.swagger.v3.oas.models.tags.Tag; @SpringBootApplication public class LiteratureBrokerServiceApplication extends AbstractDnetApp { @@ -24,22 +25,28 @@ public class LiteratureBrokerServiceApplication extends AbstractDnetApp { SpringApplication.run(LiteratureBrokerServiceApplication.class, args); } - @Override - protected void configSwagger(final Docket docket) { - docket.select() - .apis(RequestHandlerSelectors.any()) - .paths(p -> p.startsWith("/api/")) - .build() - .tags(new Tag(TAG_EVENTS, "Events management"), new Tag(TAG_SUBSCRIPTIONS, "Subscriptions management"), new Tag(TAG_NOTIFICATIONS, - "Notifications management"), new Tag(TAG_TOPIC_TYPES, "Topic types management"), new Tag(TAG_OPENAIRE, "OpenAIRE use case")) - .apiInfo(new ApiInfoBuilder() - .title("Literature Broker Service") - .description("APIs documentation") - .version("1.1") - .contact(ApiInfo.DEFAULT_CONTACT) - .license("Apache 2.0") - .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0") - .build()); - + @Bean + public GroupedOpenApi publicApi() { + return GroupedOpenApi.builder() + .group("Broker APIs") + .pathsToMatch("/api/**") + .build(); } + + @Override + protected String swaggerTitle() { + return "OpenAIRE Broker API"; + } + + @Override + protected List swaggerTags() { + final List tags = new ArrayList<>(); + tags.add(new Tag().name(TAG_EVENTS).description("Events management")); + tags.add(new Tag().name(TAG_SUBSCRIPTIONS).description("Subscriptions management")); + tags.add(new Tag().name(TAG_NOTIFICATIONS).description("Notifications management")); + tags.add(new Tag().name(TAG_TOPIC_TYPES).description("Topic types management")); + tags.add(new Tag().name(TAG_OPENAIRE).description("OpenAIRE use case")); + return tags; + } + } diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/LiteratureBrokerServiceConfiguration.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/LiteratureBrokerServiceConfiguration.java index a92f8862..785b9e5f 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/LiteratureBrokerServiceConfiguration.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/LiteratureBrokerServiceConfiguration.java @@ -16,10 +16,8 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import eu.dnetlib.broker.common.elasticsearch.Event; import eu.dnetlib.broker.common.elasticsearch.Notification; import eu.dnetlib.broker.common.properties.ElasticSearchProperties; -import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration -@EnableSwagger2 @EnableCaching @EnableScheduling @EnableTransactionManagement diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/ApiDocController.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/ApiDocController.java index ee648936..fcdd0e66 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/ApiDocController.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/ApiDocController.java @@ -8,6 +8,6 @@ public class ApiDocController { @GetMapping({ "/apidoc", "/api-doc", "/doc", "/swagger" }) public String apiDoc() { - return "redirect:swagger-ui/"; + return "redirect:swagger-ui/index.html"; } } diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/EventsController.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/EventsController.java index 5a981252..2f8f790a 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/EventsController.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/EventsController.java @@ -31,12 +31,12 @@ import eu.dnetlib.broker.common.elasticsearch.EventStatsManager.BrowseEntry; import eu.dnetlib.broker.common.subscriptions.Subscription; import eu.dnetlib.broker.common.subscriptions.SubscriptionRepository; import eu.dnetlib.common.controller.AbstractDnetController; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @RequestMapping("/api/events") -@Api(tags = LiteratureBrokerServiceApplication.TAG_EVENTS) +@Tag(name = LiteratureBrokerServiceApplication.TAG_EVENTS) public class EventsController extends AbstractDnetController { private static final Log log = LogFactory.getLog(AbstractDnetController.class); @@ -50,25 +50,25 @@ public class EventsController extends AbstractDnetController { @Autowired private EventStatsManager eventStatsManager; - @ApiOperation("Return an event by ID") + @Operation(summary = "Return an event by ID") @GetMapping("/{id}") public Event getEvent(@PathVariable final String id) { return eventRepository.findById(id).get(); } - @ApiOperation("Delete an event by ID") + @Operation(summary = "Delete an event by ID") @DeleteMapping("/{id}") public void deleteEvent(@PathVariable final String id) { eventRepository.deleteById(id); } - @ApiOperation("Save an event by ID") + @Operation(summary = "Save an event by ID") @PostMapping("/{id}") public Event saveEvent(@RequestBody final Event event) { return eventRepository.save(event); } - @ApiOperation("Return a page of events") + @Operation(summary = "Return a page of events") @GetMapping("/list/{page}/{pageSize}") public List events( @PathVariable final int page, @@ -76,7 +76,7 @@ public class EventsController extends AbstractDnetController { return Lists.newArrayList(eventRepository.findAll(PageRequest.of(page, pageSize))); } - @ApiOperation("Return a page of events by topic") + @Operation(summary = "Return a page of events by topic") @GetMapping("/byTopic/{page}/{pageSize}") public List eventsByTopic( @PathVariable final int page, @@ -85,7 +85,7 @@ public class EventsController extends AbstractDnetController { return Lists.newArrayList(eventRepository.findByTopic(topic, PageRequest.of(page, pageSize))); } - @ApiOperation("Delete all the events") + @Operation(summary = "Delete all the events") @DeleteMapping("/all") public Map clearEvents() { eventRepository.deleteAll(); @@ -94,13 +94,13 @@ public class EventsController extends AbstractDnetController { return res; } - @ApiOperation("Delete the expired events") + @Operation(summary = "Delete the expired events") @DeleteMapping("/expired") public Map deleteExpiredEvents() { return deleteEventsByExpiryDate(0, new Date().getTime()); } - @ApiOperation("Delete the events with the creationDate in a range") + @Operation(summary = "Delete the events with the creationDate in a range") @DeleteMapping("/byCreationDate/{from}/{to}") public Map deleteEventsByCreationDate(@PathVariable final long from, @PathVariable final long to) { final Map res = new HashMap<>(); @@ -113,7 +113,7 @@ public class EventsController extends AbstractDnetController { return res; } - @ApiOperation("Delete the events with the expiryDate in a range") + @Operation(summary = "Delete the events with the expiryDate in a range") @DeleteMapping("/byExpiryDate/{from}/{to}") public Map deleteEventsByExpiryDate(@PathVariable final long from, @PathVariable final long to) { new Thread(() -> { @@ -128,13 +128,13 @@ public class EventsController extends AbstractDnetController { return res; } - @ApiOperation("Return the topics of the indexed events (all)") + @Operation(summary = "Return the topics of the indexed events (all)") @GetMapping("/topics/all") public List browseTopics() { return eventStatsManager.browseTopics(); } - @ApiOperation("Return the topics of the indexed events (only with subscriptions)") + @Operation(summary = "Return the topics of the indexed events (only with subscriptions)") @GetMapping("/topics/withSubscriptions") public List browseTopicsWithSubscriptions() { diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/NotificationsController.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/NotificationsController.java index 6630d6ba..8c0330d3 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/NotificationsController.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/NotificationsController.java @@ -14,16 +14,15 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import eu.dnetlib.broker.LiteratureBrokerServiceApplication; import eu.dnetlib.broker.common.elasticsearch.Notification; import eu.dnetlib.broker.common.elasticsearch.NotificationRepository; import eu.dnetlib.common.controller.AbstractDnetController; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @RequestMapping("/api/notifications") -@Api(tags = LiteratureBrokerServiceApplication.TAG_NOTIFICATIONS) +@Tag(name = "LiteratureBrokerServiceApplication.TAG_NOTIFICATIONS") public class NotificationsController extends AbstractDnetController { private static final Log log = LogFactory.getLog(NotificationsController.class); @@ -31,31 +30,31 @@ public class NotificationsController extends AbstractDnetController { @Autowired private NotificationRepository notificationRepository; - @ApiOperation("Return a notification by ID") + @Operation(summary = "Return a notification by ID") @GetMapping("/{id}") public Notification getNotification(@PathVariable final String id) { return notificationRepository.findById(id).get(); } - @ApiOperation("Delete a notification by ID") + @Operation(summary = "Delete a notification by ID") @DeleteMapping("/{id}") public void deleteNotification(@PathVariable final String id) { notificationRepository.deleteById(id); } - @ApiOperation("Save a notification by ID") + @Operation(summary = "Save a notification by ID") @PostMapping("/{id}") public Notification saveNotification(@RequestBody final Notification notification) { return notificationRepository.save(notification); } - @ApiOperation("Delete all notifications") + @Operation(summary = "Delete all notifications") @DeleteMapping("") public void deleteAllNotifications() { notificationRepository.deleteAll(); } - @ApiOperation("Delete the notifications with the date in a range") + @Operation(summary = "Delete the notifications with the date in a range") @DeleteMapping("/byDate/{from}/{to}") public Map deleteNotificationsByDate(@PathVariable final long from, @PathVariable final long to) { new Thread(() -> { diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/StartMatchingController.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/StartMatchingController.java index b5ed84e9..2410f367 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/StartMatchingController.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/StartMatchingController.java @@ -16,13 +16,13 @@ import eu.dnetlib.broker.common.subscriptions.Subscription; import eu.dnetlib.broker.common.subscriptions.SubscriptionRepository; import eu.dnetlib.broker.matchers.SubscriptionEventMatcher; import eu.dnetlib.common.controller.AbstractDnetController; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; @Profile("!openaire") @RestController @RequestMapping("/api/matching") -@Api(tags = LiteratureBrokerServiceApplication.TAG_MATCHING) +@Tag(name = LiteratureBrokerServiceApplication.TAG_MATCHING) public class StartMatchingController extends AbstractDnetController { @Autowired @@ -31,7 +31,7 @@ public class StartMatchingController extends AbstractDnetController { @Autowired(required = false) private SubscriptionEventMatcher subscriptionEventMatcher; - @ApiOperation("Launch the thread that produces new notifications") + @Operation(summary = "Launch the thread that produces new notifications") @GetMapping("/start") public List startMatching() { if (subscriptionEventMatcher != null) { @@ -42,7 +42,7 @@ public class StartMatchingController extends AbstractDnetController { } } - @ApiOperation("Launch the thread that produces new notifications by subscriptuion id") + @Operation(summary = "Launch the thread that produces new notifications by subscriptuion id") @GetMapping("/start/{subscriptionId}") public List startMatching(@PathVariable final String subscriptionId) { final Optional s = subscriptionRepo.findById(subscriptionId); diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/SubscriptionsController.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/SubscriptionsController.java index ccc90c3b..ae587f1a 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/SubscriptionsController.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/SubscriptionsController.java @@ -29,12 +29,12 @@ import eu.dnetlib.broker.common.subscriptions.NotificationMode; import eu.dnetlib.broker.common.subscriptions.Subscription; import eu.dnetlib.broker.common.subscriptions.SubscriptionRepository; import eu.dnetlib.common.controller.AbstractDnetController; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @RequestMapping("/api/subscriptions") -@Api(tags = LiteratureBrokerServiceApplication.TAG_SUBSCRIPTIONS) +@Tag(name = LiteratureBrokerServiceApplication.TAG_SUBSCRIPTIONS) public class SubscriptionsController extends AbstractDnetController { @Autowired @@ -53,26 +53,26 @@ public class SubscriptionsController extends AbstractDnetController { } }; - @ApiOperation("Return the list of subscriptions") + @Operation(summary = "Return the list of subscriptions") @GetMapping("") public Iterable listSubscriptions() { return subscriptionRepo.findAll(); } - @ApiOperation("Return a subscription by ID") + @Operation(summary = "Return a subscription by ID") @GetMapping("/{id}") public Subscription getSubscription(@PathVariable final String id) { return subscriptionRepo.findById(id).get(); } - @ApiOperation("Delete a subscription by ID and its notifications") + @Operation(summary = "Delete a subscription by ID and its notifications") @DeleteMapping("/{id}") public void deleteSubscription(@PathVariable final String id) { subscriptionRepo.deleteById(id); notificationRepo.deleteBySubscriptionId(id); } - @ApiOperation("Perform a new subscription") + @Operation(summary = "Perform a new subscription") @PostMapping("") public Subscription registerSubscription(@RequestBody final InSubscription inSub) { final Subscription sub = inSub.asSubscription(); @@ -80,7 +80,7 @@ public class SubscriptionsController extends AbstractDnetController { return sub; } - @ApiOperation("Delete all subscriptions and notifications") + @Operation(summary = "Delete all subscriptions and notifications") @DeleteMapping("") public Map clearSubscriptions() { final Map res = new HashMap<>(); @@ -90,7 +90,7 @@ public class SubscriptionsController extends AbstractDnetController { return res; } - @ApiOperation("Reset the last notification date") + @Operation(summary = "Reset the last notification date") @DeleteMapping("/{id}/date") public void deleteNotificationDate(@PathVariable final String id) { final Subscription s = subscriptionRepo.findById(id).get(); @@ -98,7 +98,7 @@ public class SubscriptionsController extends AbstractDnetController { subscriptionRepo.save(s); } - @ApiOperation("Reset all the last notification dates") + @Operation(summary = "Reset all the last notification dates") @GetMapping("/resetLastNotificationDates") public void deleteAllNotificationDates() { for (final Subscription s : subscriptionRepo.findAll()) { diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/TopicsController.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/TopicsController.java index 6ab5d836..3b438ca9 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/TopicsController.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/controllers/TopicsController.java @@ -22,12 +22,12 @@ import eu.dnetlib.broker.LiteratureBrokerServiceApplication; import eu.dnetlib.broker.common.topics.TopicType; import eu.dnetlib.broker.common.topics.TopicTypeRepository; import eu.dnetlib.common.controller.AbstractDnetController; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @RequestMapping("/api/topic-types") -@Api(tags = LiteratureBrokerServiceApplication.TAG_TOPIC_TYPES) +@Tag(name = LiteratureBrokerServiceApplication.TAG_TOPIC_TYPES) public class TopicsController extends AbstractDnetController { @Autowired @@ -36,13 +36,13 @@ public class TopicsController extends AbstractDnetController { private final Predicate verifyExpression = Pattern.compile("^([a-zA-Z0-9._-]+|<[a-zA-Z0-9._-]+>)(\\/([a-zA-Z0-9._-]+|<[a-zA-Z0-9._-]+>))+$").asPredicate(); - @ApiOperation("Return the list of topic types") + @Operation(summary = "Return the list of topic types") @GetMapping("") public Iterable listTopicTypes() { return topicTypeRepo.findAll(); } - @ApiOperation("Register a new topic type") + @Operation(summary = "Register a new topic type") @PostMapping("/add") public TopicType registerTopicType(@RequestParam final String name, @RequestParam final String expression, @@ -61,20 +61,20 @@ public class TopicsController extends AbstractDnetController { return type; } - @ApiOperation("Return a topic type by ID") + @Operation(summary = "Return a topic type by ID") @GetMapping("/{id}") public TopicType getTopicType(@PathVariable final String id) { return topicTypeRepo.findById(id).get(); } - @ApiOperation("Delete a topic type by ID") + @Operation(summary = "Delete a topic type by ID") @DeleteMapping("/{id}") public List deleteTopicType(@PathVariable final String id) { topicTypeRepo.deleteById(id); return Arrays.asList("Done."); } - @ApiOperation("Delete all topic types") + @Operation(summary = "Delete all topic types") @DeleteMapping("") public Map clearTopicTypes() { final Map res = new HashMap<>(); diff --git a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/openaire/OpenaireBrokerController.java b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/openaire/OpenaireBrokerController.java index 16490ef7..54f8e725 100644 --- a/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/openaire/OpenaireBrokerController.java +++ b/apps/dhp-broker-application/src/main/java/eu/dnetlib/broker/openaire/OpenaireBrokerController.java @@ -56,13 +56,13 @@ import eu.dnetlib.broker.common.subscriptions.SubscriptionRepository; import eu.dnetlib.broker.events.output.DispatcherManager; import eu.dnetlib.broker.objects.OaBrokerEventPayload; import eu.dnetlib.common.controller.AbstractDnetController; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; @Profile("openaire") @RestController @RequestMapping("/api/openaireBroker") -@Api(tags = LiteratureBrokerServiceApplication.TAG_OPENAIRE) +@Tag(name = LiteratureBrokerServiceApplication.TAG_OPENAIRE) public class OpenaireBrokerController extends AbstractDnetController { @Autowired @@ -85,7 +85,7 @@ public class OpenaireBrokerController extends AbstractDnetController { private static final Log log = LogFactory.getLog(OpenaireBrokerController.class); - @ApiOperation("Return the datasources having events") + @Operation(summary = "Return the datasources having events") @GetMapping("/datasources") public List findDatasourcesWithEvents(@RequestParam(defaultValue = "false", required = false) final boolean useIndex) { return useIndex ? findDatasourcesWithEventsUsingIndex() : findDatasourcesWithEventsUsingDb(); @@ -123,7 +123,7 @@ public class OpenaireBrokerController extends AbstractDnetController { } } - @ApiOperation("Return the topics of the events of a datasource") + @Operation(summary = "Return the topics of the events of a datasource") @GetMapping("/topicsForDatasource") public List findTopicsForDatasource(@RequestParam final String ds, @RequestParam(defaultValue = "false", required = false) final boolean useIndex) { @@ -163,7 +163,7 @@ public class OpenaireBrokerController extends AbstractDnetController { } } - @ApiOperation("Return a page of events of a datasource (by topic)") + @Operation(summary = "Return a page of events of a datasource (by topic)") @GetMapping("/events/{nPage}/{size}") public EventsPage showEvents(@RequestParam final String ds, @RequestParam final String topic, @PathVariable final int nPage, @PathVariable final int size) { @@ -191,7 +191,7 @@ public class OpenaireBrokerController extends AbstractDnetController { return new EventsPage(ds, topic, nPage, overrideGetTotalPage(page, size), page.getTotalHits(), list); } - @ApiOperation("Return a page of events of a datasource (by query)") + @Operation(summary = "Return a page of events of a datasource (by query)") @PostMapping("/events/{nPage}/{size}") public EventsPage advancedShowEvents(@PathVariable final int nPage, @PathVariable final int size, @RequestBody final AdvQueryObject qObj) { @@ -227,7 +227,7 @@ public class OpenaireBrokerController extends AbstractDnetController { return new EventsPage(qObj.getDatasource(), qObj.getTopic(), nPage, overrideGetTotalPage(page, size), page.getTotalHits(), list); } - @ApiOperation("Perform a subscription") + @Operation(summary = "Perform a subscription") @PostMapping("/subscribe") public Subscription registerSubscription(@RequestBody final OpenaireSubscription oSub) { final Subscription sub = oSub.asSubscription(); @@ -237,7 +237,7 @@ public class OpenaireBrokerController extends AbstractDnetController { return sub; } - @ApiOperation("Return the subscriptions of an user (by email and datasource (optional))") + @Operation(summary = "Return the subscriptions of an user (by email and datasource (optional))") @GetMapping("/subscriptions") public Map> subscriptions(@RequestParam final String email, @RequestParam(required = false) final String ds) { final Iterable iter = subscriptionRepo.findBySubscriber(email); @@ -247,7 +247,7 @@ public class OpenaireBrokerController extends AbstractDnetController { .collect(Collectors.groupingBy(SimpleSubscriptionDesc::getDatasource)); } - @ApiOperation("Return a page of notifications") + @Operation(summary = "Return a page of notifications") @GetMapping("/notifications/{subscrId}/{nPage}/{size}") public EventsPage notifications(@PathVariable final String subscrId, @PathVariable final int nPage, @PathVariable final int size) { @@ -279,14 +279,14 @@ public class OpenaireBrokerController extends AbstractDnetController { } - @ApiOperation("Send notifications") + @Operation(summary = "Send notifications") @GetMapping("/notifications/send/{date}") private List sendMailForNotifications(@PathVariable final long date) { new Thread(() -> innerSendMailForNotifications(date)).start(); return Arrays.asList("Sending ..."); } - @ApiOperation("Update stats") + @Operation(summary = "Update stats") @GetMapping("/stats/update") private List updateStats() { new Thread(() -> { diff --git a/apps/dhp-broker-application/src/main/resources/application.properties b/apps/dhp-broker-application/src/main/resources/application.properties index 8c2fb00a..76eed4de 100644 --- a/apps/dhp-broker-application/src/main/resources/application.properties +++ b/apps/dhp-broker-application/src/main/resources/application.properties @@ -1,5 +1,8 @@ spring.profiles.active = dev,openaire +server.public_url = +server.public_desc = API Base URL + #logging.level.root=DEBUG maven.pom.path = /META-INF/maven/eu.dnetlib.dhp/dhp-broker-application/effective-pom.xml diff --git a/apps/dhp-broker-application/src/main/resources/static/index.html b/apps/dhp-broker-application/src/main/resources/static/index.html index 43869a07..e268c72b 100644 --- a/apps/dhp-broker-application/src/main/resources/static/index.html +++ b/apps/dhp-broker-application/src/main/resources/static/index.html @@ -27,7 +27,7 @@ Tools diff --git a/apps/dhp-broker-public-application/pom.xml b/apps/dhp-broker-public-application/pom.xml index 9e6df821..3420d26b 100644 --- a/apps/dhp-broker-public-application/pom.xml +++ b/apps/dhp-broker-public-application/pom.xml @@ -4,7 +4,7 @@ eu.dnetlib.dhp apps - 3.2.9-SNAPSHOT + 3.3.3-SNAPSHOT ../pom.xml diff --git a/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/BrokerConfiguration.java b/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/BrokerConfiguration.java index b4721971..01993c09 100644 --- a/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/BrokerConfiguration.java +++ b/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/BrokerConfiguration.java @@ -16,10 +16,8 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import eu.dnetlib.broker.common.elasticsearch.Event; import eu.dnetlib.broker.common.elasticsearch.Notification; import eu.dnetlib.broker.common.properties.ElasticSearchProperties; -import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration -@EnableSwagger2 @EnableCaching @EnableScheduling @EnableTransactionManagement diff --git a/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/BrokerPublicApplication.java b/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/BrokerPublicApplication.java index 2093ec7c..eebab9f3 100644 --- a/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/BrokerPublicApplication.java +++ b/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/BrokerPublicApplication.java @@ -1,14 +1,15 @@ package eu.dnetlib.broker; +import java.util.Arrays; +import java.util.List; + +import org.springdoc.core.GroupedOpenApi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; import eu.dnetlib.common.app.AbstractDnetApp; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.Tag; -import springfox.documentation.spring.web.plugins.Docket; +import io.swagger.v3.oas.models.tags.Tag; @SpringBootApplication public class BrokerPublicApplication extends AbstractDnetApp { @@ -19,22 +20,22 @@ public class BrokerPublicApplication extends AbstractDnetApp { SpringApplication.run(BrokerPublicApplication.class, args); } - @Override - protected void configSwagger(final Docket docket) { - - docket.select() - .apis(RequestHandlerSelectors.any()) - .paths(p -> p.startsWith("/")) - .build() - .tags(new Tag(OA_PUBLIC_APIS, OA_PUBLIC_APIS)) - .apiInfo(new ApiInfoBuilder() - .title("OpenAIRE Public Broker API") - .description("APIs documentation") - .version("1.1") - .contact(ApiInfo.DEFAULT_CONTACT) - .license("Apache 2.0") - .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0") - .build()); - + @Bean + public GroupedOpenApi publicApi() { + return GroupedOpenApi.builder() + .group("Broker Public APIs") + .pathsToMatch("/**") + .build(); } + + @Override + protected String swaggerTitle() { + return "OpenAIRE Public Broker API"; + } + + @Override + protected List swaggerTags() { + return Arrays.asList(new Tag().name(OA_PUBLIC_APIS).description(OA_PUBLIC_APIS)); + } + } diff --git a/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/oa/controllers/ApiDocController.java b/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/oa/controllers/ApiDocController.java index 6abe9b37..295e483b 100644 --- a/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/oa/controllers/ApiDocController.java +++ b/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/oa/controllers/ApiDocController.java @@ -8,6 +8,6 @@ public class ApiDocController { @GetMapping({ "/apidoc", "/api-doc", "/doc", "/swagger" }) public String apiDoc() { - return "redirect:swagger-ui/"; + return "redirect:swagger-ui/index.html"; } } diff --git a/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/oa/controllers/OpenairePublicController.java b/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/oa/controllers/OpenairePublicController.java index c5ad736e..18184d5a 100644 --- a/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/oa/controllers/OpenairePublicController.java +++ b/apps/dhp-broker-public-application/src/main/java/eu/dnetlib/broker/oa/controllers/OpenairePublicController.java @@ -63,13 +63,13 @@ import eu.dnetlib.broker.common.subscriptions.Subscription; import eu.dnetlib.broker.common.subscriptions.SubscriptionRepository; import eu.dnetlib.broker.objects.OaBrokerEventPayload; import eu.dnetlib.common.controller.AbstractDnetController; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; @Profile("openaire") @RestController @RequestMapping("/") -@Api(tags = BrokerPublicApplication.OA_PUBLIC_APIS) +@Tag(name = BrokerPublicApplication.OA_PUBLIC_APIS) public class OpenairePublicController extends AbstractDnetController { @Autowired @@ -97,7 +97,7 @@ public class OpenairePublicController extends AbstractDnetController { private static final Log log = LogFactory.getLog(OpenairePublicController.class); - @ApiOperation("Returns notifications by subscription using scrolls (first page)") + @Operation(summary = "Returns notifications by subscription using scrolls (first page)") @GetMapping("/scroll/notifications/bySubscriptionId/{subscrId}") public ScrollPage prepareScrollNotificationsBySubscrId(@PathVariable final String subscrId) { @@ -130,7 +130,7 @@ public class OpenairePublicController extends AbstractDnetController { } } - @ApiOperation("Returns notifications using scrolls (other pages)") + @Operation(summary = "Returns notifications using scrolls (other pages)") @GetMapping("/scroll/notifications/{scrollId}") public ScrollPage scrollNotifications(@PathVariable final String scrollId) { @@ -147,7 +147,7 @@ public class OpenairePublicController extends AbstractDnetController { } } - @ApiOperation("Returns notifications as file") + @Operation(summary = "Returns notifications as file") @GetMapping(value = "/file/notifications/bySubscriptionId/{subscrId}", produces = "application/gzip") public void notificationsAsFile(final HttpServletResponse res, @PathVariable final String subscrId) throws Exception { @@ -184,7 +184,7 @@ public class OpenairePublicController extends AbstractDnetController { } - @ApiOperation("Returns events as file by opendoarId") + @Operation(summary = "Returns events as file by opendoarId") @GetMapping(value = "/file/events/opendoar/{id}", produces = "application/gzip") public void opendoarEventsAsFile(final HttpServletResponse res, @PathVariable final String id) { @@ -252,13 +252,13 @@ public class OpenairePublicController extends AbstractDnetController { return first; } - @ApiOperation("Returns the list of subscriptions by user email") + @Operation(summary = "Returns the list of subscriptions by user email") @GetMapping(value = "/subscriptions") private Iterable listSubscriptionsByUser(@RequestParam final String email) { return subscriptionRepo.findBySubscriber(email); } - @ApiOperation("Returns the status of the application") + @Operation(summary = "Returns the status of the application") @GetMapping(value = "/status") private Map status() { final Map res = new LinkedHashMap<>(); @@ -269,7 +269,7 @@ public class OpenairePublicController extends AbstractDnetController { return res; } - @ApiOperation("Store the feedback of an event (MOCK)") + @Operation(summary = "Store the feedback of an event (MOCK)") @RequestMapping(value = "/feedback/events", method = { RequestMethod.POST, RequestMethod.PATCH }) diff --git a/apps/dhp-broker-public-application/src/main/resources/application.properties b/apps/dhp-broker-public-application/src/main/resources/application.properties index 0654f96c..e8cf0ad5 100644 --- a/apps/dhp-broker-public-application/src/main/resources/application.properties +++ b/apps/dhp-broker-public-application/src/main/resources/application.properties @@ -1,5 +1,8 @@ spring.profiles.active = dev,openaire +server.public_url = +server.public_desc = API Base URL + #logging.level.root=DEBUG maven.pom.path = /META-INF/maven/eu.dnetlib.dhp/dhp-broker-public-application/effective-pom.xml diff --git a/apps/dhp-broker-public-application/src/main/resources/static/index.html b/apps/dhp-broker-public-application/src/main/resources/static/index.html index 783bde3a..bfc4e83d 100644 --- a/apps/dhp-broker-public-application/src/main/resources/static/index.html +++ b/apps/dhp-broker-public-application/src/main/resources/static/index.html @@ -2,6 +2,6 @@ OpenAIRE Broker Public API - + diff --git a/apps/dhp-mdstore-manager/pom.xml b/apps/dhp-mdstore-manager/pom.xml index e69b1243..cc28e3a5 100644 --- a/apps/dhp-mdstore-manager/pom.xml +++ b/apps/dhp-mdstore-manager/pom.xml @@ -4,7 +4,7 @@ eu.dnetlib.dhp apps - 3.2.9-SNAPSHOT + 3.3.3-SNAPSHOT ../pom.xml diff --git a/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/MainApplication.java b/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/MainApplication.java index 56a3d48d..9762ad80 100644 --- a/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/MainApplication.java +++ b/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/MainApplication.java @@ -1,53 +1,36 @@ package eu.dnetlib.data.mdstore.manager; -import org.springframework.beans.factory.annotation.Value; +import org.springdoc.core.GroupedOpenApi; 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 eu.dnetlib.common.app.AbstractDnetApp; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; @SpringBootApplication -@EnableSwagger2 @EnableCaching @EnableScheduling @EntityScan("eu.dnetlib.dhp.schema.mdstore") public class MainApplication extends AbstractDnetApp { - @Value("${dhp.swagger.api.host}") - private String swaggetHost; - - @Value("${dhp.swagger.api.basePath}") - private String swaggerPath; - public static void main(final String[] args) { SpringApplication.run(MainApplication.class, args); } + @Bean + public GroupedOpenApi publicApi() { + return GroupedOpenApi.builder() + .group("MDStore APIs") + .pathsToMatch("/mdstores/**") + .build(); + } + @Override - protected void configSwagger(final Docket docket) { - docket - .host(swaggetHost) - .pathMapping(swaggerPath) - .select() - .apis(RequestHandlerSelectors.any()) - .paths(p -> p.contains("/mdstores")) - .build() - .apiInfo(new ApiInfoBuilder() - .title("MDStore Manager APIs") - .description("APIs documentation") - .version("1.1") - .contact(ApiInfo.DEFAULT_CONTACT) - .license("Apache 2.0") - .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0") - .build()); + protected String swaggerTitle() { + return "MDStore Manager APIs"; } } diff --git a/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/controller/MDStoreController.java b/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/controller/MDStoreController.java index bf5ee22f..442f306e 100644 --- a/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/controller/MDStoreController.java +++ b/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/controller/MDStoreController.java @@ -23,15 +23,13 @@ import eu.dnetlib.data.mdstore.manager.utils.DatabaseUtils; import eu.dnetlib.data.mdstore.manager.utils.HdfsClient; import eu.dnetlib.dhp.schema.mdstore.MDStoreVersion; import eu.dnetlib.dhp.schema.mdstore.MDStoreWithInfo; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @RequestMapping("/mdstores") -@Api(tags = { - "Metadata Stores" -}) +@Tag(name = "Metadata Stores") public class MDStoreController extends AbstractDnetController { @Autowired @@ -42,67 +40,67 @@ public class MDStoreController extends AbstractDnetController { private static final Logger log = LoggerFactory.getLogger(DatabaseUtils.class); - @ApiOperation("Return all the mdstores") + @Operation(summary = "Return all the mdstores") @GetMapping("/") public Iterable find() { return databaseUtils.listMdStores(); } - @ApiOperation("Return all the mdstore identifiers") + @Operation(summary = "Return all the mdstore identifiers") @GetMapping("/ids") public List findIdentifiers() { return databaseUtils.listMdStoreIDs(); } - @ApiOperation("Return a mdstores by id") + @Operation(summary = "Return a mdstores by id") @GetMapping("/mdstore/{mdId}") - public MDStoreWithInfo getMdStore(@ApiParam("the mdstore identifier") @PathVariable final String mdId) throws MDStoreManagerException { + public MDStoreWithInfo getMdStore(@Parameter(name = "the mdstore identifier") @PathVariable final String mdId) throws MDStoreManagerException { return databaseUtils.findMdStore(mdId); } - @ApiOperation("Increase the read count of the current mdstore") + @Operation(summary = "Increase the read count of the current mdstore") @GetMapping("/mdstore/{mdId}/startReading") - public MDStoreVersion startReading(@ApiParam("the mdstore identifier") @PathVariable final String mdId) throws MDStoreManagerException { + public MDStoreVersion startReading(@Parameter(name = "the mdstore identifier") @PathVariable final String mdId) throws MDStoreManagerException { return databaseUtils.startReading(mdId); } - @ApiOperation("Create a new mdstore") + @Operation(summary = "Create a new mdstore") @GetMapping("/new/{format}/{layout}/{interpretation}") public MDStoreWithInfo createMDStore( - @ApiParam("mdstore format") @PathVariable final String format, - @ApiParam("mdstore layout") @PathVariable final String layout, - @ApiParam("mdstore interpretation") @PathVariable final String interpretation, - @ApiParam("datasource name") @RequestParam(required = true) final String dsName, - @ApiParam("datasource id") @RequestParam(required = true) final String dsId, - @ApiParam("api id") @RequestParam(required = true) final String apiId) throws MDStoreManagerException { + @Parameter(name = "mdstore format") @PathVariable final String format, + @Parameter(name = "mdstore layout") @PathVariable final String layout, + @Parameter(name = "mdstore interpretation") @PathVariable final String interpretation, + @Parameter(name = "datasource name") @RequestParam(required = true) final String dsName, + @Parameter(name = "datasource id") @RequestParam(required = true) final String dsId, + @Parameter(name = "api id") @RequestParam(required = true) final String apiId) throws MDStoreManagerException { final String id = databaseUtils.createMDStore(format, layout, interpretation, dsName, dsId, apiId); return databaseUtils.findMdStore(id); } - @ApiOperation("Delete a mdstore by id") + @Operation(summary = "Delete a mdstore by id") @DeleteMapping("/mdstore/{mdId}") - public StatusResponse delete(@ApiParam("the id of the mdstore that will be deleted") @PathVariable final String mdId) throws MDStoreManagerException { + public StatusResponse delete(@Parameter(name = "the id of the mdstore that will be deleted") @PathVariable final String mdId) throws MDStoreManagerException { final String hdfsPath = databaseUtils.deleteMdStore(mdId); hdfsClient.deletePath(hdfsPath); return StatusResponse.DELETED; } - @ApiOperation("Return all the versions of a mdstore") + @Operation(summary = "Return all the versions of a mdstore") @GetMapping("/mdstore/{mdId}/versions") public Iterable listVersions(@PathVariable final String mdId) throws MDStoreManagerException { return databaseUtils.listVersions(mdId); } - @ApiOperation("Create a new preliminary version of a mdstore") + @Operation(summary = "Create a new preliminary version of a mdstore") @GetMapping("/mdstore/{mdId}/newVersion") - public MDStoreVersion prepareNewVersion(@ApiParam("the id of the mdstore for which will be created a new version") @PathVariable final String mdId) { + public MDStoreVersion prepareNewVersion(@Parameter(name = "the id of the mdstore for which will be created a new version") @PathVariable final String mdId) { return databaseUtils.prepareMdStoreVersion(mdId); } - @ApiOperation("Promote a preliminary version to current") + @Operation(summary = "Promote a preliminary version to current") @GetMapping("/version/{versionId}/commit/{size}") - public MDStoreVersion commitVersion(@ApiParam("the id of the version that will be promoted to the current version") @PathVariable final String versionId, - @ApiParam("the size of the new current mdstore") @PathVariable final long size) throws MDStoreManagerException { + public MDStoreVersion commitVersion(@Parameter(name = "the id of the version that will be promoted to the current version") @PathVariable final String versionId, + @Parameter(name = "the size of the new current mdstore") @PathVariable final long size) throws MDStoreManagerException { try { return databaseUtils.commitMdStoreVersion(versionId, size); } finally { @@ -110,46 +108,46 @@ public class MDStoreController extends AbstractDnetController { } } - @ApiOperation("Abort a preliminary version") + @Operation(summary = "Abort a preliminary version") @GetMapping("/version/{versionId}/abort") - public StatusResponse commitVersion(@ApiParam("the id of the version to abort") @PathVariable final String versionId) throws MDStoreManagerException { + public StatusResponse commitVersion(@Parameter(name = "the id of the version to abort") @PathVariable final String versionId) throws MDStoreManagerException { final String hdfsPath = databaseUtils.deleteMdStoreVersion(versionId, true); hdfsClient.deletePath(hdfsPath); return StatusResponse.ABORTED; } - @ApiOperation("Return an existing mdstore version") + @Operation(summary = "Return an existing mdstore version") @GetMapping("/version/{versionId}") - public MDStoreVersion getVersion(@ApiParam("the id of the version that has to be deleted") @PathVariable final String versionId) + public MDStoreVersion getVersion(@Parameter(name = "the id of the version that has to be deleted") @PathVariable final String versionId) throws MDStoreManagerException { return databaseUtils.findVersion(versionId); } - @ApiOperation("Delete a mdstore version") + @Operation(summary = "Delete a mdstore version") @DeleteMapping("/version/{versionId}") - public StatusResponse deleteVersion(@ApiParam("the id of the version that has to be deleted") @PathVariable final String versionId, - @ApiParam("if true, the controls on writing and readcount values will be skipped") @RequestParam(required = false, defaultValue = "false") final boolean force) + public StatusResponse deleteVersion(@Parameter(name = "the id of the version that has to be deleted") @PathVariable final String versionId, + @Parameter(name = "if true, the controls on writing and readcount values will be skipped") @RequestParam(required = false, defaultValue = "false") final boolean force) throws MDStoreManagerException { final String hdfsPath = databaseUtils.deleteMdStoreVersion(versionId, force); hdfsClient.deletePath(hdfsPath); return StatusResponse.DELETED; } - @ApiOperation("Decrease the read count of a mdstore version") + @Operation(summary = "Decrease the read count of a mdstore version") @GetMapping("/version/{versionId}/endReading") - public MDStoreVersion endReading(@ApiParam("the id of the version that has been completely read") @PathVariable final String versionId) + public MDStoreVersion endReading(@Parameter(name = "the id of the version that has been completely read") @PathVariable final String versionId) throws MDStoreManagerException { return databaseUtils.endReading(versionId); } - @ApiOperation("Reset the read count of a mdstore version") + @Operation(summary = "Reset the read count of a mdstore version") @GetMapping("/version/{versionId}/resetReading") - public MDStoreVersion resetReading(@ApiParam("the id of the version") @PathVariable final String versionId) + public MDStoreVersion resetReading(@Parameter(name = "the id of the version") @PathVariable final String versionId) throws MDStoreManagerException { return databaseUtils.resetReading(versionId); } - @ApiOperation("Delete expired versions") + @Operation(summary = "Delete expired versions") @DeleteMapping("/versions/expired") public StatusResponse deleteExpiredVersions() { new Thread(this::performDeleteOfExpiredVersions).start(); @@ -169,10 +167,10 @@ public class MDStoreController extends AbstractDnetController { log.info("Done."); } - @ApiOperation("Fix the inconsistencies on HDFS") + @Operation(summary = "Fix the inconsistencies on HDFS") @GetMapping("/hdfs/inconsistencies") public Set fixHdfsInconsistencies( - @ApiParam("force the deletion of hdfs paths") @RequestParam(required = false, defaultValue = "false") final boolean delete) + @Parameter(name = "force the deletion of hdfs paths") @RequestParam(required = false, defaultValue = "false") final boolean delete) throws MDStoreManagerException { final Set hdfsDirs = hdfsClient.listHadoopDirs(); @@ -189,7 +187,7 @@ public class MDStoreController extends AbstractDnetController { return toDelete; } - @ApiOperation("Show informations") + @Operation(summary = "Show informations") @GetMapping("/info") public Map info() { final Map info = new LinkedHashMap<>(); @@ -201,21 +199,21 @@ public class MDStoreController extends AbstractDnetController { return info; } - @ApiOperation("list the file inside the path of a mdstore version") + @Operation(summary = "list the file inside the path of a mdstore version") @GetMapping("/version/{versionId}/parquet/files") public Set listVersionFiles(@PathVariable final String versionId) throws MDStoreManagerException { final String path = databaseUtils.findVersion(versionId).getHdfsPath(); return hdfsClient.listContent(path + "/store", HdfsClient::isParquetFile); } - @ApiOperation("read the parquet file of a mdstore version") + @Operation(summary = "read the parquet file of a mdstore version") @GetMapping("/version/{versionId}/parquet/content/{limit}") public List> listVersionParquet(@PathVariable final String versionId, @PathVariable final long limit) throws MDStoreManagerException { final String path = databaseUtils.findVersion(versionId).getHdfsPath(); return hdfsClient.readParquetFiles(path + "/store", limit); } - @ApiOperation("read the parquet file of a mdstore (current version)") + @Operation(summary = "read the parquet file of a mdstore (current version)") @GetMapping("/mdstore/{mdId}/parquet/content/{limit}") public List> listMdstoreParquet(@PathVariable final String mdId, @PathVariable final long limit) throws MDStoreManagerException { final String versionId = databaseUtils.findMdStore(mdId).getCurrentVersion(); diff --git a/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/controller/SwaggerController.java b/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/controller/SwaggerController.java index 3ec9dff8..31cf2839 100644 --- a/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/controller/SwaggerController.java +++ b/apps/dhp-mdstore-manager/src/main/java/eu/dnetlib/data/mdstore/manager/controller/SwaggerController.java @@ -11,6 +11,6 @@ public class SwaggerController { "/apidoc", "/api-doc", "/doc", "/swagger" }, method = RequestMethod.GET) public String apiDoc() { - return "redirect:swagger-ui/"; + return "redirect:swagger-ui/index.html"; } } diff --git a/apps/dhp-mdstore-manager/src/main/resources/application.properties b/apps/dhp-mdstore-manager/src/main/resources/application.properties index a749c8ca..5c1847a9 100644 --- a/apps/dhp-mdstore-manager/src/main/resources/application.properties +++ b/apps/dhp-mdstore-manager/src/main/resources/application.properties @@ -1,5 +1,8 @@ spring.main.banner-mode = console +server.public_url = +server.public_desc = API Base URL + logging.level.root = INFO maven.pom.path = /META-INF/maven/eu.dnetlib.dhp/dhp-mdstore-manager/effective-pom.xml @@ -42,5 +45,5 @@ dhp.mdstore-manager.hadoop.zeppelin.name-prefix = mdstoreManager dhp.mdstore-manager.inspector.records.max = 1000 -dhp.swagger.api.host = localhost -dhp.swagger.api.basePath = / +# dhp.swagger.api.host = localhost +dhp.swagger.api.basePath = /** diff --git a/apps/dhp-mdstore-manager/src/main/resources/static/index.html b/apps/dhp-mdstore-manager/src/main/resources/static/index.html index 19235f99..3ec1aeda 100644 --- a/apps/dhp-mdstore-manager/src/main/resources/static/index.html +++ b/apps/dhp-mdstore-manager/src/main/resources/static/index.html @@ -20,7 +20,7 @@

Metadata Store Manager


- API documentation + API documentation
create a new mdstore
diff --git a/apps/dnet-exporter-api/pom.xml b/apps/dnet-exporter-api/pom.xml index b0f123f8..f80aa74a 100644 --- a/apps/dnet-exporter-api/pom.xml +++ b/apps/dnet-exporter-api/pom.xml @@ -3,7 +3,7 @@ eu.dnetlib.dhp apps - 3.2.9-SNAPSHOT + 3.3.3-SNAPSHOT ../ diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/DNetOpenaireExporterApplication.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/DNetOpenaireExporterApplication.java index 8af6272c..f806866d 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/DNetOpenaireExporterApplication.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/DNetOpenaireExporterApplication.java @@ -1,19 +1,15 @@ package eu.dnetlib; -import static springfox.documentation.builders.RequestHandlerSelectors.basePackage; - -import java.time.LocalDate; - -import org.springframework.beans.factory.annotation.Autowired; +import org.springdoc.core.GroupedOpenApi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableScheduling; -import eu.dnetlib.DnetOpenaireExporterProperties.Swagger; import eu.dnetlib.common.app.AbstractDnetApp; import eu.dnetlib.openaire.community.CommunityApiController; import eu.dnetlib.openaire.context.ContextApiController; @@ -21,16 +17,9 @@ import eu.dnetlib.openaire.dsm.DsmApiController; import eu.dnetlib.openaire.funders.FundersApiController; import eu.dnetlib.openaire.info.InfoController; import eu.dnetlib.openaire.project.ProjectsController; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.Contact; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; @EnableCaching @EnableScheduling -@EnableSwagger2 @SpringBootApplication @EnableAutoConfiguration(exclude = { SolrAutoConfiguration.class @@ -43,67 +32,56 @@ public class DNetOpenaireExporterApplication extends AbstractDnetApp { SpringApplication.run(DNetOpenaireExporterApplication.class, args); } - @Autowired - private DnetOpenaireExporterProperties config; - - @Bean - public Docket dsm() { - return _docket("Datasource Manager", DsmApiController.class.getPackage().getName(), config.getSwaggerDsm(), V1); - } - - @Bean - public Docket projects() { - return _docket("OpenAIRE Projects", ProjectsController.class.getPackage().getName(), config.getSwaggerProjects(), V1); - } - - @Bean - public Docket funders() { - return _docket("OpenAIRE Funders", FundersApiController.class.getPackage().getName(), config.getSwaggerFunders(), V1); - } - - @Bean - public Docket communities() { - return _docket("OpenAIRE Communities", CommunityApiController.class.getPackage().getName(), config.getSwaggerCommunities(), V1); - } - - @Bean - public Docket contexts() { - return _docket("OpenAIRE Contexts", ContextApiController.class.getPackage().getName(), config.getSwaggerCommunities(), V1); - } - - private Docket _docket(final String groupName, final String controllerPackage, final Swagger swag, final String version) { - final Docket d = new Docket(DocumentationType.SWAGGER_2); - configSwagger(d, groupName, controllerPackage, swag, version); - return d; + @Override + protected String swaggerTitle() { + return "D-Net Exporter APIs"; } @Override - protected void configSwagger(final Docket docket) { - configSwagger(docket, "OpenAIRE Info", InfoController.class.getPackage().getName(), config.getSwaggerInfo(), V1); + protected String swaggerVersion() { + return V1; } - private void configSwagger(final Docket docket, final String groupName, final String controllerPackage, final Swagger swag, final String version) { - docket - .groupName(groupName) - .select() - .apis(basePackage(controllerPackage)) - .build() - .directModelSubstitute(LocalDate.class, java.sql.Date.class) - .apiInfo(apiInfo(swag, version)); + @Bean + @ConditionalOnProperty(value = "openaire.exporter.enable.dsm", havingValue = "true") + public GroupedOpenApi dsm() { + return newGroupedOpenApi("Datasource Manager", DsmApiController.class.getPackage().getName()); } - private ApiInfo apiInfo(final Swagger swag, final String version) { - return new ApiInfoBuilder() - .title(swag.getApiTitle()) - .description(swag.getApiDescription()) - .license(swag.getApiLicense()) - .licenseUrl(swag.getApiLicenseUrl()) - .termsOfServiceUrl("") - .version(version) - .contact(new Contact( - swag.getApiContactName(), - swag.getApiContactUrl(), - swag.getApiContactEmail())) + @Bean + @ConditionalOnProperty(value = "openaire.exporter.enable.project", havingValue = "true") + public GroupedOpenApi projects() { + return newGroupedOpenApi("OpenAIRE Projects", ProjectsController.class.getPackage().getName()); + } + + @Bean + @ConditionalOnProperty(value = "openaire.exporter.enable.funders", havingValue = "true") + public GroupedOpenApi funders() { + return newGroupedOpenApi("OpenAIRE Funders", FundersApiController.class.getPackage().getName()); + } + + @Bean + @ConditionalOnProperty(value = "openaire.exporter.enable.community", havingValue = "true") + public GroupedOpenApi communities() { + return newGroupedOpenApi("OpenAIRE Communities", CommunityApiController.class.getPackage().getName()); + } + + @Bean + @ConditionalOnProperty(value = "openaire.exporter.enable.context", havingValue = "true") + public GroupedOpenApi contexts() { + return newGroupedOpenApi("OpenAIRE Contexts", ContextApiController.class.getPackage().getName()); + } + + @Bean + @ConditionalOnProperty(value = "openaire.exporter.enable.info", havingValue = "true") + public GroupedOpenApi info() { + return newGroupedOpenApi("OpenAIRE Info", InfoController.class.getPackage().getName()); + } + + private GroupedOpenApi newGroupedOpenApi(final String groupName, final String controllerPackage) { + return GroupedOpenApi.builder() + .group(groupName) + .packagesToScan(controllerPackage) .build(); } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/DnetOpenaireExporterProperties.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/DnetOpenaireExporterProperties.java index f90ca4ff..f3923aaa 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/DnetOpenaireExporterProperties.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/DnetOpenaireExporterProperties.java @@ -40,12 +40,6 @@ public class DnetOpenaireExporterProperties { private Datasource datasource; private Project project; private Jdbc jdbc; - private Swagger swaggerDsm; - private Swagger swaggerProjects; - private Swagger swaggerFunders; - private Swagger swaggerCommunities; - private Swagger swaggerContexts; - private Swagger swaggerInfo; private Vocabularies vocabularies; @@ -485,54 +479,6 @@ public class DnetOpenaireExporterProperties { this.jdbc = jdbc; } - public Swagger getSwaggerDsm() { - return swaggerDsm; - } - - public void setSwaggerDsm(final Swagger swaggerDsm) { - this.swaggerDsm = swaggerDsm; - } - - public Swagger getSwaggerProjects() { - return swaggerProjects; - } - - public void setSwaggerProjects(final Swagger swaggerProjects) { - this.swaggerProjects = swaggerProjects; - } - - public Swagger getSwaggerFunders() { - return swaggerFunders; - } - - public void setSwaggerFunders(final Swagger swaggerFunders) { - this.swaggerFunders = swaggerFunders; - } - - public Swagger getSwaggerCommunities() { - return swaggerCommunities; - } - - public void setSwaggerCommunities(final Swagger swaggerCommunities) { - this.swaggerCommunities = swaggerCommunities; - } - - public Swagger getSwaggerContexts() { - return swaggerContexts; - } - - public void setSwaggerContexts(final Swagger swaggerContexts) { - this.swaggerContexts = swaggerContexts; - } - - public Swagger getSwaggerInfo() { - return swaggerInfo; - } - - public void setSwaggerInfo(final Swagger swaggerInfo) { - this.swaggerInfo = swaggerInfo; - } - public Vocabularies getVocabularies() { return vocabularies; } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/SwaggerController.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/SwaggerController.java index b53bbbc4..78485b1d 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/SwaggerController.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/SwaggerController.java @@ -7,10 +7,10 @@ import org.springframework.web.bind.annotation.RequestMapping; public class SwaggerController { @RequestMapping(value = { - "/", "/docs", "swagger-ui.html" + "/", "/docs", "swagger-ui.html", "swagger-ui/" }) public String index() { - return "redirect:swagger-ui/"; + return "redirect:swagger-ui/index.html"; } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/common/AbstractExporterController.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/common/AbstractExporterController.java index c11e15f0..711b7eb2 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/common/AbstractExporterController.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/common/AbstractExporterController.java @@ -3,12 +3,9 @@ package eu.dnetlib.openaire.common; import java.util.List; import java.util.stream.Collectors; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import eu.dnetlib.enabling.datasources.common.DsmException; -import eu.dnetlib.enabling.datasources.common.DsmForbiddenException; -import eu.dnetlib.enabling.datasources.common.DsmNotFoundException; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.commons.lang3.time.StopWatch; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.http.HttpStatus; @@ -17,6 +14,13 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import com.fasterxml.jackson.annotation.JsonAutoDetect; + +import eu.dnetlib.enabling.datasources.common.DsmException; +import eu.dnetlib.enabling.datasources.common.DsmForbiddenException; +import eu.dnetlib.enabling.datasources.common.DsmNotFoundException; +import eu.dnetlib.openaire.dsm.domain.Response; + /** * Created by claudio on 18/07/2017. */ @@ -25,7 +29,9 @@ public abstract class AbstractExporterController { private static final Log log = LogFactory.getLog(AbstractExporterController.class); // NOPMD by marko on 11/24/08 5:02 PM @ResponseBody - @ExceptionHandler({DsmException.class}) + @ExceptionHandler({ + DsmException.class + }) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public ErrorMessage handleDSMException(final Exception e) { return _handleError(e); @@ -39,7 +45,9 @@ public abstract class AbstractExporterController { } @ResponseBody - @ExceptionHandler({DsmNotFoundException.class}) + @ExceptionHandler({ + DsmNotFoundException.class + }) @ResponseStatus(value = HttpStatus.NOT_FOUND) public ErrorMessage handleNotFoundException(final Exception e) { return _handleError(e); @@ -50,23 +58,33 @@ public abstract class AbstractExporterController { @ResponseStatus(HttpStatus.BAD_REQUEST) public List processValidationError(final MethodArgumentNotValidException e) { return e.getBindingResult() - .getFieldErrors().stream() - .map(fe -> new ErrorMessage( - String.format("field '%s'", fe.getField()), - String.format("rejected value '%s'", fe.getRejectedValue()), - fe.getDefaultMessage())) - .collect(Collectors.toList()); + .getFieldErrors() + .stream() + .map(fe -> new ErrorMessage( + String.format("field '%s'", fe.getField()), + String.format("rejected value '%s'", fe.getRejectedValue()), + fe.getDefaultMessage())) + .collect(Collectors.toList()); } private ErrorMessage _handleError(final Exception e) { log.error(e); if (StringUtils.containsIgnoreCase(ExceptionUtils.getRootCauseMessage(e), "Broken pipe")) { - return null; //socket is closed, cannot return any response + return null; // socket is closed, cannot return any response } else { return new ErrorMessage(e); } } + // HELPERS + protected T prepareResponse(final int page, final int size, final StopWatch stopWatch, final T rsp) { + rsp.getHeader() + .setTime(stopWatch.getTime()) + .setPage(page) + .setSize(size); + return rsp; + } + @JsonAutoDetect public class ErrorMessage { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityApiController.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityApiController.java index e653b09a..c8c6af9a 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityApiController.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityApiController.java @@ -1,302 +1,345 @@ package eu.dnetlib.openaire.community; +import static eu.dnetlib.openaire.common.ExporterConstants.C; +import static eu.dnetlib.openaire.common.ExporterConstants.C_CP; +import static eu.dnetlib.openaire.common.ExporterConstants.C_O; +import static eu.dnetlib.openaire.common.ExporterConstants.C_PJ; +import static eu.dnetlib.openaire.common.ExporterConstants.C_ZC; +import static eu.dnetlib.openaire.common.ExporterConstants.R; +import static eu.dnetlib.openaire.common.ExporterConstants.W; + import java.util.List; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; -import static eu.dnetlib.openaire.common.ExporterConstants.*; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController -@CrossOrigin(origins = { "*" }) +@CrossOrigin(origins = { + "*" +}) @ConditionalOnProperty(value = "openaire.exporter.enable.community", havingValue = "true") -@io.swagger.annotations.Api(tags = "OpenAIRE Communities API", description = "the OpenAIRE Community API") +@Tag(name = "OpenAIRE Communities API", description = "the OpenAIRE Community API") public class CommunityApiController { @Autowired private CommunityApiCore communityApiCore; - - @RequestMapping(value = "/community/communities", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "get all community profiles", - notes = "get all community profiles", - tags = { C, R }, - response = CommunitySummary[].class) + @RequestMapping(value = "/community/communities", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get all community profiles", description = "get all community profiles", tags = { + C, R + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CommunitySummary[].class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List listCommunities() throws CommunityException { return communityApiCore.listCommunities(); } - @RequestMapping(value = "/community/{id}", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "get community profile", - notes = "get community profile", - tags = { C, R }, - response = CommunityDetails.class) + @RequestMapping(value = "/community/{id}", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get community profile", description = "get community profile", tags = { + C, R + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CommunityDetails.class), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public CommunityDetails getCommunity(@PathVariable final String id) throws CommunityException, CommunityNotFoundException { return communityApiCore.getCommunity(id); } - @RequestMapping(value = "/community/{id}", produces = { "application/json" }, method = RequestMethod.POST) - @ApiOperation( - value = "update community details", - notes = "update community details", - tags = { C, R }) + @RequestMapping(value = "/community/{id}", produces = { + "application/json" + }, method = RequestMethod.POST) + @Operation(summary = "update community details", description = "update community details", tags = { + C, R + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public void setCommunity( - @PathVariable final String id, - @RequestBody CommunityWritableProperties properties) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final CommunityWritableProperties properties) throws CommunityException, CommunityNotFoundException { communityApiCore.setCommunity(id, properties); } - @RequestMapping(value = "/community/{id}/projects", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "get community projects", - notes = "get community projects", - tags = { C_PJ, R }, - response = CommunityProject[].class) + @RequestMapping(value = "/community/{id}/projects", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get community projects", description = "get community projects", tags = { + C_PJ, R + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CommunityProject[].class), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List getCommunityProjects(@PathVariable final String id) throws CommunityException, CommunityNotFoundException { return communityApiCore.getCommunityProjects(id); } - @RequestMapping(value = "/community/{id}/projects", produces = { "application/json" }, method = RequestMethod.POST) - @ApiOperation( - value = "associate a project to the community", - notes = "associate a project to the community", - tags = { C_PJ, W }) + @RequestMapping(value = "/community/{id}/projects", produces = { + "application/json" + }, method = RequestMethod.POST) + @Operation(summary = "associate a project to the community", description = "associate a project to the community", tags = { + C_PJ, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public CommunityProject addCommunityProject( - @PathVariable final String id, - @RequestBody final CommunityProject project) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final CommunityProject project) throws CommunityException, CommunityNotFoundException { return communityApiCore.addCommunityProject(id, project); } - @RequestMapping(value = "/community/{id}/projects", produces = { "application/json" }, method = RequestMethod.DELETE) - @ApiOperation( - value = "remove a project from the community", - notes = "remove a project from the community", - tags = { C_PJ, W }) + @RequestMapping(value = "/community/{id}/projects", produces = { + "application/json" + }, method = RequestMethod.DELETE) + @Operation(summary = "remove a project from the community", description = "remove a project from the community", tags = { + C_PJ, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public void deleteCommunityProject( - @PathVariable final String id, - @RequestBody final Integer projectId) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final Integer projectId) throws CommunityException, CommunityNotFoundException { communityApiCore.removeCommunityProject(id, projectId); } - @RequestMapping(value = "/community/{id}/contentproviders", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "get the list of content providers associated to a given community", - notes = "get the list of content providers associated to a given community", - tags = { C_CP, R }, - response = CommunityContentprovider[].class) + @RequestMapping(value = "/community/{id}/contentproviders", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get the list of content providers associated to a given community", description = "get the list of content providers associated to a given community", tags = { + C_CP, R + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CommunityContentprovider[].class), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List getCommunityContentproviders(@PathVariable final String id) throws CommunityException, CommunityNotFoundException { return communityApiCore.getCommunityContentproviders(id); } - @RequestMapping(value = "/community/{id}/contentproviders", produces = { "application/json" }, method = RequestMethod.POST) - @ApiOperation( - value = "associate a content provider to the community", - notes = "associate a content provider to the community", - tags = { C_CP, W }) + @RequestMapping(value = "/community/{id}/contentproviders", produces = { + "application/json" + }, method = RequestMethod.POST) + @Operation(summary = "associate a content provider to the community", description = "associate a content provider to the community", tags = { + C_CP, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public CommunityContentprovider addCommunityContentprovider( - @PathVariable final String id, - @RequestBody final CommunityContentprovider contentprovider) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final CommunityContentprovider contentprovider) throws CommunityException, CommunityNotFoundException { return communityApiCore.addCommunityContentprovider(id, contentprovider); } - @RequestMapping(value = "/community/{id}/contentproviders", produces = { "application/json" }, method = RequestMethod.DELETE) - @ApiOperation( - value = "remove the association between a content provider and the community", - notes = "remove the association between a content provider and the community", - tags = { C_CP, W }) + @RequestMapping(value = "/community/{id}/contentproviders", produces = { + "application/json" + }, method = RequestMethod.DELETE) + @Operation(summary = "remove the association between a content provider and the community", description = "remove the association between a content provider and the community", tags = { + C_CP, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public void removeCommunityContentprovider( - @PathVariable final String id, - @RequestBody final Integer contentproviderId) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final Integer contentproviderId) throws CommunityException, CommunityNotFoundException { communityApiCore.removeCommunityContentProvider(id, contentproviderId); } - //ADDING CODE FOR COMMUNITY ORGANIZATIONS + // ADDING CODE FOR COMMUNITY ORGANIZATIONS - @RequestMapping(value = "/community/{id}/organizations", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "get the list of organizations for a given community", - notes = "get the list of organizations for a given community", - tags = { C_O, R }, - response = CommunityOrganization[].class) + @RequestMapping(value = "/community/{id}/organizations", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get the list of organizations for a given community", description = "get the list of organizations for a given community", tags = { + C_O, R + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CommunityContentprovider[].class), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List getCommunityOrganizations(@PathVariable final String id) throws CommunityException, CommunityNotFoundException { return communityApiCore.getCommunityOrganizations(id); } - @RequestMapping(value = "/community/{id}/organizations", produces = { "application/json" }, method = RequestMethod.POST) - @ApiOperation( - value = "associate an organization to the community", - notes = "associate an organization to the community", - tags = { C_O, W }) + @RequestMapping(value = "/community/{id}/organizations", produces = { + "application/json" + }, method = RequestMethod.POST) + @Operation(summary = "associate an organization to the community", description = "associate an organization to the community", tags = { + C_O, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public CommunityOrganization addCommunityOrganization( - @PathVariable final String id, - @RequestBody final CommunityOrganization organization) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final CommunityOrganization organization) throws CommunityException, CommunityNotFoundException { return communityApiCore.addCommunityOrganization(id, organization); } - @RequestMapping(value = "/community/{id}/organizations", produces = { "application/json" }, method = RequestMethod.DELETE) - @ApiOperation( - value = "remove the association between an organization and the community", - notes = "remove the association between an organization and the community", - tags = { C_O, W }) + @RequestMapping(value = "/community/{id}/organizations", produces = { + "application/json" + }, method = RequestMethod.DELETE) + @Operation(summary = "remove the association between an organization and the community", description = "remove the association between an organization and the community", tags = { + C_O, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public void removeCommunityOrganization( - @PathVariable final String id, - @RequestBody final Integer organizationId) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final Integer organizationId) throws CommunityException, CommunityNotFoundException { communityApiCore.removeCommunityOrganization(id, organizationId); } - //********************** + // ********************** - @RequestMapping(value = "/community/{id}/subjects", produces = { "application/json" }, method = RequestMethod.POST) - @ApiOperation( - value = "associate a subject to the community", - notes = "associate a subject to the community", - tags = { C, W }) + @RequestMapping(value = "/community/{id}/subjects", produces = { + "application/json" + }, method = RequestMethod.POST) + @Operation(summary = "associate a subject to the community", description = "associate a subject to the community", tags = { + C, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public CommunityDetails addCommunitySubjects( - @PathVariable final String id, - @RequestBody final List subjects) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final List subjects) throws CommunityException, CommunityNotFoundException { return communityApiCore.addCommunitySubjects(id, subjects); } - @RequestMapping(value = "/community/{id}/subjects", produces = { "application/json" }, method = RequestMethod.DELETE) - @ApiOperation( - value = "remove subjects from a community", - notes = "remove subjects from a community", - tags = { C, W }) + @RequestMapping(value = "/community/{id}/subjects", produces = { + "application/json" + }, method = RequestMethod.DELETE) + @Operation(summary = "remove subjects from a community", description = "remove subjects from a community", tags = { + C, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public CommunityDetails removeCommunitySubjects( - @PathVariable final String id, - @RequestBody final List subjects) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final List subjects) throws CommunityException, CommunityNotFoundException { return communityApiCore.removeCommunitySubjects(id, subjects); } - @RequestMapping(value = "/community/{id}/zenodocommunities", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "get the list of Zenodo communities associated to a given community", - notes = "get the list of Zenodo communities associated to a given community", - tags = { C_ZC, R }, - response = CommunityZenodoCommunity[].class) + @RequestMapping(value = "/community/{id}/zenodocommunities", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get the list of Zenodo communities associated to a given community", description = "get the list of Zenodo communities associated to a given community", tags = { + C_ZC, R + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CommunityZenodoCommunity[].class), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List getCommunityZenodoCommunities(@PathVariable final String id) throws CommunityException, CommunityNotFoundException { return communityApiCore.getCommunityZenodoCommunities(id); } - @RequestMapping(value = "/community/{id}/zenodocommunities", produces = { "application/json" }, method = RequestMethod.POST) - @ApiOperation( - value = "associate a Zenodo community to the community", - notes = "associate a Zenodo community to the community", - tags = { C_ZC, W }) + @RequestMapping(value = "/community/{id}/zenodocommunities", produces = { + "application/json" + }, method = RequestMethod.POST) + @Operation(summary = "associate a Zenodo community to the community", description = "associate a Zenodo community to the community", tags = { + C_ZC, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public CommunityZenodoCommunity addCommunityZenodoCommunity( - @PathVariable final String id, - @RequestBody final CommunityZenodoCommunity zenodocommunity) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final CommunityZenodoCommunity zenodocommunity) throws CommunityException, CommunityNotFoundException { return communityApiCore.addCommunityZenodoCommunity(id, zenodocommunity); } - @RequestMapping(value = "/community/{id}/zenodocommunities", produces = { "application/json" }, method = RequestMethod.DELETE) - @ApiOperation( - value = "remove a Zenodo community from a community", - notes = "remove a Zenodo community from a community", - tags = { C_ZC, W }) + @RequestMapping(value = "/community/{id}/zenodocommunities", produces = { + "application/json" + }, method = RequestMethod.DELETE) + @Operation(summary = "remove a Zenodo community from a community", description = "remove a Zenodo community from a community", tags = { + C_ZC, W + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public void removeCommunityZenodoCommunity( - @PathVariable final String id, - @RequestBody final Integer zenodoCommId) throws CommunityException, CommunityNotFoundException { + @PathVariable final String id, + @RequestBody final Integer zenodoCommId) throws CommunityException, CommunityNotFoundException { communityApiCore.removeCommunityZenodoCommunity(id, zenodoCommId); } - - @RequestMapping(value = "/community/{zenodoId}/openairecommunities", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "get the list of OpenAIRE communities associated to a given Zenodo community", - notes = "get the list of OpenAIRE communities associated to a given Zenodo community", - tags = { C_ZC, R }) + @RequestMapping(value = "/community/{zenodoId}/openairecommunities", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get the list of OpenAIRE communities associated to a given Zenodo community", description = "get the list of OpenAIRE communities associated to a given Zenodo community", tags = { + C_ZC, R + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 404, message = "not found", response = CommunityNotFoundException.class), - @ApiResponse(code = 500, message = "unexpected error", response = CommunityException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "not found"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public CommunityOpenAIRECommunities getOpenAireCommunities( - @PathVariable final String zenodoId) throws CommunityException, CommunityNotFoundException { + @PathVariable final String zenodoId) throws CommunityException, CommunityNotFoundException { return communityApiCore.getOpenAIRECommunities(zenodoId); diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityContentprovider.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityContentprovider.java index 334a3db1..f17df06f 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityContentprovider.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityContentprovider.java @@ -6,31 +6,31 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.google.gson.Gson; import eu.dnetlib.openaire.community.selectioncriteria.SelectionCriteria; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect public class CommunityContentprovider { - @ApiModelProperty(value = "OpenAIRE identifier for this content provider, if available", required = false) + @Schema(description = "OpenAIRE identifier for this content provider, if available", required = false) private String openaireId; @NotNull - @ApiModelProperty(value = "the community identifier this content provider belongs to", required = true) + @Schema(description = "the community identifier this content provider belongs to", required = true) private String communityId; @NotNull - @ApiModelProperty(value = "identifies this content provider within the context it belongs to", required = true) + @Schema(description = "identifies this content provider within the context it belongs to", required = true) private String id; - @ApiModelProperty(value = "content provider name", required = false) + @Schema(description = "content provider name", required = false) private String name; @NotNull - @ApiModelProperty(value = "content provider official name", required = true) + @Schema(description = "content provider official name", required = true) private String officialname; // @NotNull - @ApiModelProperty(value = "content provider selection criteria", required = false) + @Schema(description = "content provider selection criteria", required = false) private SelectionCriteria selectioncriteria; public String getOpenaireId() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityDetails.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityDetails.java index 5d315dd7..2632267c 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityDetails.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityDetails.java @@ -4,31 +4,33 @@ import java.util.Date; import java.util.List; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModelProperty; + +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect public class CommunityDetails extends CommunitySummary { - @ApiModelProperty("date of creation for this community") + @Schema(description = "date of creation for this community") private Date creationDate; - @ApiModelProperty("date of the last update for this communityu") + @Schema(description = "date of the last update for this communityu") private Date lastUpdateDate; - @ApiModelProperty("list of subjects (keywords) that characterise this community") + @Schema(description = "list of subjects (keywords) that characterise this community") private List subjects; - public CommunityDetails() { - } + public CommunityDetails() {} public CommunityDetails(final CommunitySummary summary) { super(summary); } + @Override public Date getCreationDate() { return creationDate; } + @Override public void setCreationDate(final Date creationDate) { this.creationDate = creationDate; } @@ -41,11 +43,13 @@ public class CommunityDetails extends CommunitySummary { this.subjects = subjects; } + @Override public Date getLastUpdateDate() { return lastUpdateDate; } - public void setLastUpdateDate(Date lastUpdateDate) { + @Override + public void setLastUpdateDate(final Date lastUpdateDate) { this.lastUpdateDate = lastUpdateDate; } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityOpenAIRECommunities.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityOpenAIRECommunities.java index 3cf3403f..662f7b19 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityOpenAIRECommunities.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityOpenAIRECommunities.java @@ -1,42 +1,43 @@ package eu.dnetlib.openaire.community; -import io.swagger.annotations.ApiModelProperty; - -import javax.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; +import javax.validation.constraints.NotNull; + +import io.swagger.v3.oas.annotations.media.Schema; + public class CommunityOpenAIRECommunities { - @NotNull - @ApiModelProperty(value = "the zenodo community identifier", required = true) - private String zenodoid; + @NotNull + @Schema(description = "the zenodo community identifier", required = true) + private String zenodoid; - @NotNull - @ApiModelProperty(value = "identifies this zenodo community within the context it belongs to", required = true) - private List openAirecommunitylist; + @NotNull + @Schema(description = "identifies this zenodo community within the context it belongs to", required = true) + private List openAirecommunitylist; - public CommunityOpenAIRECommunities() { - this.zenodoid = ""; - openAirecommunitylist=new ArrayList<>(); - } + public CommunityOpenAIRECommunities() { + this.zenodoid = ""; + openAirecommunitylist = new ArrayList<>(); + } - public List getOpenAirecommunitylist() { - return openAirecommunitylist; - } + public List getOpenAirecommunitylist() { + return openAirecommunitylist; + } - public CommunityOpenAIRECommunities setOpenAirecommunitylist(List openAirecommunitylist) { - this.openAirecommunitylist = openAirecommunitylist; - return this; - } + public CommunityOpenAIRECommunities setOpenAirecommunitylist(final List openAirecommunitylist) { + this.openAirecommunitylist = openAirecommunitylist; + return this; + } - public String getZenodoid() { - return zenodoid; - } + public String getZenodoid() { + return zenodoid; + } - public CommunityOpenAIRECommunities setZenodoid(String zenodoid) { - this.zenodoid = zenodoid; - return this; - } + public CommunityOpenAIRECommunities setZenodoid(final String zenodoid) { + this.zenodoid = zenodoid; + return this; + } -} \ No newline at end of file +} diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityOrganization.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityOrganization.java index 7ced9784..32e4ec2f 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityOrganization.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityOrganization.java @@ -1,75 +1,76 @@ package eu.dnetlib.openaire.community; +import javax.validation.constraints.NotNull; + import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModelProperty; -import javax.validation.constraints.NotNull; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect public class CommunityOrganization { - @NotNull - @ApiModelProperty(value = "the community identifier this organization belongs to", required = true) - private String communityId; - @NotNull - @ApiModelProperty(value = "name of the organization", required = true) - private String name; + @NotNull + @Schema(description = "the community identifier this organization belongs to", required = true) + private String communityId; - @NotNull - @ApiModelProperty(value = "identifies this organization within the context it belongs to", required = true) - private String id; + @NotNull + @Schema(description = "name of the organization", required = true) + private String name; - @NotNull - @ApiModelProperty(value="url of the logo for this organization", required = true) - private String logo_url; + @NotNull + @Schema(description = "identifies this organization within the context it belongs to", required = true) + private String id; + @NotNull + @Schema(description = "url of the logo for this organization", required = true) + private String logo_url; - @NotNull - @ApiModelProperty(value="website url for this organization", required = true) - private String website_url; + @NotNull + @Schema(description = "website url for this organization", required = true) + private String website_url; - public String getCommunityId() { - return communityId; - } + public String getCommunityId() { + return communityId; + } - public CommunityOrganization setCommunityId(String communityId) { - this.communityId = communityId; - return this; - } + public CommunityOrganization setCommunityId(final String communityId) { + this.communityId = communityId; + return this; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public CommunityOrganization setName(String name) { - this.name = name; - return this; - } + public CommunityOrganization setName(final String name) { + this.name = name; + return this; + } - public String getId() { - return id; - } + public String getId() { + return id; + } - public CommunityOrganization setId(String id) { - this.id = id; - return this; - } + public CommunityOrganization setId(final String id) { + this.id = id; + return this; + } - public String getLogo_url() { - return logo_url; - } + public String getLogo_url() { + return logo_url; + } - public CommunityOrganization setLogo_url(String logo_url) { - this.logo_url = logo_url; - return this; - } + public CommunityOrganization setLogo_url(final String logo_url) { + this.logo_url = logo_url; + return this; + } - public String getWebsite_url() { - return website_url; - } + public String getWebsite_url() { + return website_url; + } - public CommunityOrganization setWebsite_url(String website_url) { - this.website_url = website_url; - return this; - } + public CommunityOrganization setWebsite_url(final String website_url) { + this.website_url = website_url; + return this; + } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityProject.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityProject.java index 205e844a..0a3b2800 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityProject.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityProject.java @@ -1,30 +1,31 @@ package eu.dnetlib.openaire.community; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModelProperty; + +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect public class CommunityProject { - @ApiModelProperty(value = "OpenAIRE identifier for this project, if available", required = false) + @Schema(description = "OpenAIRE identifier for this project, if available", required = false) private String openaireId; - @ApiModelProperty(value = "the community identifier this project belongs to", required = true) + @Schema(description = "the community identifier this project belongs to", required = true) private String communityId; - @ApiModelProperty(value = "identifies this project within the context it belongs to", required = true) + @Schema(description = "identifies this project within the context it belongs to", required = true) private String id; - @ApiModelProperty(value = "project name", required = true) + @Schema(description = "project name", required = true) private String name; - @ApiModelProperty(value = "project acronym", required = false) + @Schema(description = "project acronym", required = false) private String acronym; - @ApiModelProperty(value = "project funder", required = true) + @Schema(description = "project funder", required = true) private String funder; - @ApiModelProperty(value = "project grant id", required = true) + @Schema(description = "project grant id", required = true) private String grantId; public String getOpenaireId() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityStatus.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityStatus.java index e3b4902a..2213feb1 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityStatus.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityStatus.java @@ -1,17 +1,18 @@ package eu.dnetlib.openaire.community; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModelProperty; + +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect public enum CommunityStatus { - @ApiModelProperty("restricted visibility") + @Schema(description = "restricted visibility") hidden, - @ApiModelProperty("visible only to RCD managers") + @Schema(description = "visible only to RCD managers") manager, - @ApiModelProperty("visible to RCD managers and to the community users") + @Schema(description = "visible to RCD managers and to the community users") all } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunitySummary.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunitySummary.java index e504583e..ff3ed2c7 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunitySummary.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunitySummary.java @@ -4,42 +4,42 @@ import java.util.Date; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect public class CommunitySummary { - @ApiModelProperty("identifies the community") + @Schema(description = "identifies the community") protected String id; - @ApiModelProperty("values for this field reflect the index field _community_ in the index, e.g. 'egi||EGI Federation'") + @Schema(description = "values for this field reflect the index field _community_ in the index, e.g. 'egi||EGI Federation'") protected String queryId; - @ApiModelProperty("community type") + @Schema(description = "community type") protected String type; - @ApiModelProperty("community name") + @Schema(description = "community name") protected String name; - @ApiModelProperty("community short name") + @Schema(description = "community short name") protected String shortName; - @ApiModelProperty("community creation date") + @Schema(description = "community creation date") protected Date creationDate; - @ApiModelProperty("community last update date") + @Schema(description = "community last update date") protected Date lastUpdateDate; - @ApiModelProperty("community description") + @Schema(description = "community description") protected String description; - @ApiModelProperty("http url for the community logo") + @Schema(description = "http url for the community logo") protected String logoUrl; - @ApiModelProperty("status of the community, drives its visibility") + @Schema(description = "status of the community, drives its visibility") protected CommunityStatus status; - @ApiModelProperty("Zenodo community associated to this community") + @Schema(description = "Zenodo community associated to this community") protected String zenodoCommunity; public CommunitySummary() {} diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityWritableProperties.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityWritableProperties.java index 08ca7a26..ac9723d6 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityWritableProperties.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityWritableProperties.java @@ -3,35 +3,35 @@ package eu.dnetlib.openaire.community; import java.util.List; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModelProperty; + +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect public class CommunityWritableProperties { - @ApiModelProperty("community name") + @Schema(description = "community name") private String name; - @ApiModelProperty("community short name") + @Schema(description = "community short name") private String shortName; - @ApiModelProperty("community description") + @Schema(description = "community description") private String description; - @ApiModelProperty("http url for the community logo") + @Schema(description = "http url for the community logo") private String logoUrl; - @ApiModelProperty("list of subjects (keywords) that characterise this community") + @Schema(description = "list of subjects (keywords) that characterise this community") private List subjects; - @ApiModelProperty("status of the community, drives its visibility") + @Schema(description = "status of the community, drives its visibility") private CommunityStatus status; - @ApiModelProperty("id of the main Zenodo community") + @Schema(description = "id of the main Zenodo community") private String mainZenodoCommunity; - public static CommunityWritableProperties fromDetails(final CommunityDetails details) { - CommunityWritableProperties p = new CommunityWritableProperties(); + final CommunityWritableProperties p = new CommunityWritableProperties(); p.setName(details.getName()); p.setShortName(details.getShortName()); p.setDescription(details.getDescription()); @@ -90,7 +90,11 @@ public class CommunityWritableProperties { this.status = status; } - public String getMainZenodoCommunity() { return mainZenodoCommunity; } + public String getMainZenodoCommunity() { + return mainZenodoCommunity; + } - public void setMainZenodoCommunity(String mainZenodoCommunity) { this.mainZenodoCommunity = mainZenodoCommunity; } + public void setMainZenodoCommunity(final String mainZenodoCommunity) { + this.mainZenodoCommunity = mainZenodoCommunity; + } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityZenodoCommunity.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityZenodoCommunity.java index c84c1692..072faf29 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityZenodoCommunity.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/community/CommunityZenodoCommunity.java @@ -3,45 +3,46 @@ package eu.dnetlib.openaire.community; import javax.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModelProperty; + +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect public class CommunityZenodoCommunity { - @NotNull - @ApiModelProperty(value = "the community identifier this zenodo Community belongs to", required = true) - private String communityId; + @NotNull + @Schema(description = "the community identifier this zenodo Community belongs to", required = true) + private String communityId; - @NotNull - @ApiModelProperty(value = "Zenodo identifier for this community", required = true) - private String zenodoid; + @NotNull + @Schema(description = "Zenodo identifier for this community", required = true) + private String zenodoid; - @NotNull - @ApiModelProperty(value = "identifies this zenodo community within the context it belongs to", required = true) - private String id; + @NotNull + @Schema(description = "identifies this zenodo community within the context it belongs to", required = true) + private String id; - public String getZenodoid() { - return zenodoid; - } + public String getZenodoid() { + return zenodoid; + } - public void setZenodoid(String zenodoid) { - this.zenodoid = zenodoid; - } + public void setZenodoid(final String zenodoid) { + this.zenodoid = zenodoid; + } - public String getId() { - return id; - } + public String getId() { + return id; + } - public void setId(final String id) { - this.id = id; - } + public void setId(final String id) { + this.id = id; + } - public String getCommunityId() { - return communityId; - } + public String getCommunityId() { + return communityId; + } - public void setCommunityId(String communityId) { - this.communityId = communityId; - } + public void setCommunityId(final String communityId) { + this.communityId = communityId; + } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/context/ContextApiController.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/context/ContextApiController.java index 64aae1fe..98fdb46b 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/context/ContextApiController.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/context/ContextApiController.java @@ -3,83 +3,88 @@ package eu.dnetlib.openaire.context; import java.util.List; import java.util.Optional; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController -@CrossOrigin(origins = { "*" }) +@CrossOrigin(origins = { + "*" +}) @ConditionalOnProperty(value = "openaire.exporter.enable.context", havingValue = "true") -@io.swagger.annotations.Api(tags = "OpenAIRE Context API", description = "the OpenAIRE Context API") +@Tag(name = "OpenAIRE Context API", description = "the OpenAIRE Context API") public class ContextApiController { @Autowired private ContextApiCore contextApiCore; - @RequestMapping(value = "/contexts", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "list brief information about all the context profiles", - notes = "list brief information about all the context profiles.", - tags = { }, - response = ContextSummary[].class) + @RequestMapping(value = "/contexts", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "list brief information about all the context profiles", description = "list brief information about all the context profiles") @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = ContextSummary[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ContextException.class) }) - public List listContexts(@RequestParam(required = false, defaultValue = "") List type) throws ContextException { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) + public List listContexts(@RequestParam(required = false, defaultValue = "") final List type) throws ContextException { return contextApiCore.listContexts(type); } - @RequestMapping(value = "/context/{contextId}", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "list the categories defined within a context", - notes = "list the categories defined within a context", - tags = { }, - response = CategorySummary[].class) + @RequestMapping(value = "/context/{contextId}", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "list the categories defined within a context", description = "list the categories defined within a context") @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CategorySummary[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ContextException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List listCategories( - @PathVariable final String contextId, - @RequestParam(required = false, defaultValue = "false") final Boolean all) throws ContextException { + @PathVariable final String contextId, + @RequestParam(required = false, defaultValue = "false") final Boolean all) throws ContextException { - Boolean allFilter = Optional.ofNullable(all).orElse(false); + final Boolean allFilter = Optional.ofNullable(all).orElse(false); return contextApiCore.listCategories(contextId, allFilter); } - @RequestMapping(value = "/context/category/{categoryId}", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "list the concepts defined within a category", - notes = "list the concepts defined within a category", - tags = { }, - response = ConceptSummary[].class) + @RequestMapping(value = "/context/category/{categoryId}", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "list the concepts defined within a category", description = "list the concepts defined within a category") @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = ConceptSummary[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ContextException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List listConcepts( - @PathVariable final String categoryId, - @RequestParam(required = false, defaultValue = "false") final Boolean all) throws ContextException { + @PathVariable final String categoryId, + @RequestParam(required = false, defaultValue = "false") final Boolean all) throws ContextException { - Boolean allFilter = Optional.ofNullable(all).orElse(false); + final Boolean allFilter = Optional.ofNullable(all).orElse(false); return contextApiCore.listConcepts(categoryId, allFilter); } - @RequestMapping(value = "/context/category/concept/{conceptId}", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation( - value = "list the concepts defined within a category", - notes = "list the concepts defined within a category", - tags = { }, - response = ConceptSummary[].class) + @RequestMapping(value = "/context/category/concept/{conceptId}", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "list the concepts defined within a category", description = "list the concepts defined within a category") @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = ConceptSummary[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ContextException.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List listSubConcepts( - @PathVariable final String conceptId, - @RequestParam(required = false, defaultValue = "false") final Boolean all) throws ContextException { + @PathVariable final String conceptId, + @RequestParam(required = false, defaultValue = "false") final Boolean all) throws ContextException { - Boolean allFilter = Optional.ofNullable(all).orElse(false); + final Boolean allFilter = Optional.ofNullable(all).orElse(false); return contextApiCore.listSubConcepts(conceptId, allFilter); } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmApiController.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmApiController.java index 460a9970..180cf716 100755 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmApiController.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmApiController.java @@ -16,10 +16,11 @@ import org.apache.http.HttpStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -34,52 +35,53 @@ import eu.dnetlib.openaire.dsm.domain.ApiDetailsResponse; import eu.dnetlib.openaire.dsm.domain.DatasourceDetailResponse; import eu.dnetlib.openaire.dsm.domain.DatasourceDetails; import eu.dnetlib.openaire.dsm.domain.DatasourceDetailsUpdate; -import eu.dnetlib.openaire.dsm.domain.DatasourceResponse; +import eu.dnetlib.openaire.dsm.domain.DatasourceDetailsWithApis; import eu.dnetlib.openaire.dsm.domain.DatasourceSnippetResponse; +import eu.dnetlib.openaire.dsm.domain.RegisteredDatasourceInfo; import eu.dnetlib.openaire.dsm.domain.RequestFilter; import eu.dnetlib.openaire.dsm.domain.RequestSort; import eu.dnetlib.openaire.dsm.domain.RequestSortOrder; -import eu.dnetlib.openaire.dsm.domain.Response; import eu.dnetlib.openaire.dsm.domain.SimpleResponse; import eu.dnetlib.openaire.vocabularies.Country; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @CrossOrigin(origins = { "*" }) @ConditionalOnProperty(value = "openaire.exporter.enable.dsm", havingValue = "true") -@io.swagger.annotations.Api(tags = "OpenAIRE DSM API", description = "the OpenAIRE Datasource Manager API") +@Tag(name = "OpenAIRE DSM API", description = "the OpenAIRE Datasource Manager API") public class DsmApiController extends AbstractExporterController { @Autowired private DsmCore dsmCore; - @RequestMapping(value = "/ds/countries", produces = { + @GetMapping(value = "/ds/countries", produces = { "application/json" - }, method = RequestMethod.GET) - @ApiOperation(value = "list the datasource countries", notes = "list the datasource countries", tags = { + }) + @Operation(summary = "list the datasource countries", description = "list the datasource countries", tags = { DS, R - }, response = Country[].class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = Country[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public List listCountries() throws DsmException { return dsmCore.listCountries(); } - @RequestMapping(value = "/ds/searchdetails/{page}/{size}", produces = { + @PostMapping(value = "/ds/searchdetails/{page}/{size}", produces = { "application/json" - }, method = RequestMethod.POST) - @ApiOperation(value = "search datasources", notes = "Returns list of Datasource details.", tags = { + }) + @Operation(summary = "search datasources", description = "Returns list of Datasource details.", tags = { DS, R - }, response = DatasourceDetailResponse.class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = DatasourceDetailResponse.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public DatasourceDetailResponse searchDsDetails( @RequestParam final RequestSort requestSortBy, @@ -92,15 +94,15 @@ public class DsmApiController extends AbstractExporterController { return prepareResponse(page, size, stop, rsp); } - @RequestMapping(value = "/ds/aggregationhistory/{dsId}", produces = { + @GetMapping(value = "/ds/aggregationhistory/{dsId}", produces = { "application/json" - }, method = RequestMethod.GET) - @ApiOperation(value = "search datasources", notes = "Returns list of Datasource details.", tags = { + }) + @Operation(summary = "search datasources", description = "Returns list of Datasource details.", tags = { DS, R - }, response = AggregationHistoryResponse.class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = AggregationHistoryResponse.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public AggregationHistoryResponse aggregationHistory(@PathVariable final String dsId) throws DsmException { final StopWatch stop = StopWatch.createStarted(); @@ -108,15 +110,15 @@ public class DsmApiController extends AbstractExporterController { return prepareResponse(0, rsp.getAggregationInfo().size(), stop, rsp); } - @RequestMapping(value = "/ds/searchsnippet/{page}/{size}", produces = { + @PostMapping(value = "/ds/searchsnippet/{page}/{size}", produces = { "application/json" - }, method = RequestMethod.POST) - @ApiOperation(value = "search datasources", notes = "Returns list of Datasource basic info.", tags = { + }) + @Operation(summary = "search datasources", description = "Returns list of Datasource basic info.", tags = { DS, R - }, response = DatasourceSnippetResponse.class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = DatasourceSnippetResponse.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public DatasourceSnippetResponse searchSnippet( @RequestParam final RequestSort requestSortBy, @@ -129,16 +131,16 @@ public class DsmApiController extends AbstractExporterController { return prepareResponse(page, size, stop, rsp); } - @RequestMapping(value = "/ds/searchregistered/{page}/{size}", produces = { + @PostMapping(value = "/ds/searchregistered/{page}/{size}", produces = { "application/json" - }, method = RequestMethod.POST) - @ApiOperation(value = "search among registered datasources", notes = "Returns list of Datasource basic info.", tags = { + }) + @Operation(summary = "search among registered datasources", description = "Returns list of Datasource basic info.", tags = { DS, R - }, response = DatasourceSnippetResponse.class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = DatasourceSnippetResponse.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public DatasourceSnippetResponse searchRegistered( @RequestParam final RequestSort requestSortBy, @@ -151,49 +153,49 @@ public class DsmApiController extends AbstractExporterController { return prepareResponse(page, size, stop, rsp); } - @RequestMapping(value = "/ds/recentregistered/{size}", produces = { + @GetMapping(value = "/ds/recentregistered/{size}", produces = { "application/json" - }, method = RequestMethod.GET) - @ApiOperation(value = "return the latest datasources that were registered through Provide", notes = "Returns list of Datasource basic info.", tags = { + }) + @Operation(summary = "return the latest datasources that were registered through Provide", description = "Returns list of Datasource basic info.", tags = { DS, R - }, response = SimpleResponse.class) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = DatasourceResponse.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) }) - public SimpleResponse recentRegistered(@PathVariable final int size) throws Throwable { + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) + public SimpleResponse recentRegistered(@PathVariable final int size) throws Throwable { final StopWatch stop = StopWatch.createStarted(); - final SimpleResponse rsp = dsmCore.searchRecentRegistered(size); + final SimpleResponse rsp = dsmCore.searchRecentRegistered(size); return prepareResponse(1, size, stop, rsp); } - @RequestMapping(value = "/ds/countregistered", produces = { + @GetMapping(value = "/ds/countregistered", produces = { "application/json" - }, method = RequestMethod.GET) - @ApiOperation(value = "return the number of datasources registered after the given date", notes = "Returns a number.", tags = { + }) + @Operation(summary = "return the number of datasources registered after the given date", description = "Returns a number.", tags = { DS, R - }, response = Long.class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = Long.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public Long countRegistered(@RequestParam final String fromDate, @RequestParam(required = false) final String typologyFilter) throws Throwable { return dsmCore.countRegisteredAfter(fromDate, typologyFilter); } - @RequestMapping(value = "/ds/api/{dsId}", produces = { + @GetMapping(value = "/ds/api/{dsId}", produces = { "application/json" - }, method = RequestMethod.GET) - @ApiOperation(value = "get the list of API for a given datasource", notes = "Returns the list of API for a given datasource.", tags = { + }) + @Operation(summary = "get the list of API for a given datasource", description = "Returns the list of API for a given datasource.", tags = { API, R - }, response = ApiDetailsResponse.class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = ApiDetailsResponse.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public ApiDetailsResponse getApi( @PathVariable final String dsId) throws DsmException { @@ -203,15 +205,15 @@ public class DsmApiController extends AbstractExporterController { return prepareResponse(0, rsp.getApi().size(), stop, rsp); } - @RequestMapping(value = "/api/baseurl/{page}/{size}", produces = { + @PostMapping(value = "/api/baseurl/{page}/{size}", produces = { "application/json" - }, method = RequestMethod.POST) - @ApiOperation(value = "search for the list of base URLs of Datasource APIs managed by a user", notes = "Returns the list of base URLs of Datasource APIs managed by a user", tags = { + }) + @Operation(summary = "search for the list of base URLs of Datasource APIs managed by a user", description = "Returns the list of base URLs of Datasource APIs managed by a user", tags = { DS, API, R - }, response = String[].class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = String[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public List searchBaseUrls( @RequestBody final RequestFilter requestFilter, @@ -221,27 +223,27 @@ public class DsmApiController extends AbstractExporterController { return dsmCore.findBaseURLs(requestFilter, page, size); } - @RequestMapping(value = "/ds/api/{apiId}", method = RequestMethod.DELETE) - @ApiOperation(value = "delete an API", notes = "delete an API, if removable", tags = { + @DeleteMapping(value = "/ds/api/{apiId}") + @Operation(summary = "delete an API", description = "delete an API, if removable", tags = { API, W }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 400, message = "Api not found", response = ErrorMessage.class), - @ApiResponse(code = 403, message = "Api not removable", response = ErrorMessage.class), - @ApiResponse(code = 500, message = "DSM Server error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "400", description = "Api not found"), + @ApiResponse(responseCode = "403", description = "Api not removable"), + @ApiResponse(responseCode = "500", description = "DSM Server error") }) public void deleteApi(@PathVariable final String apiId) throws DsmForbiddenException, DsmNotFoundException { dsmCore.deleteApi(apiId); } - @RequestMapping(value = "/ds/manage", method = RequestMethod.POST) - @ApiOperation(value = "set the managed status for a given datasource", notes = "set the managed status for a given datasource", tags = { + @PostMapping(value = "/ds/manage") + @Operation(summary = "set the managed status for a given datasource", description = "set the managed status for a given datasource", tags = { DS, W }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public void setManaged( @RequestParam final String id, @@ -250,26 +252,26 @@ public class DsmApiController extends AbstractExporterController { dsmCore.setManaged(id, managed); } - @RequestMapping(value = "/ds/managed/{id}", method = RequestMethod.GET) - @ApiOperation(value = "get the datasource managed status", notes = "get the datasource managed status", tags = { + @GetMapping(value = "/ds/managed/{id}") + @Operation(summary = "get the datasource managed status", description = "get the datasource managed status", tags = { DS, R }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public boolean isManaged(@PathVariable final String id) throws DsmException { return dsmCore.isManaged(id); } - @RequestMapping(value = "/ds/add", method = RequestMethod.POST) - @ApiOperation(value = "add a new Datasource", notes = "add a new Datasource", tags = { + @PostMapping(value = "/ds/add") + @Operation(summary = "add a new Datasource", description = "add a new Datasource", tags = { DS, W }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 400, message = "Malformed request", response = ErrorMessage[].class), - @ApiResponse(code = 500, message = "Unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "400", description = "Malformed request"), + @ApiResponse(responseCode = "500", description = "Unexpected error") }) public void saveDs(@Valid @RequestBody final DatasourceDetails datasource) throws DsmException { @@ -279,13 +281,30 @@ public class DsmApiController extends AbstractExporterController { dsmCore.save(datasource); } - @RequestMapping(value = "/ds/update", method = RequestMethod.POST) - @ApiOperation(value = "update Datasource details", notes = "update Datasource details", tags = { + @PostMapping(value = "/ds/addWithApis") + @Operation(summary = "add a new Datasource and its apis", description = "add a new Datasource and its apis", tags = { DS, W }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "400", description = "Malformed request"), + @ApiResponse(responseCode = "500", description = "Unexpected error") + }) + public void saveDsWithApis(@Valid @RequestBody final DatasourceDetailsWithApis d) throws DsmException { + if (d.getDatasource() == null) { throw new DsmException(HttpStatus.SC_BAD_REQUEST, "Datasource field is null"); } + if (dsmCore.exist(d.getDatasource())) { // TODO further check that the DS doesn't have any API + throw new DsmException(HttpStatus.SC_CONFLICT, String.format("cannot register, datasource already defined '%s'", d.getDatasource().getId())); + } + dsmCore.save(d); + } + + @PostMapping(value = "/ds/update") + @Operation(summary = "update Datasource details", description = "update Datasource details", tags = { + DS, W + }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public void updateDatasource( @RequestBody final DatasourceDetailsUpdate ds) throws DsmException, DsmNotFoundException { @@ -293,13 +312,13 @@ public class DsmApiController extends AbstractExporterController { dsmCore.updateDatasource(ds); } - @RequestMapping(value = "/ds/api/baseurl", method = RequestMethod.POST) - @ApiOperation(value = "update the base URL of a datasource interface", notes = "update the base URL of a datasource interface", tags = { + @PostMapping(value = "/ds/api/baseurl") + @Operation(summary = "update the base URL of a datasource interface", description = "update the base URL of a datasource interface", tags = { API, W }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public void updateBaseUrl( @RequestParam final String dsId, @@ -309,13 +328,13 @@ public class DsmApiController extends AbstractExporterController { dsmCore.updateApiBaseurl(dsId, apiId, baseUrl); } - @RequestMapping(value = "/ds/api/compliance", method = RequestMethod.POST) - @ApiOperation(value = "update the compatibility of a datasource interface", notes = "update the compatibility of a datasource interface", tags = { + @PostMapping(value = "/ds/api/compliance") + @Operation(summary = "update the compatibility of a datasource interface", description = "update the compatibility of a datasource interface", tags = { API, W }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public void updateCompliance( @RequestParam final String dsId, @@ -326,13 +345,13 @@ public class DsmApiController extends AbstractExporterController { dsmCore.updateApiCompatibility(dsId, apiId, compliance, override); } - @RequestMapping(value = "/ds/api/oaiset", method = RequestMethod.POST) - @ApiOperation(value = "update the OAI set of a datasource interface", notes = "update the OAI set of a datasource interface", tags = { + @PostMapping(value = "/ds/api/oaiset") + @Operation(summary = "update the OAI set of a datasource interface", description = "update the OAI set of a datasource interface", tags = { API, W }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public void updateOaiSetl( @RequestParam final String dsId, @@ -342,13 +361,13 @@ public class DsmApiController extends AbstractExporterController { dsmCore.updateApiOaiSet(dsId, apiId, oaiSet); } - @RequestMapping(value = "/ds/api/add", method = RequestMethod.POST) - @ApiOperation(value = "adds a new Interface to one Datasource", notes = "adds an Interface to one Datasource", tags = { + @PostMapping(value = "/ds/api/add") + @Operation(summary = "adds a new Interface to one Datasource", description = "adds an Interface to one Datasource", tags = { API, W }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public void addApi(@RequestBody final ApiDetails api) throws DsmException { if (StringUtils.isBlank(api.getDatasource())) { throw new DsmException(HttpStatus.SC_BAD_REQUEST, "missing datasource id"); } @@ -360,48 +379,40 @@ public class DsmApiController extends AbstractExporterController { @Autowired private OperationManager operationManager; - @RequestMapping(value = "/dsm/ops", method = RequestMethod.GET) - @ApiOperation(value = "get the number of pending operations", notes = "get the number of pending operations", tags = { + @GetMapping(value = "/dsm/ops") + @Operation(summary = "get the number of pending operations", description = "get the number of pending operations", tags = { R, M }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public int getOps() throws DsmException { return operationManager.getOpSize(); } - @RequestMapping(value = "/dsm/killops", method = RequestMethod.POST) - @ApiOperation(value = "interrupts the pending operations", notes = "return the number of interrupted operations", tags = { + @PostMapping(value = "/dsm/killops") + @Operation(summary = "interrupts the pending operations", description = "return the number of interrupted operations", tags = { W, M }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public int killOps() throws DsmException { return operationManager.dropAll(); } - @RequestMapping(value = "/dsm/dropcache", method = RequestMethod.POST) - @ApiOperation(value = "drop the caches", notes = "drop the internal caches", tags = { + @PostMapping(value = "/dsm/dropcache") + @Operation(summary = "drop the caches", description = "drop the internal caches", tags = { W, M }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public void dropCache() throws DsmException { dsmCore.dropCaches(); } - // HELPERS - private T prepareResponse(final int page, final int size, final StopWatch stopWatch, final T rsp) { - rsp.getHeader() - .setTime(stopWatch.getTime()) - .setPage(page) - .setSize(size); - return rsp; - } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmApiControllerV2.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmApiControllerV2.java new file mode 100644 index 00000000..356494e5 --- /dev/null +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmApiControllerV2.java @@ -0,0 +1,86 @@ +package eu.dnetlib.openaire.dsm; + +import static eu.dnetlib.openaire.common.ExporterConstants.DS; +import static eu.dnetlib.openaire.common.ExporterConstants.R; + +import java.util.List; + +import org.apache.commons.lang3.time.StopWatch; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import eu.dnetlib.openaire.common.AbstractExporterController; +import eu.dnetlib.openaire.dsm.dao.ResponseUtils; +import eu.dnetlib.openaire.dsm.domain.SimpleDatasourceInfo; +import eu.dnetlib.openaire.dsm.domain.SimpleResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@CrossOrigin(origins = { + "*" +}) +@ConditionalOnProperty(value = "openaire.exporter.enable.dsm", havingValue = "true") +@Tag(name = "OpenAIRE DSM API (version 2.0)", description = "the OpenAIRE Datasource Manager API 2.0") +@RequestMapping("/dsm/2.0") +public class DsmApiControllerV2 extends AbstractExporterController { + + @Autowired + private DsmCore dsmCore; + + @GetMapping("/recentregistered/{size}") + @Operation(summary = "return the latest datasources that were registered through Provide (v2)", description = "Returns list of Datasource basic info.", tags = { + DS, + R + }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) + public SimpleResponse recentRegisteredV2(@PathVariable final int size) throws Throwable { + final StopWatch stop = StopWatch.createStarted(); + final SimpleResponse rsp = dsmCore.searchRecentRegisteredV2(size); + return prepareResponse(1, size, stop, rsp); + } + + @GetMapping("/countfirstcollect") + @Operation(summary = "return the number of datasources registered after the given date", description = "Returns a number.", tags = { + DS, + R + }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) + public Long countFirstCollectAfter(@RequestParam final String fromDate, + @RequestParam(required = false) final String typologyFilter) throws Throwable { + return dsmCore.countFirstCollect(fromDate, typologyFilter); + } + + @GetMapping("/firstCollected") + @Operation(summary = "return the datasources that were collected for the first time after the specified date", description = "Returns list of Datasource basic info.", tags = { + DS, + R + }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) + public SimpleResponse firstCollectedAfter(@RequestParam final String fromDate, + @RequestParam(required = false) final String typologyFilter) throws Throwable { + final StopWatch stop = StopWatch.createStarted(); + final List list = dsmCore.getFirstCollectedAfter(fromDate, typologyFilter); + final SimpleResponse rsp = ResponseUtils.simpleResponse(list); + + return prepareResponse(1, list.size(), stop, rsp); + } + +} diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmCore.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmCore.java index 0d7e9107..42911d5b 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmCore.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/DsmCore.java @@ -14,6 +14,8 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.transaction.Transactional; + import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -24,6 +26,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.domain.Page; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; import eu.dnetlib.enabling.datasources.common.AggregationInfo; @@ -43,11 +46,13 @@ import eu.dnetlib.openaire.dsm.domain.ApiDetailsResponse; import eu.dnetlib.openaire.dsm.domain.DatasourceDetailResponse; import eu.dnetlib.openaire.dsm.domain.DatasourceDetails; import eu.dnetlib.openaire.dsm.domain.DatasourceDetailsUpdate; +import eu.dnetlib.openaire.dsm.domain.DatasourceDetailsWithApis; import eu.dnetlib.openaire.dsm.domain.DatasourceSnippetResponse; import eu.dnetlib.openaire.dsm.domain.RegisteredDatasourceInfo; import eu.dnetlib.openaire.dsm.domain.RequestFilter; import eu.dnetlib.openaire.dsm.domain.RequestSort; import eu.dnetlib.openaire.dsm.domain.RequestSortOrder; +import eu.dnetlib.openaire.dsm.domain.SimpleDatasourceInfo; import eu.dnetlib.openaire.dsm.domain.SimpleResponse; import eu.dnetlib.openaire.dsm.domain.db.ApiDbEntry; import eu.dnetlib.openaire.dsm.domain.db.DatasourceDbEntry; @@ -144,11 +149,12 @@ public class DsmCore { public ApiDetailsResponse getApis(final String dsId) throws DsmException { try { - final String eoscType = dsDao.getDs(dsId).getEoscDatasourceType(); + final DatasourceDbEntry ds = dsDao.getDs(dsId); final List apis = dsDao.getApis(dsId); final List api = apis.stream() .map(DsmMappingUtils::asDetails) - .map(a -> a.setEoscDatasourceType(eoscType)) + .map(a -> a.setEoscDatasourceType(ds.getEoscDatasourceType())) + .map(a -> a.setTypology(ds.getTypology())) .collect(Collectors.toList()); return ResponseUtils.apiResponse(api, api.size()); } catch (final Throwable e) { @@ -173,12 +179,32 @@ public class DsmCore { public void save(final DatasourceDetails d) throws DsmException { try { dsDao.saveDs(asDbEntry(d)); + log.info("DS saved, " + d.getId()); } catch (final Throwable e) { log.error(ExceptionUtils.getStackTrace(e)); throw e; } } + @Transactional + public void save(final DatasourceDetailsWithApis d) throws DsmException { + try { + dsDao.saveDs(asDbEntry(d.getDatasource())); + final List apis = d.getApis(); + if (apis != null) { + for (final ApiDetails api : apis) { + api.setDatasource(d.getDatasource().getId()); + addApi(api); + } + } + } catch ( + + final Throwable e) { + log.error(ExceptionUtils.getStackTrace(e)); + throw e; + } + } + public void updateDatasource(final DatasourceDetailsUpdate d) throws DsmException, DsmNotFoundException { try { // initialize with current values from DB @@ -234,6 +260,7 @@ public class DsmCore { log.info(String.format("missing api id, created '%s'", api.getId())); } dsDao.addApi(asDbEntry(api)); + log.info("API saved, id: " + api.getId()); } public void deleteApi(final String apiId) throws DsmForbiddenException, DsmNotFoundException { @@ -250,7 +277,7 @@ public class DsmCore { // HELPERS ////////////// - public SimpleResponse searchRecentRegistered(final int size) throws Throwable { + public SimpleResponse searchRecentRegistered(final int size) throws Throwable { try { final String sql = IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/openaire/sql/recent_registered_datasources.sql.st"), Charset.defaultCharset()); @@ -293,4 +320,123 @@ public class DsmCore { return rsp; } + + public SimpleResponse searchRecentRegisteredV2(final int size) throws Throwable { + try { + final String sql = + IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/openaire/sql/recent_registered_datasources_v2.sql.st"), Charset.defaultCharset()); + + final List list = + jdbcTemplate.query(sql, rowMapperForSimpleDatasourceInfo(), size); + + return ResponseUtils.simpleResponse(list); + } catch (final Throwable e) { + log.error("error searching recent datasources", e); + throw e; + } + } + + public Long countFirstCollect(final String fromDate, final String typeFilter) throws Throwable { + try { + if (StringUtils.isNotBlank(typeFilter)) { + final String sql = + IOUtils + .toString(getClass().getResourceAsStream("/eu/dnetlib/openaire/sql/count_first_collected_datasources_fromDate_typology.st.sql"), Charset + .defaultCharset()); + + return jdbcTemplate.queryForObject(sql, Long.class, typeFilter + "%", fromDate); + } else { + final String sql = + IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/openaire/sql/count_first_collected_datasources_fromDate.st.sql"), Charset + .defaultCharset()); + + return jdbcTemplate.queryForObject(sql, Long.class, fromDate); + } + + } catch (final Throwable e) { + log.error("error searching datasources using the first collection date", e); + throw e; + } + } + + public List getFirstCollectedAfter(final String fromDate, final String typeFilter) throws Throwable { + try { + if (StringUtils.isNotBlank(typeFilter)) { + final String sql = + IOUtils + .toString(getClass().getResourceAsStream("/eu/dnetlib/openaire/sql/first_collected_datasources_fromDate_typology.st.sql"), Charset + .defaultCharset()); + + return jdbcTemplate.query(sql, rowMapperForSimpleDatasourceInfo(), typeFilter + "%", fromDate); + + } else { + final String sql = + IOUtils + .toString(getClass().getResourceAsStream("/eu/dnetlib/openaire/sql/first_collected_datasources_fromDate.st.sql"), Charset + .defaultCharset()); + + return jdbcTemplate.query(sql, rowMapperForSimpleDatasourceInfo(), fromDate); + + } + } catch (final Throwable e) { + log.error("error searching datasources using the first collection date", e); + throw e; + } + } + + private RowMapper rowMapperForSimpleDatasourceInfo() { + + return (rs, rowNum) -> { + final SimpleDatasourceInfo info = new SimpleDatasourceInfo(); + + info.setId(rs.getString("id")); + info.setOfficialName(rs.getString("officialName")); + info.setEnglishName(rs.getString("englishName")); + info.setTypology(rs.getString("typology")); + info.setEoscType(rs.getString("eoscType")); + info.setEoscDatasourceType(rs.getString("eoscDatasourceType")); + info.setRegisteredBy(rs.getString("registeredBy")); + info.setRegistrationDate(rs.getString("registrationDate")); + info.setFirstCollectionDate(rs.getString("firstCollectionDate")); + info.setLastCollectionDate(rs.getString("lastCollectionDate")); + info.setLastCollectionTotal(rs.getLong("lastCollectionTotal")); + + final Set compatibilities = new HashSet<>(); + for (final String s : (String[]) rs.getArray("compatibilities").getArray()) { + compatibilities.add(s); + } + + // The order of the condition is important + if (compatibilities.contains("openaire-cris_1.1")) { + info.setCompatibility("openaire-cris_1.1"); + } else if (compatibilities.contains("openaire4.0")) { + info.setCompatibility("openaire4.0"); + } else if (compatibilities.contains("driver") && compatibilities.contains("openaire2.0")) { + info.setCompatibility("driver-openaire2.0"); + } else if (compatibilities.contains("driver")) { + info.setCompatibility("driver"); + } else if (compatibilities.contains("openaire2.0")) { + info.setCompatibility("openaire2.0"); + } else if (compatibilities.contains("openaire3.0")) { + info.setCompatibility("openaire3.0"); + } else if (compatibilities.contains("openaire2.0_data")) { + info.setCompatibility("openaire2.0_data"); + } else if (compatibilities.contains("native")) { + info.setCompatibility("native"); + } else if (compatibilities.contains("hostedBy")) { + info.setCompatibility("hostedBy"); + } else if (compatibilities.contains("notCompatible")) { + info.setCompatibility("notCompatible"); + } else { + info.setCompatibility("UNKNOWN"); + } + + for (final String s : (String[]) rs.getArray("organizations").getArray()) { + info.getOrganizations().put(StringUtils.substringBefore(s, "@@@").trim(), StringUtils.substringAfter(s, "@@@").trim()); + } + + return info; + }; + } + } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/DatasourceSpecs.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/DatasourceSpecs.java index 218c527d..ba110c16 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/DatasourceSpecs.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/DatasourceSpecs.java @@ -1,5 +1,21 @@ package eu.dnetlib.openaire.dsm.dao; +import java.util.Arrays; +import java.util.List; +import java.util.Map.Entry; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.data.jpa.domain.Specification; + import eu.dnetlib.enabling.datasources.common.DsmRuntimeException; import eu.dnetlib.openaire.dsm.domain.FilterName; import eu.dnetlib.openaire.dsm.domain.RequestFilter; @@ -7,15 +23,6 @@ import eu.dnetlib.openaire.dsm.domain.RequestSort; import eu.dnetlib.openaire.dsm.domain.RequestSortOrder; import eu.dnetlib.openaire.dsm.domain.db.DatasourceApiDbEntry; import eu.dnetlib.openaire.dsm.domain.db.DatasourceDbEntry; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.data.jpa.domain.Specification; - -import javax.persistence.criteria.*; -import java.util.List; -import java.util.Map.Entry; public class DatasourceSpecs { @@ -24,39 +31,43 @@ public class DatasourceSpecs { public static final String WILDCARD = "%"; public static Specification dsRegisteredbyNotNullSpec() { - return (ds, query, cb) -> cb.and( - cb.isNull(ds.get(FilterName.registeredby.name())).not(), - cb.isNull(ds.get("registrationdate")).not()); + return (ds, query, cb) -> cb.and(cb.isNull(ds.get(FilterName.registeredby.name())).not(), cb.isNull(ds.get("registrationdate")).not()); } public static Specification dsSpec(final RequestSort requestSortBy, final RequestSortOrder order, final RequestFilter requestFilter) { log.debug(String.format("RequestFilter:'%s', RequestSort:'%s', RequestSortOrder:'%s'", requestFilter, requestSortBy, order)); return (ds, query, cb) -> { final Predicate p = cb.conjunction(); + final List> expressions = p.getExpressions(); + + expressions.add(cb.equal(ds.get("eoscType"), "Data Source")); + expressions.add(cb.equal(ds.get("dedupMainService"), true)); + if (requestFilter != null) { - final List> expressions = p.getExpressions(); - requestFilter.entrySet().stream() - .forEach(e -> { - switch (FilterName.type(e.getKey())) { + requestFilter.entrySet() + .stream() + .forEach(e -> { + switch (FilterName.type(e.getKey())) { - case exact: - expressions.add(exactSearch(ds, cb, e)); + case exact: + expressions.add(exactSearch(ds, cb, e)); - break; - case search: - expressions.add(likeSearch(ds, cb, e)); + break; + case search: + expressions.add(likeSearch(ds, cb, e)); - break; - case searchOrgs: - // search by case insensitive organization's country - expressions.add( - cb.equal( - cb.lower( - ds.join("organizations").get(FilterName.country.name())), - getValue(e))); - break; - } - }); + break; + + case multiSearch: + expressions.add(likeSearchList(ds, cb, e)); + + break; + case searchOrgs: + // search by case insensitive organization's country + expressions.add(cb.equal(cb.lower(ds.join("organizations").get(FilterName.country.name())), getValue(e))); + break; + } + }); } if (requestSortBy != null) { if (order != null) { @@ -83,21 +94,27 @@ public class DatasourceSpecs { final Predicate p = cb.conjunction(); if (requestFilter != null) { final List> expressions = p.getExpressions(); - requestFilter.entrySet().stream() - .forEach(e -> { - switch (FilterName.type(e.getKey())) { + requestFilter.entrySet() + .stream() + .forEach(e -> { + switch (FilterName.type(e.getKey())) { - case exact: - expressions.add(exactSearch(api, cb, e)); - break; - case search: + case exact: + expressions.add(exactSearch(api, cb, e)); + break; + case search: - expressions.add(likeSearch(api, cb, e)); - break; - case searchOrgs: - throw new DsmRuntimeException("not implemented"); - } - }); + expressions.add(likeSearch(api, cb, e)); + break; + + case multiSearch: + expressions.add(likeSearchList(api, cb, e)); + + break; + case searchOrgs: + throw new DsmRuntimeException("not implemented"); + } + }); } query.distinct(true); return p; @@ -108,32 +125,40 @@ public class DatasourceSpecs { // substring, case insensitive, like based search private static Predicate likeSearch(final Root r, final CriteriaBuilder cb, final Entry e) { - return cb.like( - cb.lower( - r.get(e.getKey().name())), - WILDCARD + getValue(e) + WILDCARD); + return cb.like(cb.lower(r.get(e.getKey().name())), WILDCARD + getValue(e) + WILDCARD); } - // search by ID, managed. exact match + // substring, case insensitive, like based search + private static Predicate likeSearchList(final Root r, final CriteriaBuilder cb, final Entry e) { + final String key = e.getKey().name(); + + final Predicate[] arr = + Arrays.stream(e.getValue().toString().split(",")) + .map(String::trim) + .map(String::toLowerCase) + .filter(StringUtils::isNotBlank) + .map(s -> cb.like(cb.lower(r.get(key)), WILDCARD + s + WILDCARD)) + .toArray(size -> new Predicate[size]); + + return cb.or(arr); + } + + // search by ID, managed. exact match private static Predicate exactSearch(final Root r, final CriteriaBuilder cb, final Entry e) { return cb.equal(r.get(e.getKey().name()), getValue(e)); } private static Object getValue(final Entry e) { if (e.getValue() instanceof String) { - final String s = ((String) e.getValue()); + final String s = (String) e.getValue(); if (!e.getKey().equals(FilterName.country)) { - Boolean b = BooleanUtils.toBooleanObject(s); - if (b != null) { - return b; - } + final Boolean b = BooleanUtils.toBooleanObject(s); + if (b != null) { return b; } } return e.getKey().equals(FilterName.id) ? s : StringUtils.lowerCase(s); } - if (e.getValue() instanceof Boolean) { - return e.getValue(); - } + if (e.getValue() instanceof Boolean) { return e.getValue(); } return e.getValue(); } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/MongoLoggerClientImpl.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/MongoLoggerClientImpl.java index 9818d318..279c3789 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/MongoLoggerClientImpl.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/MongoLoggerClientImpl.java @@ -15,6 +15,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.logging.Log; @@ -148,21 +149,25 @@ public class MongoLoggerClientImpl implements MongoLoggerClient { AggregationInfo info = null; final AggregationStage stage = AggregationStage.parse(d.getString("system:wfName")); + final boolean success = isCompletedSuccesfully(d); + switch (stage) { case COLLECT: final CollectionInfo cInfo = new CollectionInfo(); cInfo.setAggregationStage(stage); cInfo.setCollectionMode(getCollectionMode(d)); - cInfo.setNumberOfRecords(getNumberOfRecords(d)); + cInfo.setNumberOfRecords(success ? getNumberOfRecords(d) : 0); cInfo.setDate(getDate(d)); + cInfo.setCompletedSuccessfully(success); info = cInfo; break; case TRANSFORM: final TransformationInfo tInfo = new TransformationInfo(); tInfo.setAggregationStage(stage); - tInfo.setNumberOfRecords(getNumberOfRecords(d)); + tInfo.setNumberOfRecords(success ? getNumberOfRecords(d) : 0); tInfo.setDate(getDate(d)); + tInfo.setCompletedSuccessfully(success); info = tInfo; break; } @@ -198,8 +203,13 @@ public class MongoLoggerClientImpl implements MongoLoggerClient { return DateFormatUtils.format(new DateUtils().parse(dateString), DsmMappingUtils.DATE_FORMAT); } + private boolean isCompletedSuccesfully(final Document d) { + final String boolString = d.getString("system:isCompletedSuccessfully"); + return BooleanUtils.toBoolean(boolString); + } + private static Bson getFields() { - return fields(eq("system:wfName", 1), eq("system:node:SELECT_MODE:selection", 1), eq("collectionMode", 1), eq("mainlog:sinkSize", 1), eq("mainlog:writeOps", 1), eq("mainlog:total", 1), eq("system:startHumanDate", 1), eq("system:profileName", 1)); + return fields(eq("system:wfName", 1), eq("system:node:SELECT_MODE:selection", 1), eq("collectionMode", 1), eq("mainlog:sinkSize", 1), eq("mainlog:writeOps", 1), eq("mainlog:total", 1), eq("system:startHumanDate", 1), eq("system:profileName", 1), eq("system:isCompletedSuccessfully", 1)); } private static BasicDBObject dbo(final String key, final Object value) { @@ -207,7 +217,7 @@ public class MongoLoggerClientImpl implements MongoLoggerClient { } private Bson queryForAggregationHistory(final String dsId, final String pattern) { - return and(eq("parentDatasourceId", dsId), eq("system:profileFamily", "aggregator"), eq("system:isCompletedSuccessfully", "true"), regex("system:wfName", pattern, "i")); + return and(eq("parentDatasourceId", dsId), eq("system:profileFamily", "aggregator"), regex("system:wfName", pattern, "i")); } private synchronized MongoCollection getCollection() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/ResponseUtils.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/ResponseUtils.java index a2d422b8..cdc4c581 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/ResponseUtils.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/ResponseUtils.java @@ -52,8 +52,8 @@ public class ResponseUtils { return header(Lists.newLinkedList(), total); } - public static SimpleResponse simpleResponse(final List list) { - final SimpleResponse rsp = new SimpleResponse().setResponse(list);; + public static SimpleResponse simpleResponse(final List list) { + final SimpleResponse rsp = new SimpleResponse().setResponse(list);; rsp.setHeader(header(Lists.newLinkedList(), list.size())); return rsp; } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/utils/DsmMappingUtils.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/utils/DsmMappingUtils.java index 38e031eb..7e6d80b2 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/utils/DsmMappingUtils.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/dao/utils/DsmMappingUtils.java @@ -76,7 +76,17 @@ public class DsmMappingUtils { } public static ApiDbEntry asDbEntry(final ApiDetails d) { - final ApiDbEntry apiDbEntry = _convert(d, ApiDbEntry.class); + final ApiDbEntry apiDbEntry = new ApiDbEntry(); + + apiDbEntry.setId(d.getId()); + apiDbEntry.setBaseurl(d.getBaseurl()); + apiDbEntry.setProtocol(d.getProtocol()); + apiDbEntry.setDatasource(d.getDatasource()); + apiDbEntry.setContentdescription(d.getContentdescription()); + apiDbEntry.setCompatibility(d.getCompatibility()); + apiDbEntry.setCompatibilityOverride(d.getCompatibilityOverride()); + apiDbEntry.setRemovable(d.getRemovable()); + apiDbEntry.setMetadataIdentifierPath(d.getMetadataIdentifierPath()); // Need to complete the references among objects, because you know, referential integrity ... apiDbEntry.getApiParams().forEach(ap -> ap.getId().setApi(apiDbEntry)); diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/AggregationHistoryResponse.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/AggregationHistoryResponse.java index eeddbc94..e9a92bf0 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/AggregationHistoryResponse.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/AggregationHistoryResponse.java @@ -1,29 +1,26 @@ package eu.dnetlib.openaire.dsm.domain; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import eu.dnetlib.enabling.datasources.common.AggregationInfo; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - import java.util.List; -@ApiModel +import com.fasterxml.jackson.annotation.JsonAutoDetect; + +import eu.dnetlib.enabling.datasources.common.AggregationInfo; + @JsonAutoDetect public class AggregationHistoryResponse extends Response { - @ApiModelProperty(position = 1) - private List aggregationInfo; + private List aggregationInfo; - public AggregationHistoryResponse(List aggregationInfo) { - super(); - this.aggregationInfo = aggregationInfo; - } + public AggregationHistoryResponse(final List aggregationInfo) { + super(); + this.aggregationInfo = aggregationInfo; + } - public List getAggregationInfo() { - return aggregationInfo; - } + public List getAggregationInfo() { + return aggregationInfo; + } - public void setAggregationInfo(List aggregationInfo) { - this.aggregationInfo = aggregationInfo; - } + public void setAggregationInfo(final List aggregationInfo) { + this.aggregationInfo = aggregationInfo; + } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/ApiDetails.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/ApiDetails.java index d2ab101a..4768d9a0 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/ApiDetails.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/ApiDetails.java @@ -5,64 +5,48 @@ import java.util.Set; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect -@ApiModel(value = "Api model", description = "provides information about the datasource API") +@Schema(name = "Api model", description = "provides information about the datasource API") public class ApiDetails extends ApiIgnoredProperties { - @ApiModelProperty(position = 0) private String id = null; - @ApiModelProperty(position = 1) private String protocol = null; - @ApiModelProperty(position = 2) private String datasource = null; - @ApiModelProperty(position = 3) private String contentdescription = null; - @ApiModelProperty(position = 4) private String eoscDatasourceType = null; - @ApiModelProperty(position = 5) private String compatibility; - @ApiModelProperty(position = 7) private String compatibilityOverride; - @ApiModelProperty(position = 8) private Integer lastCollectionTotal; - @ApiModelProperty(position = 9) private Date lastCollectionDate; - @ApiModelProperty(position = 10) private Integer lastAggregationTotal; - @ApiModelProperty(position = 11) private Date lastAggregationDate; - @ApiModelProperty(position = 12) private Integer lastDownloadTotal; - @ApiModelProperty(position = 13) private Date lastDownloadDate; - @ApiModelProperty(position = 14) private String baseurl; - @ApiModelProperty(position = 15) protected Boolean removable = false; - @ApiModelProperty(position = 16) private Set apiParams; - @ApiModelProperty(position = 17) private String metadataIdentifierPath = ""; + private String typology = null; + public String getId() { return id; } @@ -214,4 +198,13 @@ public class ApiDetails extends ApiIgnoredProperties { this.eoscDatasourceType = eoscDatasourceType; return this; } + + public String getTypology() { + return typology; + } + + public ApiDetails setTypology(final String typology) { + this.typology = typology; + return this; + } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/ApiDetailsResponse.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/ApiDetailsResponse.java index 495dc908..cecb20c1 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/ApiDetailsResponse.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/ApiDetailsResponse.java @@ -3,14 +3,13 @@ package eu.dnetlib.openaire.dsm.domain; import java.util.List; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -@ApiModel +import io.swagger.v3.oas.annotations.media.Schema; + + @JsonAutoDetect public class ApiDetailsResponse extends Response { - @ApiModelProperty(position = 1) private List api; public List getApi() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/CollectionInfo.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/CollectionInfo.java index 60df410d..7c21cc3d 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/CollectionInfo.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/CollectionInfo.java @@ -3,12 +3,11 @@ package eu.dnetlib.openaire.dsm.domain; import com.fasterxml.jackson.annotation.JsonAutoDetect; import eu.dnetlib.enabling.datasources.common.AggregationInfo; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; /** * Created by claudio on 29/11/2016. */ -@ApiModel @JsonAutoDetect public class CollectionInfo extends AggregationInfo { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/CollectionMode.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/CollectionMode.java index 996bd6bf..5d8702d7 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/CollectionMode.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/CollectionMode.java @@ -1,13 +1,12 @@ package eu.dnetlib.openaire.dsm.domain; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; /** * Created by claudio on 12/09/16. */ -@ApiModel @JsonAutoDetect public enum CollectionMode { - REFRESH, INCREMENTAL + REFRESH, + INCREMENTAL } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailResponse.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailResponse.java index 75ca070b..e59cb037 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailResponse.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailResponse.java @@ -1,28 +1,24 @@ package eu.dnetlib.openaire.dsm.domain; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - import java.util.List; -@ApiModel +import com.fasterxml.jackson.annotation.JsonAutoDetect; + @JsonAutoDetect public class DatasourceDetailResponse extends Response { - @ApiModelProperty(position = 1) - private List datasourceInfo; + private List datasourceInfo; - public DatasourceDetailResponse(List datasourceInfo) { - super(); - this.datasourceInfo = datasourceInfo; - } + public DatasourceDetailResponse(final List datasourceInfo) { + super(); + this.datasourceInfo = datasourceInfo; + } - public List getDatasourceInfo() { - return datasourceInfo; - } + public List getDatasourceInfo() { + return datasourceInfo; + } - public void setDatasourceInfo(List datasourceInfo) { - this.datasourceInfo = datasourceInfo; - } + public void setDatasourceInfo(final List datasourceInfo) { + this.datasourceInfo = datasourceInfo; + } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetails.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetails.java index 1434b61b..0d27e3bc 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetails.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetails.java @@ -9,128 +9,92 @@ import javax.validation.constraints.NotBlank; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; /** * Created by claudio on 12/09/16. */ @JsonAutoDetect -@ApiModel(value = "Datasource model", description = "provides information about the datasource") +@Schema(name = "Datasource model", description = "provides information about the datasource") public class DatasourceDetails extends DatasourceIgnoredProperties { @NotBlank - @ApiModelProperty(position = 0) private String id; @Transient - @ApiModelProperty(position = 1) private String openaireId; @NotBlank - @ApiModelProperty(position = 2) private String officialname; @NotBlank - @ApiModelProperty(position = 3) private String englishname; - @ApiModelProperty(position = 4) private String websiteurl; - @ApiModelProperty(position = 5) private String logourl; @Email - @ApiModelProperty(position = 6) private String contactemail; - @ApiModelProperty(position = 7) private Double latitude; - @ApiModelProperty(position = 8) private Double longitude; - @ApiModelProperty(position = 9) private String timezone; @NotBlank - @ApiModelProperty(position = 10) private String namespaceprefix; - @ApiModelProperty(position = 11) private String languages; - @ApiModelProperty(position = 12) private Date dateofvalidation; @NotBlank - @ApiModelProperty(position = 13) private String eoscDatasourceType; - @ApiModelProperty(position = 14) private Date dateofcollection; - @ApiModelProperty(position = 15) private String platform; - @ApiModelProperty(position = 16) private String activationId; - @ApiModelProperty(position = 17) private String description; - @ApiModelProperty(position = 18) private String issn; - @ApiModelProperty(position = 19) private String eissn; - @ApiModelProperty(position = 20) private String lissn; @Email - @ApiModelProperty(position = 21) private String registeredby; - @ApiModelProperty(position = 22) private String subjects; - @ApiModelProperty(position = 23) protected String aggregator = "OPENAIRE"; - @ApiModelProperty(position = 24) protected String collectedfrom; - @ApiModelProperty(position = 25) private Boolean managed; - @ApiModelProperty(position = 28) private Boolean consentTermsOfUse; - @ApiModelProperty(position = 29) private Boolean fullTextDownload; - @ApiModelProperty(position = 30) private Date consentTermsOfUseDate; - @ApiModelProperty(position = 31) private Date lastConsentTermsOfUseDate; - @ApiModelProperty(position = 26) private Set organizations; - @ApiModelProperty(position = 27) private Set identities; - @ApiModelProperty(position = 32) private String status; @Deprecated - @ApiModelProperty(position = 33) private String typology; - @ApiModelProperty(position = 34) private Date registrationdate; public String getId() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailsUpdate.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailsUpdate.java index 15305026..750813bb 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailsUpdate.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailsUpdate.java @@ -8,80 +8,59 @@ import javax.validation.constraints.NotBlank; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; /** * Created by claudio on 12/09/16. */ @JsonAutoDetect -@ApiModel(value = "Datasource updatable fields model", description = "provides information about the datasource field that can be updated") +@Schema(name = "Datasource updatable fields model", description = "provides information about the datasource field that can be updated") public class DatasourceDetailsUpdate { @NotBlank - @ApiModelProperty(position = 0) private String id; @NotBlank - @ApiModelProperty(position = 2) private String officialname; @NotBlank - @ApiModelProperty(position = 3) private String englishname; - @ApiModelProperty(position = 4) private String websiteurl; - @ApiModelProperty(position = 5) private String logourl; @Email - @ApiModelProperty(position = 6) private String contactemail; - @ApiModelProperty(position = 7) private Double latitude; - @ApiModelProperty(position = 8) private Double longitude; - @ApiModelProperty(position = 9) private String timezone; @Deprecated - @ApiModelProperty(position = 12) private String typology; - @ApiModelProperty(position = 13) private String eoscDatasourceType; - @ApiModelProperty(position = 15) private String platform; - @ApiModelProperty(position = 17) private String description; @Email - @ApiModelProperty(position = 21) private String registeredby; - @ApiModelProperty(position = 25) private Boolean managed; - @ApiModelProperty(position = 27) private Set identities; - @ApiModelProperty(position = 28) private Boolean consentTermsOfUse; - @ApiModelProperty(position = 29) private Date consentTermsOfUseDate; - @ApiModelProperty(position = 29) private Date lastConsentTermsOfUseDate; - @ApiModelProperty(position = 31) private Boolean fullTextDownload; public String getId() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailsWithApis.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailsWithApis.java new file mode 100644 index 00000000..8e0c3d09 --- /dev/null +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceDetailsWithApis.java @@ -0,0 +1,37 @@ +package eu.dnetlib.openaire.dsm.domain; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; + +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * Created by claudio on 12/09/16. + */ +@JsonAutoDetect +@Schema(name = "Datasource model with apis", description = "provides information about the datasource and its apis") +public class DatasourceDetailsWithApis { + + private DatasourceDetails datasource; + + private List apis = new ArrayList<>(); + + public DatasourceDetails getDatasource() { + return datasource; + } + + public void setDatasource(final DatasourceDetails datasource) { + this.datasource = datasource; + } + + public List getApis() { + return apis; + } + + public void setApis(final List apis) { + this.apis = apis; + } + +} diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceIgnoredProperties.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceIgnoredProperties.java index 88df10eb..f00a734c 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceIgnoredProperties.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceIgnoredProperties.java @@ -54,6 +54,12 @@ public abstract class DatasourceIgnoredProperties { @JsonIgnore protected String certificates; + @JsonIgnore + protected String eoscType; + + @JsonIgnore + protected Boolean dedupMainService; + public String getOd_contenttypes() { return od_contenttypes; } @@ -182,4 +188,20 @@ public abstract class DatasourceIgnoredProperties { this.certificates = certificates; } + public String getEoscType() { + return eoscType; + } + + public void setEoscType(final String eoscType) { + this.eoscType = eoscType; + } + + public Boolean getDedupMainService() { + return dedupMainService; + } + + public void setDedupMainService(final Boolean dedupMainService) { + this.dedupMainService = dedupMainService; + } + } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceInfo.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceInfo.java index 74c8f7cb..07399122 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceInfo.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceInfo.java @@ -3,39 +3,30 @@ package eu.dnetlib.openaire.dsm.domain; import java.util.List; import com.fasterxml.jackson.annotation.JsonAutoDetect; + import eu.dnetlib.enabling.datasources.common.AggregationInfo; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect -@ApiModel(value = "Datasource info model", description = "provides information about the datasource and its aggregation status") +@Schema(name = "Datasource info model", description = "provides information about the datasource and its aggregation status") public class DatasourceInfo { - @ApiModelProperty(position = 0) private long indexRecords; - @ApiModelProperty(position = 1) private long fundedContent; - @ApiModelProperty(position = 2) private long fulltexts; - @ApiModelProperty(position = 3) private String lastIndexingDate; - @ApiModelProperty(position = 4) private String firstHarvestDate; - @ApiModelProperty(position = 5) private DatasourceDetails datasource; - @ApiModelProperty(position = 6) private AggregationInfo lastCollection; - @ApiModelProperty(position = 7) private AggregationInfo lastTransformation; - @ApiModelProperty(position = 8) private List aggregationHistory; public DatasourceInfo() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceResponse.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceResponse.java index daae0a07..9aba8b8a 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceResponse.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceResponse.java @@ -4,9 +4,7 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.google.common.collect.Lists; -import io.swagger.annotations.ApiModel; -@ApiModel @JsonAutoDetect public class DatasourceResponse extends Response { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSearchResponse.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSearchResponse.java index ecf9e77f..2be76532 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSearchResponse.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSearchResponse.java @@ -1,28 +1,24 @@ package eu.dnetlib.openaire.dsm.domain; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - import java.util.List; -@ApiModel +import com.fasterxml.jackson.annotation.JsonAutoDetect; + @JsonAutoDetect public class DatasourceSearchResponse extends Response { - @ApiModelProperty(position = 1) - private List datasourceInfo; + private List datasourceInfo; - public DatasourceSearchResponse(List datasourceInfo) { - super(); - this.datasourceInfo = datasourceInfo; - } + public DatasourceSearchResponse(final List datasourceInfo) { + super(); + this.datasourceInfo = datasourceInfo; + } - public List getDatasourceInfo() { - return datasourceInfo; - } + public List getDatasourceInfo() { + return datasourceInfo; + } - public void setDatasourceInfo(List datasourceInfo) { - this.datasourceInfo = datasourceInfo; - } + public void setDatasourceInfo(final List datasourceInfo) { + this.datasourceInfo = datasourceInfo; + } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippet.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippet.java index 34fda827..9ce47b8d 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippet.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippet.java @@ -4,23 +4,19 @@ import javax.validation.constraints.NotBlank; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect -@ApiModel(value = "Datasource model", description = "provides information about the datasource") +@Schema(name = "Datasource model", description = "provides information about the datasource") public class DatasourceSnippet { @NotBlank - @ApiModelProperty(position = 0) private String id; @NotBlank - @ApiModelProperty(position = 2) private String officialname; @NotBlank - @ApiModelProperty(position = 3) private String englishname; public String getId() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippetExtended.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippetExtended.java index 69dcab91..819fe307 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippetExtended.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippetExtended.java @@ -8,61 +8,45 @@ import javax.validation.constraints.NotBlank; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect -@ApiModel(value = "Datasource model", description = "provides extended information about the datasource") +@Schema(name = "Datasource model", description = "provides extended information about the datasource") public class DatasourceSnippetExtended { @NotBlank - @ApiModelProperty(position = 0) private String id; @NotBlank - @ApiModelProperty(position = 2) private String officialname; @NotBlank - @ApiModelProperty(position = 3) private String englishname; - @ApiModelProperty(position = 4) private String websiteurl; @Email - @ApiModelProperty(position = 5) private String registeredby; - @ApiModelProperty(position = 6) private Date registrationdate; - @ApiModelProperty(position = 7) private String eoscDatasourceType; - @ApiModelProperty(position = 8) private String logoUrl; - @ApiModelProperty(position = 9) private String description; - @ApiModelProperty(position = 10) private Boolean consentTermsOfUse; - @ApiModelProperty(position = 11) private Date consentTermsOfUseDate; - @ApiModelProperty(position = 12) private Date lastConsentTermsOfUseDate; - @ApiModelProperty(position = 13) private Boolean fullTextDownload; - @ApiModelProperty(position = 14) private Set organizations; @Deprecated - @ApiModelProperty(position = 15) private String typology; public String getId() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippetResponse.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippetResponse.java index a5636b65..522d5653 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippetResponse.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/DatasourceSnippetResponse.java @@ -1,28 +1,24 @@ package eu.dnetlib.openaire.dsm.domain; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - import java.util.List; -@ApiModel +import com.fasterxml.jackson.annotation.JsonAutoDetect; + @JsonAutoDetect public class DatasourceSnippetResponse extends Response { - @ApiModelProperty(position = 1) - private List datasourceInfo; + private List datasourceInfo; - public DatasourceSnippetResponse(List datasourceInfo) { - super(); - this.datasourceInfo = datasourceInfo; - } + public DatasourceSnippetResponse(final List datasourceInfo) { + super(); + this.datasourceInfo = datasourceInfo; + } - public List getDatasourceInfo() { - return datasourceInfo; - } + public List getDatasourceInfo() { + return datasourceInfo; + } - public void setDatasourceInfo(List datasourceInfo) { - this.datasourceInfo = datasourceInfo; - } + public void setDatasourceInfo(final List datasourceInfo) { + this.datasourceInfo = datasourceInfo; + } } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/FilterName.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/FilterName.java index f6e3de96..2dbd67eb 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/FilterName.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/FilterName.java @@ -2,10 +2,10 @@ package eu.dnetlib.openaire.dsm.domain; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect -@ApiModel(value = "Filter name", description = "List of the field names used to filter datasources") +@Schema(name = "Filter name", description = "List of the field names used to filter datasources") public enum FilterName { id, @@ -16,6 +16,7 @@ public enum FilterName { websiteurl, contactemail, registeredby, + typology, eoscDatasourceType, platform, // like match country; // exact match on related organization @@ -31,9 +32,11 @@ public enum FilterName { case websiteurl: case contactemail: case registeredby: - case eoscDatasourceType: + case typology: case platform: return FilterType.search; + case eoscDatasourceType: + return FilterType.multiSearch; case country: return FilterType.searchOrgs; default: diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/FilterType.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/FilterType.java index 5d15adfd..a028e350 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/FilterType.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/FilterType.java @@ -1,5 +1,8 @@ package eu.dnetlib.openaire.dsm.domain; public enum FilterType { - exact, search, searchOrgs + exact, + search, + searchOrgs, + multiSearch } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/Header.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/Header.java index 81dc2d67..4db04905 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/Header.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/Header.java @@ -8,29 +8,20 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.collect.Lists; import com.google.gson.GsonBuilder; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -@ApiModel @JsonAutoDetect public class Header { - @ApiModelProperty(position = 0) private long total; - @ApiModelProperty(position = 1) private int page; - @ApiModelProperty(position = 2) private int size; - @ApiModelProperty(position = 3) private long time; - @ApiModelProperty(position = 4) private int statusCode; - @ApiModelProperty(position = 5) private List errors = Lists.newArrayList(); @JsonIgnore @@ -40,8 +31,7 @@ public class Header { return new Header(); } - public Header() { - } + public Header() {} public long getTime() { return time; @@ -99,8 +89,8 @@ public class Header { public List getErrors() { return getExceptions().stream() - .map(Throwable::getMessage) - .collect(Collectors.toList()); + .map(Throwable::getMessage) + .collect(Collectors.toList()); } public Header setErrors(final List errors) { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/IdentitiesDetails.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/IdentitiesDetails.java index ff389b38..48cba1e9 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/IdentitiesDetails.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/IdentitiesDetails.java @@ -1,9 +1,7 @@ package eu.dnetlib.openaire.dsm.domain; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -@ApiModel @JsonAutoDetect public class IdentitiesDetails { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/OrganizationDetails.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/OrganizationDetails.java index 79dd5a3c..1abc52d4 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/OrganizationDetails.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/OrganizationDetails.java @@ -4,28 +4,22 @@ import javax.validation.constraints.NotBlank; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect -@ApiModel(value = "Organization info model", description = "provides information about the organization") +@Schema(name = "Organization info model", description = "provides information about the organization") public class OrganizationDetails extends OrganizationIgnoredProperties { - @ApiModelProperty(position = 0) private String legalshortname; @NotBlank - @ApiModelProperty(position = 1) private String legalname; - @ApiModelProperty(position = 2) private String websiteurl; - @ApiModelProperty(position = 3) private String logourl; @NotBlank - @ApiModelProperty(position = 4) private String country; public String getLegalshortname() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/RequestFilter.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/RequestFilter.java index 4275db07..fe160844 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/RequestFilter.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/RequestFilter.java @@ -4,10 +4,10 @@ import java.util.HashMap; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect -@ApiModel(value = "Request filter", description = "field name and value pairs") +@Schema(name = "Request filter", description = "field name and value pairs") public class RequestFilter extends HashMap { /** diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/Response.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/Response.java index d52b499a..abba2c54 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/Response.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/Response.java @@ -1,16 +1,13 @@ package eu.dnetlib.openaire.dsm.domain; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; + +import io.swagger.v3.oas.annotations.media.Schema; @JsonAutoDetect -@ApiModel( - value = "Api response model", - description = "Api response model, provides a response header") +@Schema(name = "Api response model", description = "Api response model, provides a response header") public class Response { - @ApiModelProperty(position = 0) private Header header; public Response() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/SimpleDatasourceInfo.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/SimpleDatasourceInfo.java new file mode 100644 index 00000000..997f3894 --- /dev/null +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/SimpleDatasourceInfo.java @@ -0,0 +1,129 @@ +package eu.dnetlib.openaire.dsm.domain; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class SimpleDatasourceInfo { + + private String id; + private String officialName; + private String englishName; + private Map organizations = new LinkedHashMap<>(); + @Deprecated + private String typology; + private String eoscType; + private String eoscDatasourceType; + private String registeredBy; + private String registrationDate; + private String compatibility; + private String firstCollectionDate; + private String lastCollectionDate; + private long lastCollectionTotal; + + public String getId() { + return id; + } + + public void setId(final String id) { + this.id = id; + } + + public String getOfficialName() { + return officialName; + } + + public void setOfficialName(final String officialName) { + this.officialName = officialName; + } + + public String getEnglishName() { + return englishName; + } + + public void setEnglishName(final String englishName) { + this.englishName = englishName; + } + + public Map getOrganizations() { + return organizations; + } + + public void setOrganizations(final Map organizations) { + this.organizations = organizations; + } + + @Deprecated + public String getTypology() { + return typology; + } + + @Deprecated + public void setTypology(final String typology) { + this.typology = typology; + } + + public String getEoscType() { + return eoscType; + } + + public void setEoscType(final String eoscType) { + this.eoscType = eoscType; + } + + public String getEoscDatasourceType() { + return eoscDatasourceType; + } + + public void setEoscDatasourceType(final String eoscDatasourceType) { + this.eoscDatasourceType = eoscDatasourceType; + } + + public String getRegisteredBy() { + return registeredBy; + } + + public void setRegisteredBy(final String registeredBy) { + this.registeredBy = registeredBy; + } + + public String getRegistrationDate() { + return registrationDate; + } + + public void setRegistrationDate(final String registrationDate) { + this.registrationDate = registrationDate; + } + + public String getCompatibility() { + return compatibility; + } + + public void setCompatibility(final String compatibility) { + this.compatibility = compatibility; + } + + public String getFirstCollectionDate() { + return firstCollectionDate; + } + + public void setFirstCollectionDate(final String firstCollectionDate) { + this.firstCollectionDate = firstCollectionDate; + } + + public String getLastCollectionDate() { + return lastCollectionDate; + } + + public void setLastCollectionDate(final String lastCollectionDate) { + this.lastCollectionDate = lastCollectionDate; + } + + public long getLastCollectionTotal() { + return lastCollectionTotal; + } + + public void setLastCollectionTotal(final long lastCollectionTotal) { + this.lastCollectionTotal = lastCollectionTotal; + } + +} diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/SimpleResponse.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/SimpleResponse.java index cb79eb9c..73381faf 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/SimpleResponse.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/SimpleResponse.java @@ -4,14 +4,9 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - -@ApiModel @JsonAutoDetect public class SimpleResponse extends Response { - @ApiModelProperty(position = 1) private List response; public List getResponse() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/TransformationInfo.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/TransformationInfo.java index b4ccc38b..ec7cf05f 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/TransformationInfo.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/TransformationInfo.java @@ -3,12 +3,10 @@ package eu.dnetlib.openaire.dsm.domain; import com.fasterxml.jackson.annotation.JsonAutoDetect; import eu.dnetlib.enabling.datasources.common.AggregationInfo; -import io.swagger.annotations.ApiModel; /** * Created by claudio on 29/11/2016. */ -@ApiModel @JsonAutoDetect public class TransformationInfo extends AggregationInfo { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/ApiParamDbEntry.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/ApiParamDbEntry.java index 59a90314..49a4dde2 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/ApiParamDbEntry.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/ApiParamDbEntry.java @@ -6,8 +6,9 @@ import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + import eu.dnetlib.enabling.datasources.common.ApiParam; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; /** * Created by claudio on 13/04/2017. @@ -15,7 +16,7 @@ import io.swagger.annotations.ApiModel; @Entity @Table(name = "dsm_apiparams") @JsonIgnoreProperties(ignoreUnknown = true) -@ApiModel(value = "Datasource Api params model", description = "describes the datasource api params") +@Schema(name = "Datasource Api params model", description = "describes the datasource api params") public class ApiParamDbEntry implements ApiParam { @EmbeddedId @@ -35,10 +36,12 @@ public class ApiParamDbEntry implements ApiParam { return id; } + @Override public String getValue() { return value; } + @Override public void setValue(final String value) { this.value = value; } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/CountryTerm.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/CountryTerm.java index 87b78ed8..8fc19f5b 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/CountryTerm.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/CountryTerm.java @@ -7,14 +7,12 @@ import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonAutoDetect; import eu.dnetlib.enabling.datasources.common.BrowseTerm; -import io.swagger.annotations.ApiModel; /** * Created by claudio on 20/04/2017. */ @Entity @Table(name = "browse_countries") -@ApiModel @JsonAutoDetect public class CountryTerm implements Comparable, BrowseTerm { @@ -27,6 +25,7 @@ public class CountryTerm implements Comparable, BrowseTerm { return term; } + @Override public void setTerm(final String term) { this.term = term; } @@ -36,6 +35,7 @@ public class CountryTerm implements Comparable, BrowseTerm { return total; } + @Override public void setTotal(final long total) { this.total = total; } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/DatasourceApiDbEntry.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/DatasourceApiDbEntry.java index 064c4f41..044aff6e 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/DatasourceApiDbEntry.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/DatasourceApiDbEntry.java @@ -8,12 +8,12 @@ import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnore; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; @Entity @JsonAutoDetect @Table(name = "dsm_datasource_api") -@ApiModel(value = "DatasourceApi model", description = "describes a joint view between datasources and their API (1:N)") +@Schema(name = "DatasourceApi model", description = "describes a joint view between datasources and their API (1:N)") public class DatasourceApiDbEntry { @Id diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/DatasourceDbEntry.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/DatasourceDbEntry.java index fad3e190..9b558ed0 100755 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/DatasourceDbEntry.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/dsm/domain/db/DatasourceDbEntry.java @@ -19,6 +19,8 @@ import eu.dnetlib.enabling.datasources.common.Datasource; @Table(name = "dsm_services") public class DatasourceDbEntry extends Datasource { + public static final String DEFAULT_EOSC_TYPE = "Data Source"; + @Transient private String openaireId; @@ -26,6 +28,12 @@ public class DatasourceDbEntry extends Datasource getFunders( - @PathVariable final int page, - @PathVariable final int size) throws FundersApiException { + @PathVariable final int page, + @PathVariable final int size) throws FundersApiException { return fDao.listFunderDetails(page, size); } - @RequestMapping(value = "/funder/{id}", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation(value = "get the funder details", notes = "complete funder information", response = FunderDbEntry.class) + @RequestMapping(value = "/funder/{id}", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get the funder details", description = "complete funder information") @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = FunderDbEntry.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public ExtendedFunderDetails getFunderDetails( - @PathVariable final String id) throws FundersApiException { + @PathVariable final String id) throws FundersApiException { return fDao.getExtendedFunderDetails(id); } - @RequestMapping(value = "/funder/ids", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation(value = "get the list of funder ids", notes = "get the list of funder ids", response = String[].class) + @RequestMapping(value = "/funder/ids", produces = { + "application/json" + }, method = RequestMethod.GET) + @Operation(summary = "get the list of funder ids", description = "get the list of funder ids") @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = String[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public List getFunderIds( - @PathVariable final int page, - @PathVariable final int size - ) throws FundersApiException { + @PathVariable final int page, + @PathVariable final int size) throws FundersApiException { return fDao.listFunderIds(page, size); } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/info/InfoController.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/info/InfoController.java index a3027500..4d132ba5 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/info/InfoController.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/info/InfoController.java @@ -19,16 +19,17 @@ import com.google.common.collect.Maps; import eu.dnetlib.openaire.common.AbstractExporterController; import eu.dnetlib.openaire.common.ExporterConstants; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @CrossOrigin(origins = { "*" }) @ConditionalOnProperty(value = "openaire.exporter.enable.info", havingValue = "true") -@io.swagger.annotations.Api(tags = "OpenAIRE Info API", description = "the OpenAIRE info API") +@Tag(name = "OpenAIRE Info API", description = "the OpenAIRE info API") public class InfoController extends AbstractExporterController { private static final Log log = LogFactory.getLog(InfoController.class); // NOPMD by marko on 11/24/08 5:02 PM @@ -41,12 +42,12 @@ public class InfoController extends AbstractExporterController { @RequestMapping(value = "/info/{infoKey}", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation(value = "get info date", notes = "get info date", tags = { + @Operation(summary = "get info date", description = "get info date", tags = { ExporterConstants.R - }, response = LocalDate.class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = LocalDate.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public LocalDate getDate(@PathVariable final String infoKey) { final JdbcInfoDao.DATE_INFO info = JdbcInfoDao.DATE_INFO.valueOf(infoKey); @@ -57,12 +58,12 @@ public class InfoController extends AbstractExporterController { @RequestMapping(value = "/info", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation(value = "get all the info date", notes = "get all the info date", tags = { + @Operation(summary = "get all the info date", description = "get all the info date", tags = { ExporterConstants.R - }, response = Map.class) + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = LocalDate.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public Map listInfo() { final Map map = Maps.newHashMap(); @@ -75,12 +76,12 @@ public class InfoController extends AbstractExporterController { @RequestMapping(value = "/info/keys", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation(value = "get the available keys", notes = "get the available keys", tags = { + @Operation(summary = "get the available keys", description = "get the available keys", tags = { ExporterConstants.R - }, response = String.class, responseContainer = "List") + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = LocalDate.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") }) public List listInfoKeys() { final List keys = Lists.newArrayList(); @@ -93,7 +94,7 @@ public class InfoController extends AbstractExporterController { @RequestMapping(value = "/info/dropCache", produces = { "application/json" }, method = RequestMethod.GET) - @ApiOperation(value = "Drops the info cache", notes = "Drops the info cache", tags = { + @Operation(summary = "Drops the info cache", description = "Drops the info cache", tags = { ExporterConstants.R }) public void dropCache() { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/ProjectsController.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/ProjectsController.java index 00abbcf2..95115946 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/ProjectsController.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/ProjectsController.java @@ -8,22 +8,11 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.zip.ZipOutputStream; + import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.google.common.xml.XmlEscapers; -import eu.dnetlib.DnetOpenaireExporterProperties; -import eu.dnetlib.DnetOpenaireExporterProperties.Project; -import eu.dnetlib.openaire.common.AbstractExporterController; -import eu.dnetlib.openaire.common.ExporterConstants; -import eu.dnetlib.openaire.project.domain.db.ProjectTsv; -import eu.dnetlib.openaire.project.domain.db.ProjectDetails; -import eu.dnetlib.openaire.project.dao.JdbcApiDao; -import eu.dnetlib.openaire.project.dao.ValueCleaner; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import org.antlr.stringtemplate.StringTemplate; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -38,10 +27,25 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; +import com.google.common.xml.XmlEscapers; + +import eu.dnetlib.DnetOpenaireExporterProperties; +import eu.dnetlib.DnetOpenaireExporterProperties.Project; +import eu.dnetlib.openaire.common.AbstractExporterController; +import eu.dnetlib.openaire.common.ExporterConstants; +import eu.dnetlib.openaire.project.dao.JdbcApiDao; +import eu.dnetlib.openaire.project.dao.ValueCleaner; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + @Controller -@CrossOrigin(origins = { "*" }) +@CrossOrigin(origins = { + "*" +}) @ConditionalOnProperty(value = "openaire.exporter.enable.project", havingValue = "true") -@io.swagger.annotations.Api(tags = "OpenAIRE projects API", description = "the OpenAIRE projects API") +@Tag(name = "OpenAIRE projects API", description = "the OpenAIRE projects API") public class ProjectsController extends AbstractExporterController { private static final Log log = LogFactory.getLog(ProjectsController.class); // NOPMD by marko on 11/24/08 5:02 PM @@ -58,19 +62,19 @@ public class ProjectsController extends AbstractExporterController { private ProjectQueryParamsFactory projectQueryParamsFactory; @RequestMapping(value = "/export/**/project/dspace.do", method = RequestMethod.GET) - @ApiOperation( - value = "DSpace", - notes = "return project information in compatible with the OpenAIRE plugin for DSpace", - tags = { ExporterConstants.DSPACE }, - response = String.class) + @Operation(summary = "DSpace", description = "return project information in compatible with the OpenAIRE plugin for DSpace", tags = { + ExporterConstants.DSPACE + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = String.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) }) - public void processDspace(final HttpServletRequest request, final ServletResponse response, - @RequestParam(value = "startFrom", required = false) final String startFrom, - @RequestParam(value = "startUntil", required = false) final String startUntil, - @RequestParam(value = "endFrom", required = false) final String endFrom, - @RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) + public void processDspace(final HttpServletRequest request, + final ServletResponse response, + @RequestParam(value = "startFrom", required = false) final String startFrom, + @RequestParam(value = "startUntil", required = false) final String startUntil, + @RequestParam(value = "endFrom", required = false) final String endFrom, + @RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception { final Project conf = config.getProject(); @@ -86,19 +90,19 @@ public class ProjectsController extends AbstractExporterController { } @RequestMapping(value = "/export/**/project/eprints.do", method = RequestMethod.GET) - @ApiOperation( - value = "EPrints", - notes = "return project information in compatible with the OpenAIRE plugin for Eprints", - tags = { ExporterConstants.EPRINT }, - response = String.class) + @Operation(summary = "EPrints", description = "return project information in compatible with the OpenAIRE plugin for Eprints", tags = { + ExporterConstants.EPRINT + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = String.class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) }) - public void processEprints(final HttpServletRequest request, final ServletResponse response, - @RequestParam(value = "startFrom", required = false) final String startFrom, - @RequestParam(value = "startUntil", required = false) final String startUntil, - @RequestParam(value = "endFrom", required = false) final String endFrom, - @RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) + public void processEprints(final HttpServletRequest request, + final ServletResponse response, + @RequestParam(value = "startFrom", required = false) final String startFrom, + @RequestParam(value = "startUntil", required = false) final String startUntil, + @RequestParam(value = "endFrom", required = false) final String endFrom, + @RequestParam(value = "endUntil", required = false) final String endUntil) throws Exception { final ProjectQueryParams params = projectQueryParamsFactory.generateParams(request, startFrom, startUntil, endFrom, endUntil); response.setContentType("text/html"); @@ -110,29 +114,30 @@ public class ProjectsController extends AbstractExporterController { } private void doProcess( - final ServletResponse response, - final ProjectQueryParams params, - final String head, final Resource projectTemplate, final String tail, - final ValueCleaner cleaner) throws IOException, SQLException { + final ServletResponse response, + final ProjectQueryParams params, + final String head, + final Resource projectTemplate, + final String tail, + final ValueCleaner cleaner) throws IOException, SQLException { final StringTemplate st = new StringTemplate(IOUtils.toString(projectTemplate.getInputStream(), UTF8)); - try(final OutputStream out = new BufferedOutputStream(response.getOutputStream())) { + try (final OutputStream out = new BufferedOutputStream(response.getOutputStream())) { dao.streamProjects(obtainQuery(params), out, head, st, tail, cleaner); } } @RequestMapping(value = "/noads/project2tsv.do", method = RequestMethod.GET) - @ApiOperation( - value = "TSV", - notes = "download project information in TSV format", - tags = { ExporterConstants.TSV }, - response = ProjectTsv[].class) + @Operation(summary = "TSV", description = "download project information in TSV format", tags = { + ExporterConstants.TSV + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = ProjectTsv[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public void processTsv(final HttpServletResponse response, - @RequestParam(value = "funding", required = true) final String funding, - @RequestParam(value = "article293", required = false) final Boolean article293) throws Exception { + @RequestParam(value = "funding", required = true) final String funding, + @RequestParam(value = "article293", required = false) final Boolean article293) throws Exception { final String fundingPrefix = getFundingPrefix(funding, null); @@ -140,37 +145,37 @@ public class ProjectsController extends AbstractExporterController { final String filename = "projects_" + funding + "_" + date + ".tsv"; response.setContentType("text/tab-separated-values"); response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + ".zip\""); - try(final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()))) { + try (final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()))) { dao.processTsvRequest(out, article293, fundingPrefix, filename); - } catch (Throwable e) { + } catch (final Throwable e) { throw new RuntimeException("Error processing the request", e); } } @RequestMapping(value = "/export/streamProjectDetails.do", method = RequestMethod.GET) - @ApiOperation( - value = "Stream projects", - notes = "stream project information", - tags = { ExporterConstants.STREAMING }, - response = ProjectDetails[].class) + @Operation(summary = "Stream projects", description = "stream project information", tags = { + ExporterConstants.STREAMING + }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = ProjectDetails[].class), - @ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) }) + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "500", description = "unexpected error") + }) public void streamProjectDetails(final HttpServletResponse response, - @RequestParam(value = "format", required = true) final String format, - @RequestParam(value = "compress", required = false) final Boolean compress) throws IOException, SQLException { + @RequestParam(value = "format", required = true) final String format, + @RequestParam(value = "compress", required = false) final Boolean compress) throws IOException, SQLException { if (compress != null && compress) { response.setHeader("Content-Encoding", "gzip"); } switch (format) { - case "csv": - response.setContentType("text/csv"); - break; - case "json": - response.setContentType("text/plain"); - break; - default: throw new IllegalArgumentException("unsupported format: " + format); + case "csv": + response.setContentType("text/csv"); + break; + case "json": + response.setContentType("text/plain"); + break; + default: + throw new IllegalArgumentException("unsupported format: " + format); } dao.processProjectDetails(response.getOutputStream(), format, compress); @@ -190,22 +195,20 @@ public class ProjectsController extends AbstractExporterController { * if the funding program is not recognized */ protected String obtainQuery(final ProjectQueryParams params) throws IllegalArgumentException, IOException { - String funding = params.getFundingProgramme(); - String suffix = params.getFundingPath(); + final String funding = params.getFundingProgramme(); + final String suffix = params.getFundingPath(); final StringTemplate st = new StringTemplate(IOUtils.toString(config.getProject().getProjectsFundingQueryTemplate().getInputStream(), UTF8)); st.setAttribute("fundingprefix", getFundingPrefix(funding, suffix)); - String theQuery = setDateParameters(st.toString(), params); + final String theQuery = setDateParameters(st.toString(), params); log.debug("Generated query: " + theQuery); return theQuery; } private String getFundingPrefix(final String funding, final String suffix) { final Map fundingIds = dao.readFundingpathIds(); - if (!fundingIds.containsKey(funding.toUpperCase())) { - throw new IllegalArgumentException("invalid funding " + funding); - } - String fundingPrefix = fundingIds.get(funding.toUpperCase()); + if (!fundingIds.containsKey(funding.toUpperCase())) { throw new IllegalArgumentException("invalid funding " + funding); } + final String fundingPrefix = fundingIds.get(funding.toUpperCase()); return StringUtils.isBlank(suffix) ? fundingPrefix : fundingPrefix + "::" + suffix.toUpperCase(); } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectApi.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectApi.java index 361f6534..3bc6990a 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectApi.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectApi.java @@ -2,22 +2,25 @@ package eu.dnetlib.openaire.project.domain.db; import java.sql.Date; import java.util.ArrayList; + import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +import org.apache.commons.lang3.StringUtils; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.base.Splitter; import com.google.common.collect.Lists; -import io.swagger.annotations.ApiModel; -import org.apache.commons.lang3.StringUtils; + +import io.swagger.v3.oas.annotations.media.Schema; /** * Created by claudio on 20/09/16. */ @Entity @Table(name = "projects_api") -@ApiModel(value = "Project api model", description = "Project api model used by DSpace and Eprints exporter") +@Schema(name = "Project api model", description = "Project api model used by DSpace and Eprints exporter") public class ProjectApi { public static final String INFO_EU_REPO_GRANT_AGREEMENT = "info:eu-repo/grantAgreement/"; @@ -35,10 +38,10 @@ public class ProjectApi { private Date enddate; private String fundingpathid; - public ProjectApi() { } + public ProjectApi() {} public String getIdnamespace() { - String res = INFO_EU_REPO_GRANT_AGREEMENT + getFunder()+"/"; + String res = INFO_EU_REPO_GRANT_AGREEMENT + getFunder() + "/"; final String fundingProgram = asFundingProgram(getFundingpathid()); if (StringUtils.isNotBlank(fundingProgram)) { res += fundingProgram; @@ -69,9 +72,12 @@ public class ProjectApi { private String asFundingProgram(final String fundingpathid) { final ArrayList strings = Lists.newArrayList(Splitter.on("::").split(fundingpathid)); - if(strings.size() <= 1) throw new IllegalStateException("Unexpected funding id: "+fundingpathid); - if(strings.size() == 2) return ""; - else return replaceSlash(strings.get(2)); + if (strings.size() <= 1) { throw new IllegalStateException("Unexpected funding id: " + fundingpathid); } + if (strings.size() == 2) { + return ""; + } else { + return replaceSlash(strings.get(2)); + } } private String replaceSlash(final String s) { diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectDetails.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectDetails.java index e4bb8ad3..47517d24 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectDetails.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectDetails.java @@ -6,15 +6,16 @@ import java.io.StringWriter; import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; -import javax.persistence.*; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.google.gson.Gson; -import io.swagger.annotations.ApiModel; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; + import org.hibernate.annotations.Type; import org.supercsv.cellprocessor.Optional; import org.supercsv.cellprocessor.ift.CellProcessor; -import org.supercsv.cellprocessor.ift.StringCellProcessor; import org.supercsv.io.CsvBeanReader; import org.supercsv.io.CsvBeanWriter; import org.supercsv.io.ICsvBeanReader; @@ -22,21 +23,26 @@ import org.supercsv.io.ICsvBeanWriter; import org.supercsv.prefs.CsvPreference; import org.supercsv.util.CsvContext; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.gson.Gson; + +import io.swagger.v3.oas.annotations.media.Schema; + /** * Created by claudio on 04/07/2017. */ @Entity @Table(name = "project_details") -@ApiModel(value = "Project details model", description = "provides project details") +@Schema(name = "Project details model", description = "provides project details") public class ProjectDetails { @Transient @JsonIgnore private transient static final String[] FIELDS = Arrays.stream(ProjectDetails.class.getDeclaredFields()) - .map(Field::getName) - .filter(s -> !s.equals("FIELDS")) - .filter(s -> !s.startsWith("optional")) - .toArray(String[]::new); + .map(Field::getName) + .filter(s -> !s.equals("FIELDS")) + .filter(s -> !s.startsWith("optional")) + .toArray(String[]::new); @Id @Column(name = "projectid") @@ -50,8 +56,7 @@ public class ProjectDetails { @Column(name = "fundingpath", columnDefinition = "text[]") private String[] fundingPath; - public ProjectDetails() { - } + public ProjectDetails() {} public String getProjectId() { return projectId; @@ -74,7 +79,7 @@ public class ProjectDetails { } public void setFundingPath(final List fundingPath) { - if(fundingPath != null && !fundingPath.isEmpty()) { + if (fundingPath != null && !fundingPath.isEmpty()) { this.fundingPath = fundingPath.toArray(new String[fundingPath.size()]); } } @@ -85,28 +90,32 @@ public class ProjectDetails { public static ProjectDetails fromCSV(final String csv) throws IOException { try (ICsvBeanReader beanReader = new CsvBeanReader(new StringReader(csv), CsvPreference.STANDARD_PREFERENCE)) { - return beanReader.read(ProjectDetails.class, FIELDS, getProcessors(new StringCellProcessor() { + final CellProcessor cp = new CellProcessor() { + + @SuppressWarnings("unchecked") @Override - public Object execute(final Object value, final CsvContext context) { - return new Gson().fromJson(value.toString(), List.class); + public T execute(final Object value, final CsvContext context) { + return (T) new Gson().fromJson(value.toString(), List.class); } - })); + }; + + return beanReader.read(ProjectDetails.class, FIELDS, getProcessors(cp)); } } /** - * Sets up the processors used for the examples. There are 10 CSV columns, so 10 processors are defined. Empty - * columns are read as null (hence the NotNull() for mandatory columns). + * Sets up the processors used for the examples. There are 10 CSV columns, so 10 processors are defined. Empty columns are read as null + * (hence the NotNull() for mandatory columns). * * @return the cell processors */ private static CellProcessor[] getProcessors(final CellProcessor fundingPathProcessor) { return new CellProcessor[] { - new Optional(), // projectId - new Optional(), // acronym - new Optional(), // code - new Optional(), // jsonextrainfo - fundingPathProcessor + new Optional(), // projectId + new Optional(), // acronym + new Optional(), // code + new Optional(), // jsonextrainfo + fundingPathProcessor }; } @@ -117,12 +126,15 @@ public class ProjectDetails { public String asCSV() throws IOException { final StringWriter sb = new StringWriter(); try (ICsvBeanWriter beanWriter = new CsvBeanWriter(sb, CsvPreference.STANDARD_PREFERENCE)) { - beanWriter.write(this, FIELDS, getProcessors(new StringCellProcessor() { + final CellProcessor cp = new CellProcessor() { + + @SuppressWarnings("unchecked") @Override - public Object execute(final Object value, final CsvContext context) { - return new Gson().toJson(value); + public T execute(final Object value, final CsvContext context) { + return (T) new Gson().toJson(value); } - })); + }; + beanWriter.write(this, FIELDS, getProcessors(cp)); beanWriter.flush(); } diff --git a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectTsv.java b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectTsv.java index fdf7bd05..9e746118 100644 --- a/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectTsv.java +++ b/apps/dnet-exporter-api/src/main/java/eu/dnetlib/openaire/project/domain/db/ProjectTsv.java @@ -2,22 +2,25 @@ package eu.dnetlib.openaire.project.domain.db; import java.sql.Date; import java.util.List; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +import org.apache.commons.lang3.StringUtils; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.collect.Lists; -import io.swagger.annotations.ApiModel; -import org.apache.commons.lang3.StringUtils; + +import io.swagger.v3.oas.annotations.media.Schema; /** * Created by claudio on 05/07/2017. */ @Entity @Table(name = "projects_tsv") -@ApiModel(value = "Project TSV model", description = "project TSV model description") +@Schema(name = "Project TSV model", description = "project TSV model description") public class ProjectTsv { @Id @@ -51,25 +54,14 @@ public class ProjectTsv { public ProjectTsv() {} public List asList() { - return Lists.newArrayList( - clean(getCode()), - clean(getAcronym()), - clean(getTitle()), - clean(getCallIdentifier()), - clean(getStartdate() != null ? getStartdate().toString() : ""), - clean(getEnddate() != null ? getEnddate().toString() : ""), - clean(String.valueOf(isOaMandateForPublications())), - clean(String.valueOf(isOaMandateForDatasets())), - clean(getDescription()), - clean(getOrgLegalname()), - clean(getOrgCountry()), - clean(getOrgRole()), - clean(getContactfullname()), - clean(getContactemail())); + return Lists.newArrayList(clean(getCode()), clean(getAcronym()), clean(getTitle()), clean(getCallIdentifier()), clean(getStartdate() != null + ? getStartdate().toString() + : ""), clean(getEnddate() != null ? getEnddate().toString() : ""), clean(String.valueOf(isOaMandateForPublications())), clean(String + .valueOf(isOaMandateForDatasets())), clean(getDescription()), clean(getOrgLegalname()), clean(getOrgCountry()), clean(getOrgRole()), clean(getContactfullname()), clean(getContactemail())); } private String clean(final String s) { - return StringUtils.isNotBlank(s) ? "\"" + s.replaceAll("\\n|\\t|\\s+", " ").replace("\"","\"\"").trim() + "\"" : ""; + return StringUtils.isNotBlank(s) ? "\"" + s.replaceAll("\\n|\\t|\\s+", " ").replace("\"", "\"\"").trim() + "\"" : ""; } public long getRowid() { diff --git a/apps/dnet-exporter-api/src/main/resources/application.properties b/apps/dnet-exporter-api/src/main/resources/application.properties index 2b947038..bde38f76 100644 --- a/apps/dnet-exporter-api/src/main/resources/application.properties +++ b/apps/dnet-exporter-api/src/main/resources/application.properties @@ -2,6 +2,9 @@ server.servlet.context-path = /openaire server.port = 8080 +server.public_url = +server.public_desc = API Base URL + spring.datasource.driverClassName = org.postgresql.Driver spring.jpa.database-platform = org.hibernate.dialect.PostgreSQL9Dialect spring.jpa.show-sql = false diff --git a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/count_first_collected_datasources_fromDate.st.sql b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/count_first_collected_datasources_fromDate.st.sql new file mode 100644 index 00000000..1cf5f393 --- /dev/null +++ b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/count_first_collected_datasources_fromDate.st.sql @@ -0,0 +1,7 @@ +select count(*) as count +from ( + select d.id + from dsm_services d left outer join dsm_api a on (d.id = a.service) + group by d.id + having min(a.first_collection_date) >= cast(? as date) +) as t diff --git a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/count_first_collected_datasources_fromDate_typology.st.sql b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/count_first_collected_datasources_fromDate_typology.st.sql new file mode 100644 index 00000000..b0a79a29 --- /dev/null +++ b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/count_first_collected_datasources_fromDate_typology.st.sql @@ -0,0 +1,8 @@ +select count(*) as count +from ( + select d.id + from dsm_services d left outer join dsm_api a on (d.id = a.service) + where d._typology_to_remove_ like ? + group by d.id + having min(a.first_collection_date) >= cast(? as date) +) as t diff --git a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/first_collected_datasources_fromDate.st.sql b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/first_collected_datasources_fromDate.st.sql new file mode 100644 index 00000000..f228e03b --- /dev/null +++ b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/first_collected_datasources_fromDate.st.sql @@ -0,0 +1,29 @@ +SELECT + s.id AS "id", + s.officialname AS "officialName", + s.englishname AS "englishName", + s._typology_to_remove_ AS "typology", + s.eosc_type AS "eoscType", + s.eosc_datasource_type AS "eoscDatasourceType", + s.registeredby AS "registeredBy", + s.registrationdate::text AS "registrationDate", + MIN(a.first_collection_date) AS "firstCollectionDate", + MAX(a.last_collection_date) AS "lastCollectionDate", + (array_remove(array_agg(a.last_collection_total order by a.last_collection_date desc), NULL))[1] AS "lastCollectionTotal", + array_remove(array_agg(DISTINCT coalesce(a.compatibility_override, a.compatibility)), NULL) AS "compatibilities", + array_remove(array_agg(DISTINCT o.id||' @@@ '||o.legalname), NULL) AS "organizations" +FROM + dsm_services s + left outer join dsm_api a on (s.id = a.service) + left outer join dsm_service_organization dso on (s.id = dso.service) + left outer join dsm_organizations o on (o.id = dso.organization) +GROUP BY + s.id, + s.officialname, + s.englishname, + s._typology_to_remove_, + s.eosc_type, + s.eosc_datasource_type, + s.registeredby, + s.registrationdate +HAVING MIN(a.first_collection_date) >= cast(? as date) diff --git a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/first_collected_datasources_fromDate_typology.st.sql b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/first_collected_datasources_fromDate_typology.st.sql new file mode 100644 index 00000000..13d64cb4 --- /dev/null +++ b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/first_collected_datasources_fromDate_typology.st.sql @@ -0,0 +1,31 @@ +SELECT + s.id AS "id", + s.officialname AS "officialName", + s.englishname AS "englishName", + s._typology_to_remove_ AS "typology", + s.eosc_type AS "eoscType", + s.eosc_datasource_type AS "eoscDatasourceType", + s.registeredby AS "registeredBy", + s.registrationdate::text AS "registrationDate", + MIN(a.first_collection_date) AS "firstCollectionDate", + MAX(a.last_collection_date) AS "lastCollectionDate", + (array_remove(array_agg(a.last_collection_total order by a.last_collection_date desc), NULL))[1] AS "lastCollectionTotal", + array_remove(array_agg(DISTINCT coalesce(a.compatibility_override, a.compatibility)), NULL) AS "compatibilities", + array_remove(array_agg(DISTINCT o.id||' @@@ '||o.legalname), NULL) AS "organizations" +FROM + dsm_services s + left outer join dsm_api a on (s.id = a.service) + left outer join dsm_service_organization dso on (s.id = dso.service) + left outer join dsm_organizations o on (o.id = dso.organization) +WHERE + s._typology_to_remove_ like ? +GROUP BY + s.id, + s.officialname, + s.englishname, + s._typology_to_remove_, + s.eosc_type, + s.eosc_datasource_type, + s.registeredby, + s.registrationdate +HAVING MIN(a.first_collection_date) >= cast(? as date) diff --git a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_fromDate.st.sql b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_fromDate.st.sql index e014461c..6d8bbf02 100644 --- a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_fromDate.st.sql +++ b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_fromDate.st.sql @@ -1,9 +1,7 @@ -select count(d.id) as count +select count(DISTINCT d.id) as count from dsm_services d left outer join dsm_api a on (d.id = a.service) - left outer join dsm_service_organization dso on (d.id = dso.service) - left outer join dsm_organizations o on (o.id = dso.organization) where d.registrationdate >= cast(? as date) and d.registrationdate < a.last_collection_date diff --git a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_fromDate_typology.st.sql b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_fromDate_typology.st.sql index 1af6acd7..9e8a9f0b 100644 --- a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_fromDate_typology.st.sql +++ b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_fromDate_typology.st.sql @@ -1,12 +1,10 @@ -select count(d.id) as count +select count(DISTINCT d.id) as count from dsm_services d left outer join dsm_api a on (d.id = a.service) - left outer join dsm_service_organization dso on (d.id = dso.service) - left outer join dsm_organizations o on (o.id = dso.organization) where d.registrationdate >= cast(? as date) - and d.eosc_datasource_type like ? + and d._typology_to_remove_ like ? and d.registrationdate < a.last_collection_date and d.registeredby is not null and d.managed = true diff --git a/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_v2.sql.st b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_v2.sql.st new file mode 100644 index 00000000..b4002ce4 --- /dev/null +++ b/apps/dnet-exporter-api/src/main/resources/eu/dnetlib/openaire/sql/recent_registered_datasources_v2.sql.st @@ -0,0 +1,38 @@ +SELECT + s.id AS "id", + s.officialname AS "officialName", + s.englishname AS "englishName", + s._typology_to_remove_ AS "typology", + s.eosc_type AS "eoscType", + s.eosc_datasource_type AS "eoscDatasourceType", + s.registeredby AS "registeredBy", + s.registrationdate::text AS "registrationDate", + MIN(a.first_collection_date) AS "firstCollectionDate", + MAX(a.last_collection_date) AS "lastCollectionDate", + (array_remove(array_agg(a.last_collection_total order by a.last_collection_date desc), NULL))[1] AS "lastCollectionTotal", + array_remove(array_agg(DISTINCT coalesce(a.compatibility_override, a.compatibility)), NULL) AS "compatibilities", + array_remove(array_agg(DISTINCT o.id||' @@@ '||o.legalname), NULL) AS "organizations" +FROM + dsm_services s + left outer join dsm_api a on (s.id = a.service) + left outer join dsm_service_organization dso on (s.id = dso.service) + left outer join dsm_organizations o on (o.id = dso.organization) +WHERE + s.registrationdate is not null + and s.registeredby is not null + and s.managed = true +GROUP BY + s.id, + s.officialname, + s.englishname, + s._typology_to_remove_, + s.eosc_type, + s.eosc_datasource_type, + s.registeredby, + s.registrationdate +HAVING + s.registrationdate < max(a.last_collection_date) + and sum(a.last_collection_total) > 0 +ORDER BY s.registrationdate desc +LIMIT ? + diff --git a/apps/dnet-exporter-api/src/test/java/eu/dnetlib/openaire/dsm/dao/utils/DsmMappingUtilsTest.java b/apps/dnet-exporter-api/src/test/java/eu/dnetlib/openaire/dsm/dao/utils/DsmMappingUtilsTest.java new file mode 100644 index 00000000..eb11e14d --- /dev/null +++ b/apps/dnet-exporter-api/src/test/java/eu/dnetlib/openaire/dsm/dao/utils/DsmMappingUtilsTest.java @@ -0,0 +1,24 @@ +package eu.dnetlib.openaire.dsm.dao.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import eu.dnetlib.openaire.dsm.domain.ApiDetails; +import eu.dnetlib.openaire.dsm.domain.db.ApiDbEntry; + +class DsmMappingUtilsTest { + + @BeforeEach + void setUp() throws Exception {} + + @Test + void testAsDetailsApiDbEntry() { + final ApiDetails api = new ApiDetails(); + api.setId("id:123"); + final ApiDbEntry dbEntry = DsmMappingUtils.asDbEntry(api); + assertEquals(api.getId(), dbEntry.getId()); + } + +} diff --git a/apps/dnet-orgs-database-application/pom.xml b/apps/dnet-orgs-database-application/pom.xml index 8c7638f6..026fa11d 100644 --- a/apps/dnet-orgs-database-application/pom.xml +++ b/apps/dnet-orgs-database-application/pom.xml @@ -4,7 +4,7 @@ eu.dnetlib.dhp apps - 3.2.9-SNAPSHOT + 3.3.3-SNAPSHOT ../ diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/MainApplication.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/MainApplication.java index f75b9eef..e1968ca4 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/MainApplication.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/MainApplication.java @@ -1,20 +1,16 @@ package eu.dnetlib.organizations; +import org.springdoc.core.GroupedOpenApi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; 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 eu.dnetlib.common.app.AbstractDnetApp; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; @SpringBootApplication -@EnableSwagger2 @EnableCaching @EnableScheduling @ComponentScan(basePackages = "eu.dnetlib") @@ -24,20 +20,16 @@ public class MainApplication extends AbstractDnetApp { SpringApplication.run(MainApplication.class, args); } - @Override - protected void configSwagger(final Docket docket) { - docket.select() - .apis(RequestHandlerSelectors.any()) - .paths(p -> p.startsWith("/api/") || p.startsWith("/oa_api")) - .build() - .apiInfo(new ApiInfoBuilder() - .title("D-Net Organizations Service APIs") - .description("APIs documentation") - .version("1.1") - .contact(ApiInfo.DEFAULT_CONTACT) - .license("Apache 2.0") - .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0") - .build()); + @Bean + public GroupedOpenApi publicApi() { + return GroupedOpenApi.builder() + .group("D-Net Organizations Service APIs") + .pathsToMatch("/api/**", "/oa_api/**") + .build(); } + @Override + protected String swaggerTitle() { + return "D-Net Organizations Service APIs"; + } } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/MockSecurityConfig.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/MockSecurityConfig.java index dccbd71b..4e5a34e1 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/MockSecurityConfig.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/MockSecurityConfig.java @@ -21,6 +21,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.access.AccessDeniedHandler; import eu.dnetlib.organizations.controller.UserInfo; +import eu.dnetlib.organizations.controller.UserRole; import eu.dnetlib.organizations.utils.OpenOrgsConstants; @Profile("dev") @@ -92,7 +93,7 @@ public class MockSecurityConfig extends WebSecurityConfigurerAdapter { .usersByUsernameQuery("select ?, '{MD5}" + DigestUtils.md5Hex(DEFAULT_PASSWORD) + "', true") .authoritiesByUsernameQuery("with const as (SELECT ? as email) " + "select c.email, 'ROLE_" + OpenOrgsConstants.OPENORGS_ROLE_PREFIX + "'||coalesce(u.role, '" - + OpenOrgsConstants.NOT_AUTORIZED_ROLE + + UserRole.NOT_AUTHORIZED + "') from const c left outer join users u on (u.email = c.email)"); } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/OAuth2WebSecurityConfig.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/OAuth2WebSecurityConfig.java index 2ff636dc..c34e4c43 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/OAuth2WebSecurityConfig.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/OAuth2WebSecurityConfig.java @@ -1,6 +1,7 @@ package eu.dnetlib.organizations; import java.util.HashSet; +import java.util.Optional; import java.util.Set; import org.apache.commons.lang3.StringUtils; @@ -49,7 +50,7 @@ public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter { @Value("${openaire.override.logout.url}") private String openaireLogoutUrl; - private static Logger logger = LoggerFactory.getLogger(OAuth2WebSecurityConfig.class); + private static Logger log = LoggerFactory.getLogger(OAuth2WebSecurityConfig.class); @Override protected void configure(final HttpSecurity http) throws Exception { @@ -85,7 +86,7 @@ public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter { return (req, res, e) -> { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null) { - logger.warn(String + log.warn(String .format("User '%s' (%s) attempted to access the protected URL: %s", UserInfo.getEmail(authentication), req .getRemoteAddr(), req.getRequestURI())); } @@ -107,10 +108,10 @@ public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter { handler.setPostLogoutRedirectUri("{baseUrl}"); handler.setRedirectStrategy((req, res, url) -> { if (StringUtils.isNotBlank(openaireLogoutUrl)) { - logger.info("Performing remote logout: " + openaireLogoutUrl); + log.info("Performing remote logout: " + openaireLogoutUrl); res.sendRedirect(openaireLogoutUrl); } else { - logger.info("Performing remote logout: " + url); + log.info("Performing remote logout: " + url); res.sendRedirect(url); } }); @@ -124,7 +125,18 @@ public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter { return (userRequest) -> { final OidcUser oidcUser = delegate.loadUser(userRequest); - final String role = "ROLE_" + OpenOrgsConstants.OPENORGS_ROLE_PREFIX + databaseUtils.findUser(oidcUser.getEmail()) + log.debug("User attributes:"); + oidcUser.getAttributes().forEach((k, v) -> { + log.debug(" - " + k + ": " + v); + }); + + final Optional user = databaseUtils.findUser(UserInfo.getEmail(oidcUser)); + + if (user.isPresent()) { + databaseUtils.updateUserDetails(UserInfo.getEmail(oidcUser), UserInfo.getFullname(oidcUser), UserInfo.getOrganization(oidcUser)); + } + + final String role = "ROLE_" + OpenOrgsConstants.OPENORGS_ROLE_PREFIX + user .map(User::getRole) .filter(StringUtils::isNotBlank) .orElse(UserRole.NOT_AUTHORIZED.toString()); @@ -136,17 +148,4 @@ public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter { }; } - // https://www.baeldung.com/spring-security-openid-connect - - // https://github.com/mitreid-connect/ - // https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/tree/master/openid-connect-client - // https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/wiki/Client-configuration - - // https://svn.driver.research-infrastructures.eu/driver/dnet45/modules/uoa-login-core/trunk/ - // https://svn.driver.research-infrastructures.eu/driver/dnet45/modules/uoa-user-management/trunk/ - // https://svn.driver.research-infrastructures.eu/driver/dnet45/modules/dnet-openaire-users/trunk/ - // https://svn.driver.research-infrastructures.eu/driver/dnet45/modules/dnet-login/trunk/ - - // Aprire Ticket a GRNET con Argiro e Katerina come watchers - } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/AdminController.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/AdminController.java index fd59c98a..943ceadf 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/AdminController.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/AdminController.java @@ -22,11 +22,13 @@ import eu.dnetlib.organizations.importer.ImportExecution; import eu.dnetlib.organizations.importer.ImportExecutor; import eu.dnetlib.organizations.model.SystemConfiguration; import eu.dnetlib.organizations.model.utils.VocabularyTerm; +import eu.dnetlib.organizations.model.view.PersistentOrganizationView; import eu.dnetlib.organizations.model.view.UserView; import eu.dnetlib.organizations.repository.SystemConfigurationRepository; import eu.dnetlib.organizations.repository.UserRepository; import eu.dnetlib.organizations.repository.readonly.UserViewRepository; import eu.dnetlib.organizations.utils.DatabaseUtils; +import eu.dnetlib.organizations.utils.MailDispatcher; @RestController public class AdminController extends AbstractDnetController { @@ -46,17 +48,26 @@ public class AdminController extends AbstractDnetController { @Autowired private DatabaseUtils dbUtils; + @Autowired + private MailDispatcher mailDispatcher; + @PostMapping(value = "/registration_api/newUser") - public Map newUser(final @RequestBody List countries, final Authentication authentication) { + public Map newUser(final @RequestBody UserRegistration user, final Authentication authentication) { final String email = UserInfo.getEmail(authentication); + final String fullname = UserInfo.getFullname(authentication); + final String organization = UserInfo.getOrganization(authentication); final Map res = new HashMap<>(); if (!UserInfo.isNotAuthorized(authentication) || userRepository.existsById(email)) { res.put("status", 2); } else { - dbUtils.newUser(email, countries); + dbUtils.newUser(email, fullname, organization, user.getReferencePerson(), user.getRequestMessage(), user.getCountries()); + + final UserView savedUser = userViewRepository.findById(email).get(); + mailDispatcher.sendRequestRegistrationMail(savedUser); + res.put("status", 1); } return res; @@ -87,9 +98,18 @@ public class AdminController extends AbstractDnetController { } @PostMapping("/api/users") - public Iterable saveUser(@RequestBody final UserView userView, final Authentication authentication) { + public Iterable updateUser(@RequestBody final UserView userView, final Authentication authentication) { if (UserInfo.getEmail(authentication).equals(userView.getEmail())) { throw new RuntimeException("You can't edit your own user"); } - dbUtils.saveUser(userView); + + dbUtils.updateUser(userView); + + if (userView.getRole().equals(UserRole.USER.toString()) || + userView.getRole().equals(UserRole.NATIONAL_ADMIN.toString()) || + userView.getRole().equals(UserRole.ADMIN.toString())) { + + mailDispatcher.sendUpdatedUserMail(userView); + } + return users(authentication); } @@ -122,7 +142,9 @@ public class AdminController extends AbstractDnetController { public SystemConfiguration saveSysConf(@RequestBody final SystemConfiguration sysConf, final Authentication authentication) { if (UserInfo.isSuperAdmin(authentication)) { sysConf.setId(SystemConfiguration.DEFAULT_ID); - return systemConfigurationRepository.save(sysConf); + systemConfigurationRepository.save(sysConf); + mailDispatcher.configure(sysConf); + return sysConf; } else { throw new RuntimeException("User not authorized"); } @@ -181,4 +203,22 @@ public class AdminController extends AbstractDnetController { throw new RuntimeException("User not authorized"); } } + + @GetMapping("/api/persistentOrgs") + public Iterable listPersistentOrgs() { + return dbUtils.listPersistentOrgs(); + } + + @PostMapping("/api/persistentOrgs") + public Iterable addPersistentOrgs(@RequestBody final List ids) { + ids.forEach(id -> dbUtils.addPersistentOrgs(id)); + return dbUtils.listPersistentOrgs(); + } + + @DeleteMapping("/api/persistentOrgs") + public Iterable deletePersistentOrgs(@RequestParam final String id) { + dbUtils.deletePersistentOrgs(id); + return dbUtils.listPersistentOrgs(); + } + } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/HomeController.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/HomeController.java index 1ea46874..7d76fb8d 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/HomeController.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/HomeController.java @@ -11,6 +11,7 @@ import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; @@ -30,6 +31,9 @@ public class HomeController extends AbstractDnetController { @Autowired private SystemConfigurationRepository systemConfigurationRepository; + @Value("${openaire.explore.organization.baseurl}") + private String openaireBaseUrl; + @Value("${openorgs.support.pages}") private String supportPagesJson; @@ -40,6 +44,11 @@ public class HomeController extends AbstractDnetController { return env.acceptsProfiles(Profiles.of("dev")) ? "redirect:main" : "home"; } + @GetMapping("/redirect/oa/{orgId}") + public String openaireUrl(@PathVariable final String orgId) { + return "redirect:" + String.format(openaireBaseUrl, orgId); + } + @GetMapping("/main") public String main() { return "main"; @@ -65,6 +74,21 @@ public class HomeController extends AbstractDnetController { return authentication != null ? UserInfo.getEmail(authentication) : null; } + @ModelAttribute("role") + public UserRole getUserRole(final Authentication authentication) { + return authentication != null ? UserInfo.findRole(authentication) : null; + } + + @ModelAttribute("fullname") + public String getUserFullname(final Authentication authentication) { + return authentication != null ? UserInfo.getFullname(authentication) : "unknown"; + } + + @ModelAttribute("organization") + public String getUserOrganization(final Authentication authentication) { + return authentication != null ? UserInfo.getOrganization(authentication) : "unknown"; + } + @ModelAttribute("sysconf") public SystemConfiguration getSysConf(final Authentication authentication) { return systemConfigurationRepository.findById(SystemConfiguration.DEFAULT_ID).get(); @@ -81,10 +105,10 @@ public class HomeController extends AbstractDnetController { } @GetMapping({ - "/doc", "/swagger" + "apidoc", "api-doc", "/doc", "/swagger" }) public String apiDoc() { - return "redirect:swagger-ui/"; + return "redirect:swagger-ui/index.html"; } } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java index 9ecd3cca..eb706c5f 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/OrganizationController.java @@ -17,7 +17,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.security.core.Authentication; @@ -83,8 +82,6 @@ public class OrganizationController extends AbstractDnetController { private JournalEntryRepository journalEntryRepository; @Autowired private DatabaseUtils databaseUtils; - @Value("${openaire.explore.organization.baseurl}") - private String oaBaseUrl; @PostMapping("/save") public List save(@RequestBody final OrganizationView org, final Authentication authentication) { @@ -107,9 +104,7 @@ public class OrganizationController extends AbstractDnetController { @GetMapping("/info") public OrganizationInfoView infoById(@RequestParam final String id, final Authentication authentication) { - final OrganizationInfoView info = organizationInfoViewRepository.findById(id).get(); - info.fillGraphNodeInfo(info.getId(), oaBaseUrl); - return info; + return organizationInfoViewRepository.findById(id).get(); } @GetMapping("/suggestionsInfo") @@ -160,9 +155,7 @@ public class OrganizationController extends AbstractDnetController { } private List listDuplicates(final String id) { - final List list = openaireDuplicateViewRepository.findByLocalId(id); - list.forEach(d -> d.fillGraphNodeInfo(d.getOaOriginalId(), oaBaseUrl)); - return list; + return openaireDuplicateViewRepository.findByLocalId(id); } @GetMapping("/conflicts/byCountry/{country}") diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/UserInfo.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/UserInfo.java index cfa32586..f05114a1 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/UserInfo.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/UserInfo.java @@ -5,6 +5,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; public class UserInfo { @@ -42,6 +43,7 @@ public class UserInfo { } public static UserRole findRole(final Authentication authentication) { + return authentication.getAuthorities() .stream() .map(GrantedAuthority::getAuthority) @@ -89,7 +91,29 @@ public class UserInfo { public static String getEmail(final Authentication authentication) { final Object user = authentication.getPrincipal(); - return user instanceof DefaultOidcUser ? ((DefaultOidcUser) user).getEmail() : authentication.getName(); + return user instanceof DefaultOidcUser ? getEmail((DefaultOidcUser) user) : authentication.getName(); + } + + public static String getEmail(final OidcUser user) { + return user.getEmail(); + } + + public static String getFullname(final Authentication authentication) { + final Object user = authentication.getPrincipal(); + return user instanceof DefaultOidcUser ? getFullname((DefaultOidcUser) user) : "unknown"; + } + + public static String getFullname(final OidcUser user) { + return user.getFullName(); + } + + public static String getOrganization(final Authentication authentication) { + final Object user = authentication.getPrincipal(); + return user instanceof DefaultOidcUser ? getOrganization((DefaultOidcUser) user) : "unknown"; + } + + public static String getOrganization(final OidcUser user) { + return StringUtils.firstNonBlank(user.getAttribute("organization"), user.getAttribute("affiliation")); } } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/UserRegistration.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/UserRegistration.java new file mode 100644 index 00000000..3c40d31e --- /dev/null +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/controller/UserRegistration.java @@ -0,0 +1,40 @@ +package eu.dnetlib.organizations.controller; + +import java.io.Serializable; +import java.util.List; + +public class UserRegistration implements Serializable { + + private static final long serialVersionUID = 4872798305803491565L; + + private String referencePerson; + + private String requestMessage; + + private List countries; + + public String getReferencePerson() { + return referencePerson; + } + + public void setReferencePerson(final String referencePerson) { + this.referencePerson = referencePerson; + } + + public String getRequestMessage() { + return requestMessage; + } + + public void setRequestMessage(final String requestMessage) { + this.requestMessage = requestMessage; + } + + public List getCountries() { + return countries; + } + + public void setCountries(final List countries) { + this.countries = countries; + } + +} diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/PersistentOrganization.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/PersistentOrganization.java new file mode 100644 index 00000000..b01ea8a1 --- /dev/null +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/PersistentOrganization.java @@ -0,0 +1,34 @@ +package eu.dnetlib.organizations.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "persistent_orgs") +public class PersistentOrganization implements Serializable { + + private static final long serialVersionUID = 7684478315366015099L; + + @Id + @Column(name = "id") + private String id; + + public PersistentOrganization() {} + + public PersistentOrganization(final String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setId(final String id) { + this.id = id; + } + +} diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/SystemConfiguration.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/SystemConfiguration.java index a662ea17..e778bc27 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/SystemConfiguration.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/SystemConfiguration.java @@ -31,14 +31,35 @@ public class SystemConfiguration implements Serializable { @Column(name = "readonly") private Boolean readonly; - public SystemConfiguration() {} + @Column(name = "smtp_enabled") + private Boolean smtpEnabled; - public SystemConfiguration(final String id, final String title, final String homepageMessage, final Boolean readonly) { - this.id = id; - this.title = title; - this.homepageMessage = homepageMessage; - this.readonly = readonly; - } + @Column(name = "smtp_host") + private String smtpHost; + + @Column(name = "smtp_port") + private Integer smtpPort; + + @Column(name = "smtp_user") + private String smtpUser; + + @Column(name = "smtp_password") + private String smtpPassword; + + @Column(name = "smtp_from_mail") + private String smtpFromMail; + + @Column(name = "smtp_from_name") + private String smtpFromName; + + @Column(name = "smtp_to_mail_admin") + private String smtpToMailAdmin; + + @Column(name = "smtp_new_user_message") + private String smtpNewUserMessage; + + @Column(name = "smtp_update_user_message") + private String smtpUpdateUserMessage; public String getId() { return id; @@ -72,4 +93,84 @@ public class SystemConfiguration implements Serializable { this.readonly = readonly; } + public Boolean getSmtpEnabled() { + return smtpEnabled; + } + + public void setSmtpEnabled(final Boolean smtpEnabled) { + this.smtpEnabled = smtpEnabled; + } + + public String getSmtpHost() { + return smtpHost; + } + + public void setSmtpHost(final String smtpHost) { + this.smtpHost = smtpHost; + } + + public Integer getSmtpPort() { + return smtpPort; + } + + public void setSmtpPort(final Integer smtpPort) { + this.smtpPort = smtpPort; + } + + public String getSmtpUser() { + return smtpUser; + } + + public void setSmtpUser(final String smtpUser) { + this.smtpUser = smtpUser; + } + + public String getSmtpPassword() { + return smtpPassword; + } + + public void setSmtpPassword(final String smtpPassword) { + this.smtpPassword = smtpPassword; + } + + public String getSmtpFromMail() { + return smtpFromMail; + } + + public void setSmtpFromMail(final String smtpFromMail) { + this.smtpFromMail = smtpFromMail; + } + + public String getSmtpFromName() { + return smtpFromName; + } + + public void setSmtpFromName(final String smtpFromName) { + this.smtpFromName = smtpFromName; + } + + public String getSmtpToMailAdmin() { + return smtpToMailAdmin; + } + + public void setSmtpToMailAdmin(final String smtpToMailAdmin) { + this.smtpToMailAdmin = smtpToMailAdmin; + } + + public String getSmtpNewUserMessage() { + return smtpNewUserMessage; + } + + public void setSmtpNewUserMessage(final String smtpNewUserMessage) { + this.smtpNewUserMessage = smtpNewUserMessage; + } + + public String getSmtpUpdateUserMessage() { + return smtpUpdateUserMessage; + } + + public void setSmtpUpdateUserMessage(final String smtpUpdateUserMessage) { + this.smtpUpdateUserMessage = smtpUpdateUserMessage; + } + } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/User.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/User.java index 8a6408bd..c09a39f7 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/User.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/User.java @@ -20,6 +20,18 @@ public class User implements Serializable { @Column(name = "email") private String email; + @Column(name = "fullname") + private String fullname; + + @Column(name = "organization") + private String organization; + + @Column(name = "reference_person") + private String referencePerson; + + @Column(name = "request_message") + private String requestMessage; + @Column(name = "valid") private boolean valid; @@ -34,6 +46,38 @@ public class User implements Serializable { this.email = email; } + public String getFullname() { + return fullname; + } + + public void setFullname(final String fullname) { + this.fullname = fullname; + } + + public String getOrganization() { + return organization; + } + + public void setOrganization(final String organization) { + this.organization = organization; + } + + public String getReferencePerson() { + return referencePerson; + } + + public void setReferencePerson(final String referencePerson) { + this.referencePerson = referencePerson; + } + + public String getRequestMessage() { + return requestMessage; + } + + public void setRequestMessage(final String requestMessage) { + this.requestMessage = requestMessage; + } + public boolean isValid() { return valid; } @@ -49,5 +93,4 @@ public class User implements Serializable { public void setRole(final String role) { this.role = role; } - } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/utils/OpenaireGraphNode.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/utils/OpenaireGraphNode.java index 6867942b..1b34ab01 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/utils/OpenaireGraphNode.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/utils/OpenaireGraphNode.java @@ -1,23 +1,31 @@ package eu.dnetlib.organizations.model.utils; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang3.StringUtils; +import javax.persistence.Column; +import javax.persistence.MappedSuperclass; -public interface OpenaireGraphNode { +@MappedSuperclass +public abstract class OpenaireGraphNode { - String getOaGraphId(); + @Column(name = "openaire_id") + private String openaireId; - void setOaGraphId(String oaGraphId); + @Column(name = "openaire_persistent") + private Boolean persistent = false; - String getOaGraphUrl(); + public String getOpenaireId() { + return openaireId; + } - void setOaGraphUrl(String oaGraphUrl); + public void setOpenaireId(final String openaireId) { + this.openaireId = openaireId; + } - default void fillGraphNodeInfo(final String origId, final String baseUrl) { - final String oaGraphId = StringUtils.substringBefore(origId, "::") + "::" - + DigestUtils.md5Hex(StringUtils.substringAfter(origId, "::")); - setOaGraphId(oaGraphId); - setOaGraphUrl(baseUrl + oaGraphId); + public Boolean getPersistent() { + return persistent; + } + + public void setPersistent(final Boolean persistent) { + this.persistent = persistent; } } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OpenaireDuplicateView.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OpenaireDuplicateView.java index 2a02ed35..9cfba1a3 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OpenaireDuplicateView.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OpenaireDuplicateView.java @@ -8,7 +8,6 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; -import javax.persistence.Transient; import org.hibernate.annotations.Type; @@ -18,7 +17,7 @@ import eu.dnetlib.organizations.model.utils.OpenaireGraphNode; @Entity @Table(name = "oa_duplicates_view") @IdClass(OpenaireDuplicatePK.class) -public class OpenaireDuplicateView implements Serializable, OpenaireGraphNode { +public class OpenaireDuplicateView extends OpenaireGraphNode implements Serializable { /** * @@ -88,12 +87,6 @@ public class OpenaireDuplicateView implements Serializable, OpenaireGraphNode { @Column(name = "ec_nutscode") private Boolean ecNutscode; - @Transient - private String oaGraphId; - - @Transient - private String oaGraphUrl; - public String getLocalId() { return localId; } @@ -254,24 +247,4 @@ public class OpenaireDuplicateView implements Serializable, OpenaireGraphNode { this.ecNutscode = ecNutscode; } - @Override - public String getOaGraphId() { - return oaGraphId; - } - - @Override - public void setOaGraphId(final String oaGraphId) { - this.oaGraphId = oaGraphId; - } - - @Override - public String getOaGraphUrl() { - return oaGraphUrl; - } - - @Override - public void setOaGraphUrl(final String oaGraphUrl) { - this.oaGraphUrl = oaGraphUrl; - } - } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OrganizationInfoView.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OrganizationInfoView.java index 7109d8a1..3ca41df6 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OrganizationInfoView.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OrganizationInfoView.java @@ -7,13 +7,12 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; -import javax.persistence.Transient; import eu.dnetlib.organizations.model.utils.OpenaireGraphNode; @Entity @Table(name = "organizations_info_view") -public class OrganizationInfoView implements Serializable, OpenaireGraphNode { +public class OrganizationInfoView extends OpenaireGraphNode implements Serializable { /** * @@ -48,12 +47,6 @@ public class OrganizationInfoView implements Serializable, OpenaireGraphNode { @Column(name = "note") private boolean note; - @Transient - private String oaGraphId; - - @Transient - private String oaGraphUrl; - public String getId() { return id; } @@ -126,24 +119,4 @@ public class OrganizationInfoView implements Serializable, OpenaireGraphNode { this.note = note; } - @Override - public String getOaGraphId() { - return oaGraphId; - } - - @Override - public void setOaGraphId(final String oaGraphId) { - this.oaGraphId = oaGraphId; - } - - @Override - public String getOaGraphUrl() { - return oaGraphUrl; - } - - @Override - public void setOaGraphUrl(final String oaGraphUrl) { - this.oaGraphUrl = oaGraphUrl; - } - } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OrganizationView.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OrganizationView.java index 06d92519..cdf41c94 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OrganizationView.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/OrganizationView.java @@ -15,13 +15,15 @@ import org.hibernate.annotations.TypeDefs; import com.vladmihalcea.hibernate.type.json.JsonBinaryType; import com.vladmihalcea.hibernate.type.json.JsonStringType; +import eu.dnetlib.organizations.model.utils.OpenaireGraphNode; + @Entity @Table(name = "organizations_view") @TypeDefs({ @TypeDef(name = "json", typeClass = JsonStringType.class), @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) }) -public class OrganizationView implements Serializable { +public class OrganizationView extends OpenaireGraphNode implements Serializable { /** * diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/PersistentOrganizationView.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/PersistentOrganizationView.java new file mode 100644 index 00000000..872fa06a --- /dev/null +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/PersistentOrganizationView.java @@ -0,0 +1,63 @@ +package eu.dnetlib.organizations.model.view; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +import eu.dnetlib.organizations.model.utils.OpenaireGraphNode; + +@Entity +@Table(name = "persistent_orgs_view") +public class PersistentOrganizationView extends OpenaireGraphNode implements Serializable { + + private static final long serialVersionUID = -8906936709574708538L; + + @Id + @Column(name = "id") + private String id; + + @Column(name = "name") + private String name; + + @Column(name = "city") + private String city; + + @Column(name = "country") + private String country; + + public String getId() { + return id; + } + + public void setId(final String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getCity() { + return city; + } + + public void setCity(final String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(final String country) { + this.country = country; + } + +} diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/UserView.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/UserView.java index e09b4da8..bfc3d6f0 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/UserView.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/model/view/UserView.java @@ -30,6 +30,18 @@ public class UserView implements Serializable { @Column(name = "email") private String email; + @Column(name = "fullname") + private String fullname; + + @Column(name = "organization") + private String organization; + + @Column(name = "reference_person") + private String referencePerson; + + @Column(name = "request_message") + private String requestMessage; + @Column(name = "valid") private boolean valid; @@ -93,4 +105,36 @@ public class UserView implements Serializable { public void setLastAccess(final OffsetDateTime lastAccess) { this.lastAccess = lastAccess; } + + public String getFullname() { + return fullname; + } + + public void setFullname(final String fullname) { + this.fullname = fullname; + } + + public String getOrganization() { + return organization; + } + + public void setOrganization(final String organization) { + this.organization = organization; + } + + public String getReferencePerson() { + return referencePerson; + } + + public void setReferencePerson(final String referencePerson) { + this.referencePerson = referencePerson; + } + + public String getRequestMessage() { + return requestMessage; + } + + public void setRequestMessage(final String requestMessage) { + this.requestMessage = requestMessage; + } } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/OrganizationRepository.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/OrganizationRepository.java index 6071b0d4..30301239 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/OrganizationRepository.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/OrganizationRepository.java @@ -22,9 +22,10 @@ public interface OrganizationRepository extends JpaRepository { + +} diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/UserRepository.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/UserRepository.java index 0d2da87e..6fd5be93 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/UserRepository.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/UserRepository.java @@ -11,7 +11,7 @@ import eu.dnetlib.organizations.model.User; public interface UserRepository extends JpaRepository { @Modifying - @Query("update User set last_access = ?2 where email = ?1") - void updateLastAccess(final String email, OffsetDateTime now); + @Query("update User set fullname = ?2, organization = ?3, last_access = ?4 where email = ?1") + void updateDetails(final String email, final String fullname, final String organization, OffsetDateTime now); } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/readonly/OrganizationViewRepository.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/readonly/OrganizationViewRepository.java index 2ea10b64..5af6cdb9 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/readonly/OrganizationViewRepository.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/readonly/OrganizationViewRepository.java @@ -1,5 +1,7 @@ package eu.dnetlib.organizations.repository.readonly; +import java.util.Optional; + import org.springframework.stereotype.Repository; import eu.dnetlib.organizations.model.view.OrganizationView; @@ -7,4 +9,5 @@ import eu.dnetlib.organizations.model.view.OrganizationView; @Repository public interface OrganizationViewRepository extends ReadOnlyRepository { + Optional findByOpenaireId(String openaireId); } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/readonly/PersistentOrganizationViewRepository.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/readonly/PersistentOrganizationViewRepository.java new file mode 100644 index 00000000..c53dd904 --- /dev/null +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/repository/readonly/PersistentOrganizationViewRepository.java @@ -0,0 +1,10 @@ +package eu.dnetlib.organizations.repository.readonly; + +import org.springframework.stereotype.Repository; + +import eu.dnetlib.organizations.model.view.PersistentOrganizationView; + +@Repository +public interface PersistentOrganizationViewRepository extends ReadOnlyRepository { + +} diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/DatabaseUtils.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/DatabaseUtils.java index 77399cd8..e58add34 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/DatabaseUtils.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/DatabaseUtils.java @@ -12,10 +12,12 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; import javax.transaction.Transactional; +import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; @@ -37,6 +39,7 @@ import eu.dnetlib.organizations.model.OpenaireDuplicate; import eu.dnetlib.organizations.model.Organization; import eu.dnetlib.organizations.model.OtherIdentifier; import eu.dnetlib.organizations.model.OtherName; +import eu.dnetlib.organizations.model.PersistentOrganization; import eu.dnetlib.organizations.model.Relationship; import eu.dnetlib.organizations.model.Url; import eu.dnetlib.organizations.model.User; @@ -46,6 +49,7 @@ import eu.dnetlib.organizations.model.utils.OrganizationConflict; import eu.dnetlib.organizations.model.utils.TempBrowseEntry; import eu.dnetlib.organizations.model.utils.VocabularyTerm; import eu.dnetlib.organizations.model.view.OrganizationView; +import eu.dnetlib.organizations.model.view.PersistentOrganizationView; import eu.dnetlib.organizations.model.view.UserView; import eu.dnetlib.organizations.repository.AcronymRepository; import eu.dnetlib.organizations.repository.JournalEntryRepository; @@ -54,11 +58,13 @@ import eu.dnetlib.organizations.repository.OpenaireDuplicateRepository; import eu.dnetlib.organizations.repository.OrganizationRepository; import eu.dnetlib.organizations.repository.OtherIdentifierRepository; import eu.dnetlib.organizations.repository.OtherNameRepository; +import eu.dnetlib.organizations.repository.PersistentOrganizationRepository; import eu.dnetlib.organizations.repository.RelationshipRepository; import eu.dnetlib.organizations.repository.UrlRepository; import eu.dnetlib.organizations.repository.UserCountryRepository; import eu.dnetlib.organizations.repository.UserRepository; import eu.dnetlib.organizations.repository.readonly.OrganizationViewRepository; +import eu.dnetlib.organizations.repository.readonly.PersistentOrganizationViewRepository; @Component public class DatabaseUtils { @@ -87,6 +93,10 @@ public class DatabaseUtils { private OrganizationViewRepository organizationViewRepository; @Autowired private JournalEntryRepository journalEntryRepository; + @Autowired + private PersistentOrganizationRepository persistentOrganizationRepository; + @Autowired + private PersistentOrganizationViewRepository persistentOrganizationViewRepository; @Autowired private JdbcTemplate jdbcTemplate; @@ -129,7 +139,7 @@ public class DatabaseUtils { final String pendingId = OpenOrgsConstants.OPENORGS_PENDING_PREFIX + UUID.randomUUID(); orgView.setId(pendingId); // to override the generation strategy of the ID - organizationRepository.preparePendingOrg(pendingId); + organizationRepository.prepareOrgWithId(pendingId); } else { orgView.setId(null); // The ID is generated by the DB } @@ -337,8 +347,12 @@ public class DatabaseUtils { } @Transactional - public void saveUser(@RequestBody final UserView userView) { + public void updateUser(@RequestBody final UserView userView) { final User user = userRepository.findById(userView.getEmail()).orElseThrow(() -> new RuntimeException("User not found")); + user.setFullname(userView.getFullname()); + user.setOrganization(userView.getOrganization()); + user.setReferencePerson(userView.getReferencePerson()); + user.setRequestMessage(userView.getRequestMessage()); user.setRole(userView.getRole()); user.setValid(userView.isValid()); userRepository.save(user); @@ -356,12 +370,24 @@ public class DatabaseUtils { } @Transactional - public void newUser(final String email, final List countries) { + public void newUser(final String email, + final String fullname, + final String organization, + final String referencePerson, + final String requestMessage, + final List countries) { + final User user = new User(); user.setEmail(email); + user.setFullname(fullname); + user.setOrganization(organization); + user.setReferencePerson(referencePerson); + user.setRequestMessage(requestMessage); user.setRole(UserRole.PENDING.name()); user.setValid(false); + userRepository.save(user); + if (countries != null) { userCountryRepository.saveAll(countries.stream().map(c -> new UserCountry(email, c)).collect(Collectors.toList())); } @@ -452,45 +478,97 @@ public class DatabaseUtils { @Transactional public String fixConflictSimilars(final List similarIds, final String user) { - final OffsetDateTime now = OffsetDateTime.now(); - final List views = similarIds.stream().map(organizationViewRepository::findById).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); - // I create a new org - final OrganizationView newOrg = new OrganizationView(); - newOrg.setId(null); - newOrg.setStatus(null); - newOrg.setName(findFirstString(views, OrganizationView::getName)); - newOrg.setType(findFirstString(views, OrganizationView::getType)); - newOrg.setLat(findFirstNumber(views, OrganizationView::getLat)); - newOrg.setLng(findFirstNumber(views, OrganizationView::getLng)); - newOrg.setCity(findFirstString(views, OrganizationView::getCity)); - newOrg.setCountry(findFirstString(views, OrganizationView::getCountry)); - newOrg.setOtherIdentifiers(findAll(views, OrganizationView::getOtherIdentifiers)); - newOrg.setOtherNames(findAll(views, OrganizationView::getOtherNames)); - newOrg.setAcronyms(findAll(views, OrganizationView::getAcronyms)); - newOrg.setUrls(findAll(views, OrganizationView::getUrls)); - newOrg.setRelations(findAll(views, OrganizationView::getRelations)); + final List persistents = views.stream().filter(v -> v.getPersistent()).collect(Collectors.toList()); - newOrg.getOtherNames() - .addAll(views.stream() + final OrganizationView masterOrg = new OrganizationView(); + + if (persistents.size() > 1) { + throw new RuntimeException("Too many persintent organizations"); + } else if (persistents.size() == 1) { + backupOrg(persistents.get(0), user); + masterOrg.setId(persistents.get(0).getId()); + masterOrg.setStatus(OrganizationStatus.approved.toString()); + } else { + masterOrg.setId(null); + masterOrg.setStatus(null); + } + return fixConflicts(masterOrg, views, user); + } + + private String backupOrg(final OrganizationView org, final String user) { + final String origId = org.getId(); + final String backupId = origId + "::" + OffsetDateTime.now().toEpochSecond(); + + organizationRepository.prepareOrgWithId(backupId); + try { + + final OrganizationView backupOrg = (OrganizationView) BeanUtils.cloneBean(org); + backupOrg.setId(backupId); + + insertOrUpdateOrganization(backupOrg, user, false); + + organizationRepository.updateStatus(backupId, OrganizationStatus.hidden.toString()); + + journalEntryRepository + .save(new JournalEntry(origId, JournalOperations.BACKUP_ORG, "Saved a backup copy: " + backupId, user)); + journalEntryRepository + .save(new JournalEntry(backupId, JournalOperations.BACKUP_ORG, "Saved a backup copy of " + origId, user)); + + return backupId; + } catch (final Exception e) { + log.error("Error performing the backup of " + origId, e); + throw new RuntimeException("Error performing the backup of " + origId, e); + } + } + + private String fixConflicts(final OrganizationView masterOrg, final List orgs, final String user) { + + final OffsetDateTime now = OffsetDateTime.now(); + + final String finalMessage = (masterOrg.getId() == null ? "New org created merging: " : "Merging in persistent org: ") + + orgs.stream() + .map(OrganizationView::getId) + .collect(Collectors.joining(", ")); + + masterOrg.setName(findFirstString(orgs, OrganizationView::getName)); + masterOrg.setType(findFirstString(orgs, OrganizationView::getType)); + masterOrg.setLat(findFirstNumber(orgs, OrganizationView::getLat)); + masterOrg.setLng(findFirstNumber(orgs, OrganizationView::getLng)); + masterOrg.setCity(findFirstString(orgs, OrganizationView::getCity)); + masterOrg.setCountry(findFirstString(orgs, OrganizationView::getCountry)); + masterOrg.setOtherIdentifiers(findAll(orgs, OrganizationView::getOtherIdentifiers)); + masterOrg.setOtherNames(findAll(orgs, OrganizationView::getOtherNames)); + masterOrg.setAcronyms(findAll(orgs, OrganizationView::getAcronyms)); + masterOrg.setUrls(findAll(orgs, OrganizationView::getUrls)); + masterOrg.setRelations(findAll(orgs, OrganizationView::getRelations, r -> !r.getType().equals(RelationType.Merged_In.toString()) + && !r.getType().equals(RelationType.Merged_In.toString()))); + + masterOrg.getOtherNames() + .addAll(orgs.stream() .map(OrganizationView::getName) .filter(StringUtils::isNotBlank) - .filter(s -> StringUtils.equalsIgnoreCase(s, newOrg.getName())) + .filter(s -> StringUtils.equalsIgnoreCase(s, masterOrg.getName())) .map(s -> new eu.dnetlib.organizations.model.view.OtherName(s, "UNKNOWN")) .collect(Collectors.toList())); - final String masterId = insertOrUpdateOrganization(newOrg, user, false); + final String masterId = insertOrUpdateOrganization(masterOrg, user, false); // I hide the merged organizations - similarIds.forEach(id -> { - hideConflictOrgs(masterId, id); - journalEntryRepository.save(new JournalEntry(masterId, JournalOperations.FIX_CONFLICT, "The org has been hidded and merged in " + masterId, user)); - }); + orgs.stream() + .map(OrganizationView::getId) + .filter(id -> !id.equals(masterId)) + .forEach(id -> { + hideConflictOrgs(masterId, id); + journalEntryRepository + .save(new JournalEntry(id, JournalOperations.FIX_CONFLICT, "The org has been hidded and merged in " + masterId, user)); + }); // I reassign the duplicates to the new org - final List newDuplicates = similarIds.stream() + final List newDuplicates = orgs.stream() + .map(OrganizationView::getId) .map(openaireDuplicateRepository::findByLocalId) .flatMap(l -> l.stream()) .map(d -> new OpenaireDuplicate(masterId, d.getOaOriginalId(), d.getRelType(), d.getOaCollectedFrom())) @@ -502,18 +580,20 @@ public class DatabaseUtils { openaireDuplicateRepository.updateModificationDate(d.getLocalId(), d.getOaOriginalId(), user, now); }); - for (final String similarId : similarIds) { + orgs.forEach(org -> { + final String similarId = org.getId(); openaireConflictRepository.updateMultipleStatusAndResetGroup(similarId, SimilarityType.is_different.toString(), user, now); - } + }); - for (int i = 0; i < similarIds.size(); i++) { - for (int j = i + 1; j < similarIds.size(); j++) { - openaireConflictRepository.updateStatusAndResetGroup(similarIds.get(i), similarIds.get(j), SimilarityType.is_similar.toString(), user, now); + for (int i = 0; i < orgs.size(); i++) { + for (int j = i + 1; j < orgs.size(); j++) { + openaireConflictRepository + .updateStatusAndResetGroup(orgs.get(i).getId(), orgs.get(j).getId(), SimilarityType.is_similar.toString(), user, now); } } journalEntryRepository - .save(new JournalEntry(masterId, JournalOperations.FIX_CONFLICT, "New org created merging: " + StringUtils.join(similarIds, ", "), user)); + .save(new JournalEntry(masterId, JournalOperations.FIX_CONFLICT, finalMessage, user)); return masterId; } @@ -536,11 +616,12 @@ public class DatabaseUtils { @Transactional public Optional findUser(final String email) { - final Optional user = userRepository.findById(email); - if (user.isPresent()) { - userRepository.updateLastAccess(email, OffsetDateTime.now()); - } - return user; + return userRepository.findById(email); + } + + @Transactional + public void updateUserDetails(final String email, final String fullname, final String organization) { + userRepository.updateDetails(email, fullname, organization, OffsetDateTime.now()); } private String findFirstString(final List views, final Function mapper) { @@ -555,6 +636,10 @@ public class DatabaseUtils { return views.stream().map(mapper).flatMap(s -> s.stream()).collect(Collectors.toCollection(LinkedHashSet::new)); } + private Set findAll(final List views, final Function> mapper, final Predicate filter) { + return views.stream().map(mapper).flatMap(s -> s.stream()).filter(filter).collect(Collectors.toCollection(LinkedHashSet::new)); + } + private List hideConflictOrgs(final String masterId, final String otherId) { organizationRepository.updateStatus(otherId, OrganizationStatus.hidden.toString()); openaireConflictRepository.findById(new OpenaireConflictPK(masterId, otherId)).ifPresent(openaireConflictRepository::delete); @@ -568,4 +653,39 @@ public class DatabaseUtils { return jdbcTemplate.queryForList(sql, String.class); } + public Iterable listPersistentOrgs() { + return persistentOrganizationViewRepository.findAll(); + } + + public String addPersistentOrgs(final String id) { + + final boolean valid; + final String ooid; + + if (id.length() == 46) { + final Optional orgView = organizationViewRepository.findByOpenaireId(id); + valid = orgView.map(OrganizationView::getStatus) + .filter(s -> s.equals(OrganizationStatus.approved.toString())) + .isPresent(); + ooid = orgView.get().getId(); + } else { + valid = organizationRepository.findById(id) + .map(Organization::getStatus) + .filter(s -> s.equals(OrganizationStatus.approved.toString())) + .isPresent(); + ooid = id; + } + + if (valid) { + persistentOrganizationRepository.save(new PersistentOrganization(ooid)); + return ooid; + } else { + throw new RuntimeException("The ID does not refer to an approved Organization"); + } + } + + public void deletePersistentOrgs(final String id) { + persistentOrganizationRepository.deleteById(id); + } + } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/JournalOperations.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/JournalOperations.java index d2db9715..7bcb1ec7 100644 --- a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/JournalOperations.java +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/JournalOperations.java @@ -9,5 +9,6 @@ public enum JournalOperations { DUPLICATES, FIX_CONFLICT, NO_CONFLICT, + BACKUP_ORG, UNKNOWN } diff --git a/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/MailDispatcher.java b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/MailDispatcher.java new file mode 100644 index 00000000..f79a29bc --- /dev/null +++ b/apps/dnet-orgs-database-application/src/main/java/eu/dnetlib/organizations/utils/MailDispatcher.java @@ -0,0 +1,125 @@ +package eu.dnetlib.organizations.utils; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import eu.dnetlib.common.exceptions.DnetException; +import eu.dnetlib.common.utils.mail.EmailFactory; +import eu.dnetlib.common.utils.mail.EmailMessage; +import eu.dnetlib.organizations.controller.UserRole; +import eu.dnetlib.organizations.model.SystemConfiguration; +import eu.dnetlib.organizations.model.view.UserView; +import eu.dnetlib.organizations.repository.SystemConfigurationRepository; + +@Component +public class MailDispatcher { + + @Autowired + private SystemConfigurationRepository systemConfigurationRepository; + + private final EmailFactory emailFactory = new EmailFactory(); + + private boolean enabled = true; + + private String fromMail; + private String fromName; + private String toMailAdmin; + + private String newUserMessage; + private String updateUserMessage; + + private static final Log log = LogFactory.getLog(MailDispatcher.class); + + @PostConstruct + public void configure() { + final SystemConfiguration conf = systemConfigurationRepository.findById(SystemConfiguration.DEFAULT_ID).get(); + configure(conf); + } + + public void configure(final SystemConfiguration conf) { + this.enabled = conf.getSmtpEnabled(); + this.fromMail = conf.getSmtpFromMail(); + this.fromName = conf.getSmtpFromName(); + this.toMailAdmin = conf.getSmtpToMailAdmin(); + this.newUserMessage = conf.getSmtpNewUserMessage(); + this.updateUserMessage = conf.getSmtpUpdateUserMessage(); + + if (StringUtils.isNotBlank(conf.getSmtpHost())) { + emailFactory.setSmtpHost(conf.getSmtpHost()); + } else { + emailFactory.setSmtpHost("localhost"); + } + if (conf.getSmtpPort() != null) { + emailFactory.setSmtpPort(conf.getSmtpPort()); + } else { + emailFactory.setSmtpPort(587); + } + if (StringUtils.isNotBlank(conf.getSmtpUser())) { + emailFactory.setSmtpUser(conf.getSmtpUser()); + emailFactory.setSmtpPassword(conf.getSmtpPassword()); + } else { + emailFactory.setSmtpUser(null); + emailFactory.setSmtpPassword(null); + } + } + + public void sendRequestRegistrationMail(final UserView user) { + if (StringUtils.isNotBlank(newUserMessage)) { + final String message = prepareMessage(this.newUserMessage, user); + + for (final String to : StringUtils.split(toMailAdmin, ",")) { + sendMail("OpenOrgs: new registration request", message, to.trim()); + } + } else { + log.warn("Template is empty (newUserMessage)"); + } + } + + public void sendUpdatedUserMail(final UserView user) { + if (StringUtils.isNotBlank(updateUserMessage)) { + final String message = prepareMessage(this.updateUserMessage, user); + sendMail("OpenOrgs: user updated", message, user.getEmail()); + } else { + log.warn("Template is empty (updateUserMessage)"); + } + } + + private String prepareMessage(final String template, final UserView user) { + final String countries = user.getRole().equals(UserRole.ADMIN.toString()) ? "All" : StringUtils.join(user.getCountries(), ", "); + + return template.replaceAll(":email:", user.getEmail()) + .replaceAll(":fullname:", user.getFullname()) + .replaceAll(":organization:", user.getOrganization()) + .replaceAll(":refperson:", user.getReferencePerson()) + .replaceAll(":reqmessage:", user.getRequestMessage()) + .replaceAll(":role:", user.getRole()) + .replaceAll(":countries:", countries); + + } + + private void sendMail(final String subject, final String content, final String to) { + if (!enabled) { + log.debug("Mail not sent: MailDispatcher is disabled"); + } else if (StringUtils.isAnyBlank(subject, content, to, fromMail, fromName)) { + log.warn("Mail not sent: some fields are empty"); + log.warn(" - subject: " + subject); + log.warn(" - to: " + to); + log.warn(" - fromMail: " + fromMail); + log.warn(" - fromName: " + fromName); + log.warn(" - content: " + content); + } else { + try { + final EmailMessage mail = emailFactory.prepareEmail(subject, content, fromMail, fromName, to); + mail.sendMail(); + } catch (final DnetException e) { + log.error("Error sending mail", e); + } + } + } + +} diff --git a/apps/dnet-orgs-database-application/src/main/resources/application.properties b/apps/dnet-orgs-database-application/src/main/resources/application.properties index b063a3da..83038eca 100644 --- a/apps/dnet-orgs-database-application/src/main/resources/application.properties +++ b/apps/dnet-orgs-database-application/src/main/resources/application.properties @@ -1,5 +1,8 @@ server.port=8480 +server.public_url = http://localhost:8480 +server.public_desc = API Base URL + spring.profiles.active=dev maven.pom.path = /META-INF/maven/eu.dnetlib.dhp/dnet-orgs-database-application/effective-pom.xml @@ -48,4 +51,4 @@ openorgs.support.pages = { "Ask a question": "https://www.openaire.eu/support/he openaire.override.logout.url = -openaire.explore.organization.baseurl = https://explore.openaire.eu/search/organization?organizationId= +openaire.explore.organization.baseurl = https://explore.openaire.eu/search/organization?organizationId=%s diff --git a/apps/dnet-orgs-database-application/src/main/resources/sql/schema.sql b/apps/dnet-orgs-database-application/src/main/resources/sql/schema.sql index 30959313..7ff4a386 100644 --- a/apps/dnet-orgs-database-application/src/main/resources/sql/schema.sql +++ b/apps/dnet-orgs-database-application/src/main/resources/sql/schema.sql @@ -5,6 +5,7 @@ DROP VIEW IF EXISTS users_view; DROP VIEW IF EXISTS conflict_groups_view; DROP VIEW IF EXISTS suggestions_info_by_country_view; DROP VIEW IF EXISTS duplicate_groups_view; +DROP VIEW IF EXISTS persistent_orgs_view; DROP TABLE IF EXISTS sysconf; DROP TABLE IF EXISTS other_ids; @@ -14,6 +15,8 @@ DROP TABLE IF EXISTS relationships; DROP TABLE IF EXISTS urls; DROP TABLE IF EXISTS oa_duplicates; DROP TABLE IF EXISTS oa_conflicts; +DROP TABLE IF EXISTS persistent_orgs; + DROP TABLE IF EXISTS organizations; DROP TABLE IF EXISTS org_types; @@ -31,7 +34,17 @@ CREATE TABLE sysconf ( id text PRIMARY KEY DEFAULT 'default', title text NOT NULL, homepage_msg text NOT NULL DEFAULT '', - readonly boolean NOT NULL DEFAULT false + readonly boolean NOT NULL DEFAULT false, + smtp_enabled boolean NOT NULL DEFAULT false, + smtp_host text NOT NULL DEFAULT 'localhost', + smtp_port int NOT NULL DEFAULT 587, + smtp_user text NOT NULL DEFAULT '', + smtp_password text NOT NULL DEFAULT '', + smtp_from_mail text NOT NULL DEFAULT 'no-reply@openaire.eu', + smtp_from_name text NOT NULL DEFAULT 'OpenOrgs Database', + smtp_to_mail_admin text NOT NULL DEFAULT 'openorgs-admin@openaire.eu', + smtp_new_user_message text NOT NULL DEFAULT '-- message template here --', + smtp_update_user_message text NOT NULL DEFAULT '-- message template here --' ); INSERT INTO sysconf(id, title) VALUES ('default', 'OpenOrgs Database'); @@ -318,11 +331,15 @@ CREATE TABLE user_roles(role text PRIMARY KEY); INSERT INTO user_roles VALUES ('ADMIN'), ('NATIONAL_ADMIN'), ('USER'), ('PENDING'), ('NOT_AUTHORIZED'); CREATE TABLE users ( - email text PRIMARY KEY, - valid boolean DEFAULT true, - role text NOT NULL default 'USER' REFERENCES user_roles(role), - first_access timestamp with time zone DEFAULT now(), - last_access timestamp with time zone DEFAULT now() + email text PRIMARY KEY, + fullname text, + organization text, + reference_person text, + request_message text, + valid boolean DEFAULT true, + role text NOT NULL default 'USER' REFERENCES user_roles(role), + first_access timestamp with time zone DEFAULT now(), + last_access timestamp with time zone DEFAULT now() ); CREATE TABLE user_countries ( @@ -360,6 +377,10 @@ CREATE TABLE organizations ( CREATE INDEX organizations_type_idx ON organizations(type); CREATE INDEX organizations_country_idx ON organizations(country); +CREATE TABLE persistent_orgs ( + id text PRIMARY KEY REFERENCES organizations(id) ON UPDATE CASCADE ON DELETE CASCADE +); + CREATE TABLE other_ids ( id text REFERENCES organizations(id) ON UPDATE CASCADE ON DELETE CASCADE, otherid text, @@ -450,7 +471,9 @@ CREATE VIEW oa_duplicates_view AS o.ec_internationalorganization, o.ec_enterprise, o.ec_smevalidated, - o.ec_nutscode + o.ec_nutscode, + substr(d.oa_original_id, 1, 14)||md5(substr(d.oa_original_id, 15)) as openaire_id, + false as openaire_persistent FROM oa_duplicates d LEFT OUTER JOIN organizations o ON (o.id = d.oa_original_id) @@ -510,6 +533,8 @@ CREATE VIEW organizations_view AS SELECT org.ec_enterprise, org.ec_smevalidated, org.ec_nutscode, + substr(org.id, 1, 14)||md5(substr(org.id, 15)) as openaire_id, + count(po.id) > 0 as openaire_persistent, COALESCE(jsonb_agg(DISTINCT jsonb_build_object('id', oid.otherid, 'type', oid.type)) FILTER (WHERE oid.otherid IS NOT NULL), '[]') AS other_ids, COALESCE(jsonb_agg(DISTINCT jsonb_build_object('name', n.name, 'lang', n.lang)) FILTER (WHERE n.name IS NOT NULL), '[]') AS other_names, COALESCE(jsonb_agg(DISTINCT a.acronym) FILTER (WHERE a.acronym IS NOT NULL), '[]') AS acronyms, @@ -523,6 +548,7 @@ FROM LEFT OUTER JOIN urls u ON (org.id = u.id) LEFT OUTER JOIN relationships r ON (org.id = r.id1) LEFT OUTER JOIN organizations relorg ON (relorg.id = r.id2) + LEFT OUTER JOIN persistent_orgs po ON (org.id = po.id) GROUP BY org.id, org.name, @@ -550,13 +576,16 @@ CREATE VIEW organizations_info_view AS SELECT org.creation_date, org.modified_by, org.modification_date, + substr(org.id, 1, 14)||md5(substr(org.id, 15)) as openaire_id, + count(po.id) > 0 as openaire_persistent, count(DISTINCT d.oa_original_id) as n_duplicates, count(DISTINCT c.id2) as n_conflicts, count(DISTINCT n.note) > 0 as note FROM organizations org - LEFT OUTER JOIN oa_duplicates d ON (org.id = d.local_id AND d.reltype = 'suggested') - LEFT OUTER JOIN oa_conflicts c ON (org.id = c.id1 AND c.reltype = 'suggested') - LEFT OUTER JOIN notes n ON (org.id = n.id) + LEFT OUTER JOIN oa_duplicates d ON (org.id = d.local_id AND d.reltype = 'suggested') + LEFT OUTER JOIN oa_conflicts c ON (org.id = c.id1 AND c.reltype = 'suggested') + LEFT OUTER JOIN notes n ON (org.id = n.id) + LEFT OUTER JOIN persistent_orgs po ON (org.id = po.id) GROUP BY org.id; CREATE VIEW organizations_simple_view AS SELECT @@ -586,6 +615,10 @@ GROUP BY CREATE VIEW users_view AS SELECT u.email, + u.fullname, + u.organization, + u.reference_person, + u.request_message, u.valid, u.role, u.first_access, @@ -594,7 +627,16 @@ CREATE VIEW users_view AS SELECT FROM users u LEFT OUTER JOIN user_countries uc ON (u.email = uc.email) -GROUP BY u.email, u.valid, u.role, u.first_access, u.last_access +GROUP BY + u.email, + u.fullname, + u.organization, + u.reference_person, + u.request_message, + u.valid, + u.role, + u.first_access, + u.last_access ORDER BY u.email; CREATE VIEW suggestions_info_by_country_view AS SELECT @@ -647,6 +689,18 @@ WHERE GROUP BY o.id, o.name, o.city, o.country ORDER BY o.name; +CREATE VIEW persistent_orgs_view AS SELECT + po.id, + substr(po.id, 1, 14)||md5(substr(po.id,15)) as openaire_id, + true as openaire_persistent, + o.name, + o.city, + o.country +FROM + persistent_orgs po + JOIN organizations o ON (po.id = o.id) +ORDER BY o.name; + CREATE TABLE org_index_search(id text PRIMARY KEY, txt tsvector); CREATE INDEX org_index_search_txt_gin_idx ON org_index_search USING gin(txt); @@ -655,7 +709,7 @@ CREATE OR REPLACE FUNCTION refresh_index_search() RETURNS bigint AS $$ WITH d as ( INSERT INTO org_index_search(id, txt) SELECT o.id, - to_tsvector(o.id||' '||o.name||' '||array_to_string(array_agg(DISTINCT n.name), ' ','')||' '||array_to_string(array_agg(DISTINCT i.otherid), ' ','')||' '||array_to_string(array_agg(DISTINCT a.acronym), ' ','')||' '||array_to_string(array_agg(DISTINCT u.url), ' ','')) + to_tsvector(o.id||' '||substr(o.id, 1, 14)||md5(substr(o.id, 15))||' '||o.name||' '||array_to_string(array_agg(DISTINCT n.name), ' ','')||' '||array_to_string(array_agg(DISTINCT i.otherid), ' ','')||' '||array_to_string(array_agg(DISTINCT a.acronym), ' ','')||' '||array_to_string(array_agg(DISTINCT u.url), ' ','')) FROM organizations o LEFT OUTER JOIN other_names n on (o.id = n.id) LEFT OUTER JOIN other_ids i on (o.id = i.id) @@ -667,8 +721,6 @@ $$ LANGUAGE SQL; SELECT refresh_index_search(); - - CREATE OR REPLACE FUNCTION delete_index_search() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN DELETE FROM org_index_search WHERE id = old.id; @@ -680,7 +732,7 @@ CREATE OR REPLACE FUNCTION insert_or_update_index_search_trigger() RETURNS trigg BEGIN INSERT INTO org_index_search(id, txt) (SELECT o.id, - to_tsvector(o.id||' '||o.name||' '||array_to_string(array_agg(DISTINCT n.name), ' ','')||' '||array_to_string(array_agg(DISTINCT i.otherid), ' ','')||' '||array_to_string(array_agg(DISTINCT a.acronym), ' ','')||' '||array_to_string(array_agg(DISTINCT u.url), ' ','')) + to_tsvector(o.id||' '||substr(o.id, 1, 14)||md5(substr(o.id, 15))||' '||o.name||' '||array_to_string(array_agg(DISTINCT n.name), ' ','')||' '||array_to_string(array_agg(DISTINCT i.otherid), ' ','')||' '||array_to_string(array_agg(DISTINCT a.acronym), ' ','')||' '||array_to_string(array_agg(DISTINCT u.url), ' ','')) FROM organizations o LEFT OUTER JOIN other_names n on (o.id = n.id) LEFT OUTER JOIN other_ids i on (o.id = i.id) diff --git a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/persistentOrgs.html b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/persistentOrgs.html new file mode 100644 index 00000000..28ef2fa4 --- /dev/null +++ b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/persistentOrgs.html @@ -0,0 +1,56 @@ +

Persistent Organizations

+ +

+ It is necessary to persist the identifiers of the organizations associated to an Institutional Dashboard +

+ + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDOA Graph Node IDNamePlace
{{o.id}}{{o.openaireId}}{{o.name}} {{o.city || '-'}}, {{o.country}} + +
No persistent organizazions
+ + + +
+
+
+
diff --git a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/sysConf.html b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/sysConf.html index de507648..dee414ba 100644 --- a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/sysConf.html +++ b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/sysConf.html @@ -4,28 +4,126 @@
-
- -
- -
-
-
- -
- -
-
-
- -
-
- +
+
+
General
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+ +
+
-
-
-
+
+ +
+
+
Mail configuration
+ +
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ + + + + + + + + +
+
diff --git a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/users.html b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/users.html index af693259..e42d95f6 100644 --- a/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/users.html +++ b/apps/dnet-orgs-database-application/src/main/resources/static/resources/html/pages/admin/users.html @@ -5,7 +5,7 @@
- +
@@ -19,7 +19,11 @@ - +
User
{{u.email}} + {{u.email}} +
Fullname: {{u.fullname}}
+
Organization: {{u.organization}}
+
not configured @@ -60,54 +64,69 @@ -