Added virtual corpus service (store).
Change-Id: Ic8073d801bc324b4f51fd0a0222c9e48a1ad17f9
diff --git a/full/src/main/java/de/ids_mannheim/korap/dto/VirtualCorpusDto.java b/full/src/main/java/de/ids_mannheim/korap/dto/VirtualCorpusDto.java
new file mode 100644
index 0000000..6f44a4c
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/dto/VirtualCorpusDto.java
@@ -0,0 +1,7 @@
+package de.ids_mannheim.korap.dto;
+
+public class VirtualCorpusDto {
+
+ int id;
+
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
new file mode 100644
index 0000000..f866aeb
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
@@ -0,0 +1,103 @@
+package de.ids_mannheim.korap.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import de.ids_mannheim.korap.constant.VirtualCorpusType;
+import de.ids_mannheim.korap.dao.VirtualCorpusDao;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.query.serialize.QuerySerializer;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.user.User.CorpusAccess;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
+import de.ids_mannheim.korap.web.SearchKrill;
+import de.ids_mannheim.korap.web.input.VirtualCorpusFromJson;
+
+@Service
+public class VirtualCorpusService {
+
+ private static Logger jlog =
+ LoggerFactory.getLogger(VirtualCorpusService.class);
+
+ @Autowired
+ private VirtualCorpusDao dao;
+
+ @Autowired
+ private SearchKrill krill;
+
+ @Autowired
+ private KustvaktConfiguration config;
+
+ public void storeVC (VirtualCorpusFromJson vc, User user)
+ throws KustvaktException {
+
+ // EM: how about VirtualCorpusType.PUBLISHED?
+ if (vc.getType().equals(VirtualCorpusType.PREDEFINED)
+ && !user.isAdmin()) {
+ throw new KustvaktException(StatusCodes.UNAUTHORIZED_OPERATION,
+ "Unauthorized operation for user: " + user.getUsername(),
+ user.getUsername());
+ }
+
+ String koralQuery = serializeCollectionQuery(vc.getCollectionQuery());
+ CorpusAccess requiredAccess = determineRequiredAccess(koralQuery);
+
+ dao.createVirtualCorpus(vc.getName(), vc.getType(), requiredAccess,
+ koralQuery, vc.getDefinition(), vc.getDescription(),
+ vc.getStatus(), vc.getCreatedBy());
+
+ // EM: should this return anything?
+ }
+
+ private String serializeCollectionQuery (String collectionQuery)
+ throws KustvaktException {
+ QuerySerializer serializer = new QuerySerializer();
+ serializer.setCollection(collectionQuery);
+ String koralQuery;
+ try {
+ koralQuery = serializer.convertCollectionToJson();
+ }
+ catch (JsonProcessingException e) {
+ throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
+ "Invalid argument: " + collectionQuery, collectionQuery);
+ }
+ jlog.debug(koralQuery);
+ return koralQuery;
+ }
+
+ private CorpusAccess determineRequiredAccess (String koralQuery)
+ throws KustvaktException {
+
+ if (findDocWithLicense(koralQuery, config.getAllOnlyRegex())) {
+ return CorpusAccess.ALL;
+ }
+ else if (findDocWithLicense(koralQuery, config.getPublicOnlyRegex())) {
+ return CorpusAccess.PUB;
+ }
+ else {
+ return CorpusAccess.FREE;
+ }
+ }
+
+ private boolean findDocWithLicense (String koralQuery, String license)
+ throws KustvaktException {
+ KoralCollectionQueryBuilder koral = new KoralCollectionQueryBuilder();
+ koral.setBaseQuery(koralQuery);
+ koral.with("availability=/" + license + "/");
+ String json = koral.toJSON();
+
+ String statistics = krill.getStatistics(json);
+ JsonNode node = JsonUtils.readTree(statistics);
+ int numberOfDoc = node.at("/documents").asInt();
+ jlog.debug("License: " + license + ", number of docs: " + numberOfDoc);
+ return (numberOfDoc > 0) ? true : false;
+ }
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
new file mode 100644
index 0000000..aafaa10
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
@@ -0,0 +1,79 @@
+package de.ids_mannheim.korap.web.controller;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+import com.sun.jersey.spi.container.ResourceFilters;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.filter.AuthFilter;
+import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
+import de.ids_mannheim.korap.service.VirtualCorpusService;
+import de.ids_mannheim.korap.user.TokenContext;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.utils.ParameterChecker;
+import de.ids_mannheim.korap.web.filter.DemoUserFilter;
+import de.ids_mannheim.korap.web.filter.PiwikFilter;
+import de.ids_mannheim.korap.web.input.VirtualCorpusFromJson;
+import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
+
+@Controller
+@Path("vc")
+@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
+@ResourceFilters({ AuthFilter.class, DemoUserFilter.class, PiwikFilter.class })
+public class VirtualCorpusController {
+
+ private static Logger jlog =
+ LoggerFactory.getLogger(VirtualCorpusController.class);
+
+ @Autowired
+ private AuthenticationManagerIface authManager;
+ @Autowired
+ private KustvaktResponseHandler responseHandler;
+ @Autowired
+ private VirtualCorpusService service;
+
+ @POST
+ @Path("store")
+ public Response storeVC (@Context SecurityContext securityContext,
+ String json) {
+ try {
+ ParameterChecker.checkStringValue(json, "json string");
+
+ // create vc object from json
+ VirtualCorpusFromJson vc =
+ JsonUtils.convertToClass(json, VirtualCorpusFromJson.class);
+ jlog.debug(vc.toString());
+
+ // get user info
+ TokenContext context =
+ (TokenContext) securityContext.getUserPrincipal();
+ if (context.isDemo()) {
+ throw new KustvaktException(StatusCodes.UNAUTHORIZED_OPERATION,
+ "Operation is not permitted for user: "
+ + context.getUsername(),
+ context.getUsername());
+ }
+
+ User user = authManager.getUser(context.getUsername());
+ service.storeVC(vc, user);
+ }
+ catch (KustvaktException e) {
+ throw responseHandler.throwit(e);
+ }
+ return Response.ok().build();
+ }
+
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/input/VirtualCorpusFromJson.java b/full/src/main/java/de/ids_mannheim/korap/web/input/VirtualCorpusFromJson.java
new file mode 100644
index 0000000..d6ddbd0
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/web/input/VirtualCorpusFromJson.java
@@ -0,0 +1,38 @@
+package de.ids_mannheim.korap.web.input;
+
+import de.ids_mannheim.korap.constant.VirtualCorpusType;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.utils.ParameterChecker;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class VirtualCorpusFromJson {
+
+ private String name;
+ private VirtualCorpusType type;
+ private String createdBy;
+ private String collectionQuery;
+
+ // optional
+ private String definition;
+ private String description;
+ private String status;
+
+ public void setName (String name) throws KustvaktException {
+ ParameterChecker.checkStringValue(name, "name");
+ this.name = name;
+ }
+
+ public void setCreatedBy (String createdBy) throws KustvaktException {
+ ParameterChecker.checkStringValue(createdBy, "createdBy");
+ this.createdBy = createdBy;
+ }
+
+ public void setCollectionQuery (String collectionQuery)
+ throws KustvaktException {
+ ParameterChecker.checkStringValue(collectionQuery, "collectionQuery");
+ this.collectionQuery = collectionQuery;
+ }
+}
\ No newline at end of file
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/service/full/VirtualCorpusServiceTest.java b/full/src/test/java/de/ids_mannheim/korap/web/service/full/VirtualCorpusServiceTest.java
new file mode 100644
index 0000000..7996ac6
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/web/service/full/VirtualCorpusServiceTest.java
@@ -0,0 +1,105 @@
+package de.ids_mannheim.korap.web.service.full;
+
+import static org.junit.Assert.*;
+
+import org.eclipse.jetty.http.HttpHeaders;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.ContextLoaderListener;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
+import com.sun.jersey.test.framework.AppDescriptor;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+import com.sun.jersey.test.framework.spi.container.TestContainerException;
+import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
+import com.sun.jersey.test.framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("classpath:test-config.xml")
+public class VirtualCorpusServiceTest extends JerseyTest {
+
+ private static String[] classPackages =
+ new String[] { "de.ids_mannheim.korap.web.service.full",
+ "de.ids_mannheim.korap.web.filter",
+ "de.ids_mannheim.korap.web.utils" };
+
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory ()
+ throws TestContainerException {
+ return new GrizzlyWebTestContainerFactory();
+ }
+
+ @Override
+ protected AppDescriptor configure () {
+ return new WebAppDescriptor.Builder(classPackages)
+ .servletClass(SpringServlet.class)
+ .contextListenerClass(ContextLoaderListener.class)
+ .contextParam("contextConfigLocation",
+ "classpath:test-config.xml")
+ .build();
+ }
+
+ @Test
+ public void testStoreVC () throws KustvaktException {
+ String json =
+ "{\"name\": \"new vc\",\"type\": \"PRIVATE\",\"createdBy\": "
+ + "\"test class\",\"collectionQuery\": \"corpusSigle=GOE\"}";
+
+ ClientResponse response = resource().path("vc").path("store")
+ .header(Attributes.AUTHORIZATION,
+ BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .entity(json)
+ .post(ClientResponse.class);
+ String entity = response.getEntity(String.class);
+ System.out.println(entity);
+ }
+
+ @Test
+ public void testStoreVCUnauthorized () throws KustvaktException {
+ String json =
+ "{\"name\": \"new vc\",\"type\": \"PRIVATE\",\"createdBy\": "
+ + "\"test class\",\"collectionQuery\": \"pubDate eq 1982\"}";
+
+ ClientResponse response = resource().path("vc").path("store")
+ .entity(json).post(ClientResponse.class);
+ String entity = response.getEntity(String.class);
+
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals(StatusCodes.UNAUTHORIZED_OPERATION,
+ node.at("/errors/0/0").asInt());
+ }
+
+ @Test
+ public void testStoreVCWithWrongType () throws KustvaktException {
+ String json =
+ "{\"name\": \"new vc\",\"type\": \"PRIVAT\",\"createdBy\": "
+ + "\"test class\",\"collectionQuery\": \"pubDate eq 1982\"}";
+
+ ClientResponse response = resource().path("vc").path("store")
+ .entity(json).post(ClientResponse.class);
+ String entity = response.getEntity(String.class);
+ // System.out.println(entity);
+
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals(StatusCodes.DESERIALIZATION_FAILED,
+ node.at("/errors/0/0").asInt());
+ assertTrue(node.at("/errors/0/1").asText().startsWith(
+ "Cannot deserialize value of type `de.ids_mannheim.korap.constant."
+ + "VirtualCorpusType` from String \"PRIVAT\": value not one of "
+ + "declared Enum instance names: [PROJECT, PRIVATE, PREDEFINED, "
+ + "PUBLISHED]"));
+ }
+}