-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #224 from bounswe/wikidata_api
Wikidata api
- Loading branch information
Showing
9 changed files
with
428 additions
and
1 deletion.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
...disasterresponse/src/main/java/com/a1/disasterresponse/controller/CategoryController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package com.a1.disasterresponse.controller; | ||
|
||
import com.a1.disasterresponse.model.EntityData; | ||
import com.a1.disasterresponse.repository.EntityRepository; | ||
import com.a1.disasterresponse.service.WikidataService; | ||
import kotlin.Pair; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
@RestController | ||
public class CategoryController { | ||
|
||
private final WikidataService wikidataService; | ||
private final EntityRepository relationRepository; | ||
|
||
public CategoryController(WikidataService wikidataService, EntityRepository relationRepository) { | ||
this.wikidataService = wikidataService; | ||
this.relationRepository = relationRepository; | ||
} | ||
|
||
@GetMapping("/category/findEntity") | ||
public ResponseEntity<EntityData.EntityRecord> findEntity(@RequestParam String query) { | ||
try { | ||
String id = wikidataService.searchForWikidataEntity(query); | ||
EntityData data = wikidataService.getWikidataEntityFromId(id); | ||
return new ResponseEntity<>(data.toRecord(), HttpStatus.OK); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); | ||
} | ||
} | ||
|
||
@GetMapping("/category/getCategoriesOf") | ||
public ResponseEntity<List<EntityData.EntityRecord>> getCategoriesOf(@RequestParam String id) { | ||
try { | ||
EntityData entityData = wikidataService.getWikidataEntityFromId(id); | ||
List<EntityData.EntityRecord> categories = new ArrayList<>(); | ||
for (String category : entityData.categories()) { | ||
categories.add(wikidataService.getWikidataEntityFromId(category).toRecord()); | ||
} | ||
return new ResponseEntity<>(categories, HttpStatus.OK); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); | ||
} | ||
} | ||
|
||
@PostMapping("/category/saveEntity") | ||
public ResponseEntity<Void> saveEntity(@RequestParam String id) { | ||
try { | ||
EntityData entityData = wikidataService.getWikidataEntityFromId(id); | ||
relationRepository.save(entityData.toRecord()); | ||
return new ResponseEntity<>(HttpStatus.OK); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); | ||
} | ||
} | ||
|
||
@GetMapping("/category/getEntities") | ||
public ResponseEntity<List<EntityData.EntityRecord>> getSavedEntities() { | ||
return new ResponseEntity<>(relationRepository.findAll(), HttpStatus.OK); | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
...-app/backend/disasterresponse/src/main/java/com/a1/disasterresponse/model/EntityData.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.a1.disasterresponse.model; | ||
|
||
import jakarta.persistence.*; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
|
||
public record EntityData(String id, Map<String, String> labels, | ||
List<String> categories) { | ||
|
||
public EntityRecord toRecord() { | ||
return new EntityRecord(id, labels.getOrDefault("en", id)); | ||
} | ||
|
||
@Entity | ||
public static class EntityRecord { | ||
@Id | ||
public String id; | ||
|
||
public String name; | ||
|
||
public EntityRecord() { | ||
} | ||
|
||
public EntityRecord(String id, String name) { | ||
this.id = id; | ||
this.name = name; | ||
} | ||
|
||
public String getId() { | ||
return id; | ||
} | ||
|
||
public void setId(String id) { | ||
this.id = id; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
...d/disasterresponse/src/main/java/com/a1/disasterresponse/repository/EntityRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.a1.disasterresponse.repository; | ||
|
||
import com.a1.disasterresponse.model.EntityData; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.util.Pair; | ||
|
||
public interface EntityRepository extends JpaRepository<EntityData.EntityRecord, String> { | ||
} |
77 changes: 77 additions & 0 deletions
77
...ckend/disasterresponse/src/main/java/com/a1/disasterresponse/service/WikidataService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.a1.disasterresponse.service; | ||
|
||
import com.a1.disasterresponse.model.EntityData; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import okhttp3.OkHttpClient; | ||
import okhttp3.Request; | ||
import okhttp3.Response; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@Service | ||
public class WikidataService { | ||
|
||
private static final String WIKIDATA_BASE_URL = "https://www.wikidata.org/w/api.php"; | ||
|
||
public static final String WIKIDATA_SEARCH = "?action=wbsearchentities&format=json&language=en&type=item&continue=0&search="; | ||
public static final String WIKIDATA_GET_ENTITY = "?action=wbgetentities&format=json&languages=en|tr&props=labels|info|claims&ids="; | ||
private static final OkHttpClient client = new OkHttpClient(); | ||
private static final ObjectMapper mapper = new ObjectMapper(); | ||
|
||
public String searchForWikidataEntity(String query) throws IOException { | ||
JsonNode rootNode = executeWikidataQuery(WIKIDATA_SEARCH + query); | ||
|
||
return rootNode.get("search").get(0).get("id").asText(); | ||
} | ||
|
||
public EntityData getWikidataEntityFromId(String id) throws IOException { | ||
JsonNode entity = executeWikidataQuery(WIKIDATA_GET_ENTITY + id).get("entities").get(id); | ||
|
||
Map<String, String> labels = new HashMap<>(); | ||
|
||
entity.get("labels") | ||
.fields() | ||
.forEachRemaining(e -> labels.put( | ||
e.getValue().get("language").textValue(), | ||
e.getValue().get("value").textValue() | ||
)); | ||
|
||
List<String> supercategories = new ArrayList<>(); | ||
if (entity.get("claims").has("P279")) { | ||
entity.get("claims") | ||
.get("P279") | ||
.elements() | ||
.forEachRemaining(e -> supercategories.add(e | ||
.get("mainsnak") | ||
.get("datavalue") | ||
.get("value") | ||
.get("id") | ||
.asText())); | ||
} | ||
|
||
return new EntityData(id, labels, supercategories); | ||
} | ||
|
||
private JsonNode executeWikidataQuery(String query) throws IOException { | ||
Request request = new Request.Builder() | ||
.url(WIKIDATA_BASE_URL + query) | ||
.get() | ||
.build(); | ||
|
||
try (Response response = client.newCall(request).execute()) { | ||
if (!response.isSuccessful() || response.body() == null) { | ||
throw new IOException("Unexpected code " + response); | ||
} | ||
|
||
String body = response.body().string(); | ||
|
||
return mapper.readTree(body); | ||
} | ||
} | ||
} |
128 changes: 128 additions & 0 deletions
128
...sterresponse/src/test/java/com/a1/disasterresponse/controller/CategoryControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package com.a1.disasterresponse.controller; | ||
|
||
import com.a1.disasterresponse.model.EntityData; | ||
import com.a1.disasterresponse.repository.EntityRepository; | ||
import com.a1.disasterresponse.service.WikidataService; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.mockito.Mockito; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
import static org.mockito.Mockito.*; | ||
|
||
class CategoryControllerTest { | ||
|
||
private WikidataService wikidataService; | ||
private EntityRepository relationRepository; | ||
|
||
private CategoryController categoryController; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
wikidataService = Mockito.mock(WikidataService.class); | ||
relationRepository = Mockito.mock(EntityRepository.class); | ||
categoryController = new CategoryController(wikidataService, relationRepository); | ||
} | ||
|
||
@Test | ||
void testIdOf() throws IOException { | ||
//Mock wikimedia api call | ||
when(wikidataService.searchForWikidataEntity("blanket")).thenReturn("Q5852"); | ||
|
||
// Call api | ||
ResponseEntity<EntityData.EntityRecord> resp = categoryController.findEntity("blanket"); | ||
|
||
// Verify the response | ||
assertEquals(HttpStatus.OK, resp.getStatusCode()); | ||
assertNotNull(resp.getBody()); | ||
assertEquals("Q5852", resp.getBody().id); | ||
|
||
verify(wikidataService, times(1)).searchForWikidataEntity("blanket"); | ||
} | ||
|
||
@Test | ||
void testGetCategoriesOf_nocats() throws IOException { | ||
EntityData blanketData = new EntityData( | ||
"Q5852", | ||
Map.of("en", "blanket", "tr", "battaniye"), | ||
List.of()); | ||
|
||
when(wikidataService.getWikidataEntityFromId("Q5852")).thenReturn(blanketData); | ||
|
||
|
||
ResponseEntity<List<EntityData.EntityRecord>> resp = categoryController.getCategoriesOf("Q5852"); | ||
|
||
// Verify the response | ||
assertEquals(HttpStatus.OK, resp.getStatusCode()); | ||
assertNotNull(resp.getBody()); | ||
assertEquals(0, resp.getBody().size()); | ||
|
||
verify(wikidataService, times(1)).getWikidataEntityFromId(anyString()); | ||
} | ||
|
||
@Test | ||
void testGetCategoriesOf_one_cat() throws IOException { | ||
EntityData blanketData = new EntityData( | ||
"Q5852", | ||
Map.of("en", "blanket", "tr", "battaniye"), | ||
List.of("Q31808206")); | ||
|
||
EntityData coveringData = new EntityData( | ||
"Q31808206", | ||
Map.of("en", "covering"), | ||
List.of("Q31807746")); | ||
|
||
when(wikidataService.getWikidataEntityFromId("Q5852")).thenReturn(blanketData); | ||
when(wikidataService.getWikidataEntityFromId("Q31808206")).thenReturn(coveringData); | ||
|
||
|
||
ResponseEntity<List<EntityData.EntityRecord>> resp = categoryController.getCategoriesOf("Q5852"); | ||
|
||
// Verify the response | ||
assertEquals(HttpStatus.OK, resp.getStatusCode()); | ||
assertNotNull(resp.getBody()); | ||
assertEquals(List.of(coveringData.toRecord()), resp.getBody()); | ||
|
||
verify(wikidataService, times(2)).getWikidataEntityFromId(anyString()); | ||
} | ||
|
||
|
||
@Test | ||
void testGetCategoriesOf_two_cats() throws IOException { | ||
EntityData blanketData = new EntityData( | ||
"Q5852", | ||
Map.of("en", "blanket", "tr", "battaniye"), | ||
List.of("Q31808206", "Q31807746")); | ||
|
||
EntityData coveringData = new EntityData( | ||
"Q31808206", | ||
Map.of("en", "covering"), | ||
List.of()); | ||
|
||
EntityData furnishingData = new EntityData( | ||
"Q31807746", | ||
Map.of("en", "furnishing"), | ||
List.of("Q10273457", "Q17537576", "Q8205328")); | ||
|
||
|
||
when(wikidataService.getWikidataEntityFromId("Q5852")).thenReturn(blanketData); | ||
when(wikidataService.getWikidataEntityFromId("Q31808206")).thenReturn(coveringData); | ||
when(wikidataService.getWikidataEntityFromId("Q31807746")).thenReturn(furnishingData); | ||
|
||
ResponseEntity<List<EntityData.EntityRecord>> resp = categoryController.getCategoriesOf("Q5852"); | ||
|
||
// Verify the response | ||
assertEquals(HttpStatus.OK, resp.getStatusCode()); | ||
assertNotNull(resp.getBody()); | ||
assertEquals(List.of(coveringData.toRecord(), furnishingData.toRecord()), resp.getBody()); | ||
|
||
verify(wikidataService, times(3)).getWikidataEntityFromId(anyString()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
practice-app/frontend/disasterresponse/src/pages/WikidataApi/WikidataPage.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.directionsDiv { | ||
margin-top: 20px; | ||
} | ||
|
||
.formDiv { | ||
width: 40vw; | ||
margin: 10px auto; | ||
} | ||
|
||
.directionsDiv { | ||
width: 40vw; | ||
margin: 10px auto; | ||
} |
Oops, something went wrong.