diff --git a/src/backend/animaltroove/pom.xml b/src/backend/animaltroove/pom.xml index 4f604ae8e..c81708377 100644 --- a/src/backend/animaltroove/pom.xml +++ b/src/backend/animaltroove/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot @@ -35,6 +35,24 @@ spring-boot-starter-test test + + + org.apache.jena + jena-arq + 4.9.0 + pom + + + org.apache.jena + jena-core + 4.6.0 + + + org.apache.jena + apache-jena-libs + pom + 4.6.0 + diff --git a/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/controller/SearchController.java b/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/controller/SearchController.java new file mode 100644 index 000000000..c32dedb49 --- /dev/null +++ b/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/controller/SearchController.java @@ -0,0 +1,27 @@ +package com.bounswe2024group10.animaltroove.controller; + +import com.bounswe2024group10.animaltroove.service.SearchService; +import com.bounswe2024group10.animaltroove.dto.SearchRequest; +import com.bounswe2024group10.animaltroove.dto.SearchResponse; + +import org.apache.jena.base.Sys; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +public class SearchController { + + @Autowired + private SearchService searchService; + + @PostMapping("/search") + public ResponseEntity search(@RequestBody SearchRequest searchRequest) { + SearchResponse searchResponse = searchService.search(searchRequest.getSearchTerm()); + if (searchResponse == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + return new ResponseEntity<>(searchResponse, HttpStatus.OK); + } +} \ No newline at end of file diff --git a/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/dto/SearchRequest.java b/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/dto/SearchRequest.java new file mode 100644 index 000000000..3856a54ec --- /dev/null +++ b/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/dto/SearchRequest.java @@ -0,0 +1,21 @@ +package com.bounswe2024group10.animaltroove.dto; + +public class SearchRequest { + private String searchTerm; + + public SearchRequest() { + // Default constructor + } + + public SearchRequest(String searchTerm) { + this.searchTerm = searchTerm; + } + + public String getSearchTerm() { + return searchTerm; + } + + public void setSearchTerm(String searchTerm) { + this.searchTerm = searchTerm; + } +} \ No newline at end of file diff --git a/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/dto/SearchResponse.java b/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/dto/SearchResponse.java new file mode 100644 index 000000000..18ef10424 --- /dev/null +++ b/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/dto/SearchResponse.java @@ -0,0 +1,101 @@ +package com.bounswe2024group10.animaltroove.dto; + +public class SearchResponse { + private String name; + private String cycle; + private String pregnancy; + private String lifeExpectancy; + private String heartRate; + private String speed; + private String numberOfBirths; + private String pic; + private String wingSpan; + private String conservationStatus; + private String mainLabel; + + public SearchResponse() { + // Default constructor + } + + // Getters and setters for each field + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCycle() { + return cycle; + } + + public void setMainLabel(String mainLabel) { + this.mainLabel = mainLabel; + } + public String getMainLabel() { + return this.mainLabel; + } + + public void setCycle(String cycle) { + this.cycle = cycle; + } + public void setPic(String pic){this.pic = pic;} + + public String getPic(){return this.pic;} + public String getPregnancy() { + return pregnancy; + } + + public void setPregnancy(String pregnancy) { + this.pregnancy = pregnancy; + } + + public String getLifeExpectancy() { + return lifeExpectancy; + } + + public void setLifeExpectancy(String lifeExpectancy) { + this.lifeExpectancy = lifeExpectancy; + } + + public String getHeartRate() { + return heartRate; + } + + public void setHeartRate(String heartRate) { + this.heartRate = heartRate; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getNumberOfBirths() { + return numberOfBirths; + } + + public void setNumberOfBirths(String numberOfBirths) { + this.numberOfBirths = numberOfBirths; + } + + public String getWingSpan() { + return wingSpan; + } + + public void setWingSpan(String wingSpan) { + this.wingSpan = wingSpan; + } + + public String getConservationStatus() { + return conservationStatus; + } + + public void setConservationStatus(String conservationStatus) { + this.conservationStatus = conservationStatus; + } +} diff --git a/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/service/SearchService.java b/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/service/SearchService.java new file mode 100644 index 000000000..d8fb64a1a --- /dev/null +++ b/src/backend/animaltroove/src/main/java/com/bounswe2024group10/animaltroove/service/SearchService.java @@ -0,0 +1,155 @@ +package com.bounswe2024group10.animaltroove.service; + +import com.bounswe2024group10.animaltroove.dto.SearchResponse; + +import java.util.List; + +import org.apache.jena.query.*; +import org.springframework.stereotype.Service; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.util.FileManager; + +@Service +public class SearchService { + + public SearchResponse search(String searchTerm) { + String entityURI = getEntityURI(searchTerm); + System.out.println("Entity URI" +entityURI); + if (entityURI == null) { + return null; + } + SearchResponse searchResponse = getAnimalDetails(entityURI); + System.out.println(searchResponse.toString()); + return searchResponse; + } + + public String getEntityURI(String searchTerm) { + String sparqlEndpoint = "https://query.wikidata.org/sparql"; + String queryString = "PREFIX rdfs: \n" + + "PREFIX wdt: \n" + + "PREFIX wd: \n" + + "SELECT ?entity\n" + + "WHERE {\n" + + "?entity rdfs:label \"" + searchTerm + "\"@en.\n" + + + "?entity wdt:P31 wd:Q16521\n" + + "}"; + + + + String qStringTest = "PREFIX rdfs: \n" + + " PREFIX wdt: \n" + + " PREFIX wd: \n" + + "PREFIX wikibase: \n" + + "PREFIX skos: \n" + + "SELECT ?entity\n" + + "WHERE {\n" + + " ?entity skos:altLabel ?alias .\n" + + " FILTER(CONTAINS(LCASE(?alias), \" "+searchTerm.toLowerCase() + "\"))\n" + +// " {\n" + +// " ?entity wdt:P31 wd:Q16521 .\n" + +// " }\n" + +// " UNION\n" + + " {\n" + + " ?entity wdt:P279* wd:Q729 .\n" + + " }\n" + +// " SERVICE wikibase:label { bd:serviceParam wikibase:language \"en\". }\n" + + "}\n" + + "LIMIT 10"; + Query query1 = QueryFactory.create(qStringTest); + QueryExecution qexec = QueryExecutionFactory.sparqlService(sparqlEndpoint,query1); + ResultSet resultSet = qexec.execSelect(); + System.out.println("REsult rows" + resultSet.getRowNumber()); + if (resultSet.hasNext()) { + QuerySolution querySolution = resultSet.next(); + if (querySolution.get("entity") != null) { + System.out.println("WE HAVE ENTITY"); + return querySolution.get("entity").toString().split("/")[4]; + } + } + return null; + } + + SearchResponse getAnimalDetails(String entityURI) { + System.out.println("Entitiy URI is : "+ entityURI); + String sparqlEndpoint = "https://query.wikidata.org/sparql"; + String queryString = "PREFIX rdfs: \n" + + "PREFIX wdt: \n" + + "PREFIX wd: \n" + + "PREFIX wikibase: \n" + + "PREFIX bd: \n" + + "SELECT ?itemLabel ?picLabel ?nameLabel ?cycleLabel ?pregLabel ?lifeLabel ?heartLabel ?speedLabel ?numBirthLabel ?wingSpanLabel ?conservationStatLabel\n" + + "WHERE {\n" + + " wd:" + entityURI + " rdfs:label ?itemLabel .\n" + // Fetch the label of the main item + " FILTER(LANG(?itemLabel) = \"en\")\n" + // Ensure the label is in English + " OPTIONAL {wd:" + entityURI + " wdt:P18 ?pic.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P225 ?name.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P9566 ?cycle.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P3063 ?preg.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P2250 ?life.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P3395 ?heart.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P2052 ?speed.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P7725 ?numBirth.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P2050 ?wingSpan.}\n" + + " OPTIONAL {wd:" + entityURI + " wdt:P141 ?conservationStat.}\n" + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"en\". }\n" + + "}"; + Query query2 = QueryFactory.create(queryString); + QueryExecution queryExec = QueryExecutionFactory.sparqlService(sparqlEndpoint,query2); + ResultSet resultSet = queryExec.execSelect(); + + if (resultSet.hasNext()) { + QuerySolution querySolution = resultSet.next(); + SearchResponse searchResponse = new SearchResponse(); + if (querySolution.get("nameLabel") != null) { + searchResponse.setName(querySolution.get("nameLabel").toString()); + } + if (querySolution.get("cycleLabel") != null) { + String cycleLabel = querySolution.get("cycleLabel").toString(); + if (cycleLabel.contains("@en")) { + cycleLabel = cycleLabel.substring(0, cycleLabel.indexOf("@en")); + } + searchResponse.setCycle(cycleLabel); + } + if (querySolution.get("itemLabel") != null) { + String itemLabel = querySolution.get("itemLabel").toString(); + if (itemLabel.contains("@en")) { + itemLabel = itemLabel.substring(0, itemLabel.indexOf("@en")); + } + searchResponse.setMainLabel(itemLabel); + } + if (querySolution.get("pregLabel") != null) { + searchResponse.setPregnancy(querySolution.get("pregLabel").toString()); + } + if (querySolution.get("lifeLabel") != null) { + searchResponse.setLifeExpectancy(querySolution.get("lifeLabel").toString()); + } + if (querySolution.get("heartLabel") != null) { + searchResponse.setHeartRate(querySolution.get("heartLabel").toString()); + } + if (querySolution.get("speedLabel") != null) { + searchResponse.setSpeed(querySolution.get("speedLabel").toString()); + } + if (querySolution.get("numBirthLabel") != null) { + searchResponse.setNumberOfBirths(querySolution.get("numBirthLabel").toString()); + } + if(querySolution.get("picLabel")!=null){ + searchResponse.setPic(querySolution.get("picLabel").toString()); + } + if (querySolution.get("wingSpanLabel") != null) { + searchResponse.setWingSpan(querySolution.get("wingSpanLabel").toString()); + } + if (querySolution.get("conservationStatLabel") != null) { + String conservationStatLabel = querySolution.get("conservationStatLabel").toString(); + if (conservationStatLabel.contains("@en")) { + conservationStatLabel = conservationStatLabel.substring(0, conservationStatLabel.indexOf("@en")); + } + searchResponse.setConservationStatus(conservationStatLabel); + + } + return searchResponse; + } + return null; + } +}