blob: 8c8a59990fce807268a20ac920722e96db537821 [file] [log] [blame]
package de.ids_mannheim.korap.web.service.full;//package de.ids_mannheim.korap.ext.web;
import com.fasterxml.jackson.databind.JsonNode;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import com.sun.jersey.spi.container.ResourceFilters;
import de.ids_mannheim.korap.config.Attributes;
import de.ids_mannheim.korap.config.BeansFactory;
import de.ids_mannheim.korap.config.KustvaktConfiguration;
import de.ids_mannheim.korap.exceptions.EmptyResultException;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.NotAuthorizedException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
import de.ids_mannheim.korap.query.serialize.MetaQueryBuilder;
import de.ids_mannheim.korap.query.serialize.QuerySerializer;
import de.ids_mannheim.korap.resource.rewrite.*;
import de.ids_mannheim.korap.resources.*;
import de.ids_mannheim.korap.security.ac.ResourceFinder;
import de.ids_mannheim.korap.security.ac.ResourceHandler;
import de.ids_mannheim.korap.security.ac.SecurityManager;
import de.ids_mannheim.korap.user.TokenContext;
import de.ids_mannheim.korap.user.User;
import de.ids_mannheim.korap.utils.*;
import de.ids_mannheim.korap.web.ClientsHandler;
import de.ids_mannheim.korap.web.KustvaktServer;
import de.ids_mannheim.korap.web.SearchKrill;
import de.ids_mannheim.korap.web.TRACE;
import de.ids_mannheim.korap.web.filter.AuthFilter;
import de.ids_mannheim.korap.web.filter.BlockingFilter;
import de.ids_mannheim.korap.web.filter.DefaultFilter;
import de.ids_mannheim.korap.web.filter.PiwikFilter;
import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import java.util.*;
/**
* @author hanl
* @date 29/01/2014
*/
@Path(KustvaktServer.API_VERSION + "/")
@ResourceFilters({ AuthFilter.class, DefaultFilter.class, PiwikFilter.class,
BlockingFilter.class })
@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
public class ResourceService {
private static Logger jlog = LoggerFactory.getLogger(ResourceService.class);
private SearchKrill searchKrill;
private ResourceHandler resourceHandler;
private AuthenticationManagerIface controller;
private ClientsHandler graphDBhandler;
private KustvaktConfiguration config;
private RewriteHandler processor;
public ResourceService () {
this.controller = BeansFactory.getKustvaktContext()
.getAuthenticationManager();
this.config = BeansFactory.getKustvaktContext().getConfiguration();
this.resourceHandler = new ResourceHandler();
this.searchKrill = new SearchKrill(config.getIndexDir());
UriBuilder builder = UriBuilder.fromUri("http://10.0.10.13").port(9997);
this.graphDBhandler = new ClientsHandler(builder.build());
this.processor = new RewriteHandler();
this.processor.defaultRewriteConstraints();
this.processor.insertBeans(BeansFactory.getKustvaktContext());
}
/**
* retrieve resources dependent by type. determines based on
* the user's permission or resource owner if the user can access
* the resource.
*
* @param locale
* @param context
* @param type
* @return valid resources in json format
*/
@GET
@Path("{type}")
public Response getResources (@Context Locale locale,
@Context SecurityContext context, @PathParam("type") String type) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
Set<KustvaktResource> resources = new HashSet<>();
type = StringUtils.normalize(type);
Class cl_type = ResourceFactory.getResourceClass(type);
if (cl_type == null) {
throw KustvaktResponseHandler.throwit(StatusCodes.REQUEST_INVALID,
"Resource type not available!", "");
}
try {
User user = controller.getUser(ctx.getUsername());
resources = ResourceFinder.search(user,
ResourceFactory.getResourceClass(type));
}
catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
Set values = new HashSet();
for (KustvaktResource resource : resources)
values.add(resource.toMap());
return Response.ok(JsonUtils.toJSON(values)).build();
}
@GET
@Path("{type}/{id}/{child}")
public Response getResource (@Context SecurityContext context,
@Context Locale locale, @PathParam("type") String type,
@PathParam("id") String id, @PathParam("child") String child) {
return getResource(context, locale, type,
StringUtils.joinResources(id, child));
}
/**
* @param context
* @param locale
* @param id
* @param type
* @return
*/
@GET
@Path("{type}/{id}")
public Response getResource (@Context SecurityContext context,
@Context Locale locale, @PathParam("type") String type,
@PathParam("id") String id) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
type = StringUtils.normalize(type);
Class cl_type = ResourceFactory.getResourceClass(type);
KustvaktResource resource;
try {
User user = controller.getUser(ctx.getUsername());
if (StringUtils.isInteger(id))
resource = resourceHandler.findbyIntId(Integer.valueOf(id),
user);
else
resource = resourceHandler.findbyStrId(id, user,
ResourceFactory.getResourceClass(type));
}
catch (KustvaktException e) {
if (e.getStatusCode() != StatusCodes.PERMISSION_DENIED)
throw KustvaktResponseHandler.throwit(e);
try {
Set set = ResourceFinder.searchPublicFiltered(cl_type, id);
resource = (KustvaktResource) set.toArray()[0];
}
catch (KustvaktException e1) {
throw KustvaktResponseHandler.throwit(e);
}
}
return Response.ok(JsonUtils.toJSON(resource.toMap())).build();
}
// @GET
// @Path("colloc")
// public Response getCollocationsAll(@Context SecurityContext ctx,
// @Context Locale locale, @QueryParam("props") String properties,
// @QueryParam("sfskip") Integer sfs,
// @QueryParam("sflimit") Integer limit, @QueryParam("q") String query,
// @QueryParam("ql") String ql, @QueryParam("context") Integer context,
// @QueryParam("foundry") String foundry,
// @QueryParam("paths") Boolean wPaths) {
// TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
// ColloQuery.ColloQueryBuilder builder;
// KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
// String result;
// try {
// User user = controller.getUser(tokenContext.getUsername());
// Set<VirtualCollection> resources = ResourceFinder
// .search(user, VirtualCollection.class);
// for (KustvaktResource c : resources)
// cquery.addResource(((VirtualCollection) c).getQuery());
//
// builder = functions
// .buildCollocations(query, ql, properties, context, limit,
// sfs, foundry, new ArrayList<Dependency>(), wPaths,
// cquery);
//
// result = graphDBhandler
// .getResponse("distCollo", "q", builder.build().toJSON());
// }catch (KustvaktException e) {
// throw KustvaktResponseHandler.throwit(e);
// }catch (JsonProcessingException e) {
// throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
// }
// return Response.ok(result).build();
// }
// /**
// * @param locale
// * @param properties a json object string containing field, op and value for the query
// * @param query
// * @param context
// * @return
// */
// @GET
// @Path("{type}/{id}/colloc")
// public Response getCollocations(@Context SecurityContext ctx,
// @Context Locale locale, @QueryParam("props") String properties,
// @QueryParam("sfskip") Integer sfs,
// @QueryParam("sflimit") Integer limit, @QueryParam("q") String query,
// @QueryParam("ql") String ql, @QueryParam("context") Integer context,
// @QueryParam("foundry") String foundry,
// @QueryParam("paths") Boolean wPaths, @PathParam("id") String id,
// @PathParam("type") String type) {
// ColloQuery.ColloQueryBuilder builder;
// type = StringUtils.normalize(type);
// id = StringUtils.decodeHTML(id);
// TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
// String result;
// try {
// KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
// try {
// User user = controller.getUser(tokenContext.getUsername());
//
// KustvaktResource resource = this.resourceHandler
// .findbyStrId(id, user, type);
//
// if (resource instanceof VirtualCollection)
// cquery.addResource(
// ((VirtualCollection) resource).getQuery());
// else if (resource instanceof Corpus)
// cquery.addMetaFilter("corpusID",
// resource.getPersistentID());
// else
// throw KustvaktResponseHandler
// .throwit(StatusCodes.ILLEGAL_ARGUMENT,
// "Type parameter not supported", type);
//
// }catch (KustvaktException e) {
// throw KustvaktResponseHandler.throwit(e);
// }catch (NumberFormatException ex) {
// throw KustvaktResponseHandler
// .throwit(StatusCodes.ILLEGAL_ARGUMENT);
// }
//
// builder = functions
// .buildCollocations(query, ql, properties, context, limit,
// sfs, foundry, new ArrayList<Dependency>(), wPaths,
// cquery);
//
// result = graphDBhandler
// .getResponse("distCollo", "q", builder.build().toJSON());
//
// }catch (JsonProcessingException e) {
// throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
// }catch (KustvaktException e) {
// throw KustvaktResponseHandler.throwit(e);
// }
//
// return Response.ok(result).build();
// }
@POST
@Path("colloc")
public Response getCollocationBase (@QueryParam("q") String query) {
String result;
try {
result = graphDBhandler.getResponse("distCollo", "q", query);
}
catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
return Response.ok(result).build();
}
@Deprecated
public Response postMatchFavorite () {
return Response.ok().build();
}
// ref query parameter removed!
@TRACE
@Path("search")
public Response buildQuery (@Context Locale locale,
@Context SecurityContext securityContext,
@QueryParam("q") String q, @QueryParam("ql") String ql,
@QueryParam("v") String v, @QueryParam("context") String context,
@QueryParam("cutoff") Boolean cutoff,
@QueryParam("count") Integer pageLength,
@QueryParam("offset") Integer pageIndex,
@QueryParam("page") Integer startPage, @QueryParam("cq") String cq) {
TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
QuerySerializer ss;
//User user;
//try {
// user = controller.getUser(ctx.getUsername());
//}
//catch (KustvaktException e) {
// throw KustvaktResponseHandler.throwit(e);
//}
ss = new QuerySerializer().setQuery(q, ql, v);
if (cq != null)
ss.setCollection(cq);
MetaQueryBuilder meta = new MetaQueryBuilder();
if (pageIndex != null)
meta.addEntry("startIndex", pageIndex);
if (pageIndex == null && startPage != null)
meta.addEntry("startPage", startPage);
if (pageLength != null)
meta.addEntry("count", pageLength);
if (context != null)
meta.setSpanContext(context);
meta.addEntry("cutOff", cutoff);
ss.setMeta(meta.raw());
return Response.ok(ss.toJSON()).build();
}
/**
* currently only supports either no reference at all in which
* case all corpora are retrieved or a corpus name like "WPD".
* No virtual collections supported!
*
* @param locale
* @param q
* @param ql
* @param v
* @param pageLength
* @param pageIndex
* @return
*/
//todo: does cq have any sensible worth here? --> would say no! --> is useful in non type/id scenarios
@TRACE
@Path("{type}/{id}/search")
public Response buildQueryWithId (@Context Locale locale,
@Context SecurityContext securityContext,
@QueryParam("q") String q, @QueryParam("ql") String ql,
@QueryParam("v") String v, @QueryParam("context") String context,
@QueryParam("cutoff") Boolean cutoff,
@QueryParam("count") Integer pageLength,
@QueryParam("offset") Integer pageIndex,
@QueryParam("page") Integer startPage,
@PathParam("type") String type, @PathParam("id") String id) {
TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
type = StringUtils.normalize(type);
id = StringUtils.decodeHTML(id);
QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
MetaQueryBuilder meta = new MetaQueryBuilder();
if (pageIndex != null)
meta.addEntry("startIndex", pageIndex);
if (pageIndex == null && startPage != null)
meta.addEntry("startPage", startPage);
if (pageLength != null)
meta.addEntry("count", pageLength);
if (context != null)
meta.setSpanContext(context);
if (cutoff != null)
meta.addEntry("cutOff", cutoff);
ss.setMeta(meta.raw());
KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
cquery.setBaseQuery(ss.toJSON());
String query = "";
KustvaktResource resource;
try {
User user = controller.getUser(ctx.getUsername());
if (StringUtils.isInteger(id))
resource = this.resourceHandler.findbyIntId(
Integer.valueOf(id), user);
else
resource = this.resourceHandler.findbyStrId(id, user,
ResourceFactory.getResourceClass(type));
}
//todo: instead of throwing exception, build notification and rewrites into result query
catch (KustvaktException e) {
if (e.getStatusCode() != StatusCodes.PERMISSION_DENIED) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
try {
Set set = ResourceFinder.searchPublicFiltered(
ResourceFactory.getResourceClass(type), id);
resource = (KustvaktResource) set.toArray()[0];
}
catch (KustvaktException e1) {
throw KustvaktResponseHandler.throwit(e);
}
}
if (resource != null) {
if (resource instanceof VirtualCollection)
query = JsonUtils.toJSON(cquery.and().mergeWith(
resource.getData()));
else if (resource instanceof Corpus) {
cquery.and().with(Attributes.CORPUS_SIGLE, "=",
resource.getPersistentID());
query = cquery.toJSON();
}
}
return Response.ok(query).build();
}
@POST
@Path("search")
public Response queryRaw (@Context SecurityContext context,
@Context Locale locale, @QueryParam("engine") String engine,
String jsonld) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
// todo: should be possible to add the meta part to the query serialization
try {
User user = controller.getUser(ctx.getUsername());
//jsonld = this.processor.processQuery(jsonld, user);
}
catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
jlog.info("Serialized search: {}", jsonld);
String result = searchKrill.search(jsonld);
// todo: logging
KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
return Response.ok(result).build();
}
@GET
@Path("search")
public Response searchbyNameAll (@Context SecurityContext securityContext,
@Context Locale locale, @QueryParam("q") String q,
@QueryParam("ql") String ql, @QueryParam("v") String v,
@QueryParam("context") String ctx,
@QueryParam("cutoff") Boolean cutoff,
@QueryParam("count") Integer pageLength,
@QueryParam("offset") Integer pageIndex,
@QueryParam("page") Integer pageInteger,
@QueryParam("cq") String cq, @QueryParam("engine") String engine) {
TokenContext context = (TokenContext) securityContext
.getUserPrincipal();
KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
User user;
try {
user = controller.getUser(context.getUsername());
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
String result;
QuerySerializer serializer = new QuerySerializer();
serializer.setQuery(q, ql, v);
if (cq != null)
serializer.setCollection(cq);
MetaQueryBuilder meta = new MetaQueryBuilder();
meta.addEntry("startIndex", pageIndex);
meta.addEntry("startPage", pageInteger);
meta.setSpanContext(ctx);
meta.addEntry("count", pageLength);
// todo: what happened to cutoff?
meta.addEntry("cutoff", cutoff);
// meta.addMeta(pageIndex, pageInteger, pageLength, ctx, cutoff);
// fixme: should only apply to CQL queries per default!
// meta.addEntry("itemsPerResource", 1);
serializer.setMeta(meta.raw());
String query;
try {
query = this.processor.processQuery(serializer.toJSON(), user);
}
catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
jlog.info("the serialized query {}", query);
if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
MultivaluedMap map = new MultivaluedMapImpl();
map.add("q", query);
map.add("count", String.valueOf(pageLength));
map.add("lctxs",
String.valueOf(meta.getSpanContext().getLeftSize()));
map.add("rctxs",
String.valueOf(meta.getSpanContext().getRightSize()));
try {
result = this.graphDBhandler.getResponse(map, "distKwic");
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
}
else
result = searchKrill.search(query);
KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
return Response.ok(result).build();
}
/**
* String search, String ql, List<String> parents,
* String cli, String cri, int cls, int crs,
* int num, int page, boolean cutoff)
* param context will be like this: context: "3-t,2-c"
* <p/>
* id does not have to be an integer. name is also possible, in
* which case a type reference is required
*
* @param securityContext
* @param locale
* @return
*/
// todo: remove raw
@GET
@Path("/{type}/{id}/search")
public Response searchbyName (@Context SecurityContext securityContext,
@Context Locale locale, @QueryParam("q") String query,
@QueryParam("ql") String ql, @QueryParam("v") String v,
@QueryParam("context") String ctx,
@QueryParam("cutoff") Boolean cutoff,
@QueryParam("count") Integer pageLength,
@QueryParam("offset") Integer pageIndex,
@QueryParam("page") Integer pageInteger,
@PathParam("id") String id, @PathParam("type") String type,
@QueryParam("cq") String cq, @QueryParam("raw") Boolean raw,
@QueryParam("engine") String engine) {
// ref is a virtual collection id!
TokenContext context = (TokenContext) securityContext
.getUserPrincipal();
KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
type = StringUtils.normalize(type);
id = StringUtils.decodeHTML(id);
raw = raw == null ? false : raw;
try {
User user = controller.getUser(context.getUsername());
MetaQueryBuilder meta = new MetaQueryBuilder();
if (!raw) {
QuerySerializer s = new QuerySerializer();
s.setQuery(query, ql, v);
KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
KustvaktResource resource;
if (StringUtils.isInteger(id))
resource = this.resourceHandler.findbyIntId(
Integer.valueOf(id), user);
else
resource = this.resourceHandler.findbyStrId(id, user,
ResourceFactory.getResourceClass(type));
if (resource instanceof VirtualCollection)
builder.setBaseQuery(resource.getData());
else if (resource instanceof Corpus)
builder.with(Attributes.CORPUS_SIGLE
+ resource.getPersistentID());
else
throw KustvaktResponseHandler.throwit(
StatusCodes.ILLEGAL_ARGUMENT,
"Type parameter not supported", type);
meta.addEntry("startIndex", pageIndex);
meta.addEntry("startPage", pageInteger);
meta.setSpanContext(ctx);
meta.addEntry("count", pageLength);
// todo: what happened to cutoff?
meta.addEntry("cutoff", cutoff);
// should only apply to CQL queries
// meta.addEntry("itemsPerResource", 1);
s.setMeta(meta.raw());
query = s.toJSON();
}
String result;
try {
// rewrite process
query = this.processor.processQuery(query, user);
if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
if (raw)
throw KustvaktResponseHandler.throwit(
StatusCodes.ILLEGAL_ARGUMENT,
"raw not supported!", null);
MultivaluedMap map = new MultivaluedMapImpl();
map.add("q", query);
map.add("count", String.valueOf(pageLength));
map.add("lctxs",
String.valueOf(meta.getSpanContext().getLeftSize()));
map.add("rctxs", String.valueOf(meta.getSpanContext()
.getRightSize()));
result = this.graphDBhandler.getResponse(map, "distKwic");
}
else
result = searchKrill.search(query);
}
catch (Exception e) {
jlog.error("Exception for serialized query: " + query, e);
throw KustvaktResponseHandler
.throwit(500, e.getMessage(), null);
}
KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
return Response.ok(result).build();
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
}
@POST
@Path("stats")
public Response getStats (@Context SecurityContext context,
@Context Locale locale, String json) {
KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
builder.with(json);
String stats = searchKrill.getStatistics(builder.toJSON());
if (stats.contains("-1"))
throw KustvaktResponseHandler.throwit(StatusCodes.EMPTY_RESULTS);
return Response.ok(stats).build();
}
@GET
@Path("{type}/{id}/{child}/stats")
public Response getStatisticsbyIdChild (@Context SecurityContext context,
@Context Locale locale, @PathParam("type") String type,
@PathParam("id") String id, @PathParam("child") String child) {
return getStatisticsbyId(context, locale, type,
StringUtils.joinResources(id, child));
}
@GET
@Path("{type}/{id}/stats")
public Response getStatisticsbyId (@Context SecurityContext context,
@Context Locale locale, @PathParam("type") String type,
@PathParam("id") String id) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
type = StringUtils.normalize(type);
id = StringUtils.decodeHTML(id);
Class sl = ResourceFactory.getResourceClass(type);
if (!VirtualCollection.class.equals(sl) & !Corpus.class.equals(sl))
throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
"Requested Resource type not supported", type);
try {
User user = controller.getUser(ctx.getUsername());
KustvaktResource resource;
if (StringUtils.isInteger(id))
resource = this.resourceHandler.findbyIntId(
Integer.valueOf(id), user);
else
resource = this.resourceHandler.findbyStrId(id, user,
ResourceFactory.getResourceClass(type));
//todo ?!
KoralCollectionQueryBuilder query = new KoralCollectionQueryBuilder();
if (resource instanceof VirtualCollection) {
query.setBaseQuery(resource.getData());
}
else if (resource instanceof Corpus) {
query.with(Attributes.CORPUS_SIGLE + "=" + resource.getName());
}
String res = query.toJSON();
String qstr = processor.processQuery(res, user);
return Response.ok(searchKrill.getStatistics(qstr)).build();
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
}
/**
* @param context
* @param locale
* @param json
* @return
*/
//todo: rename
@POST
@Path("collection_raw")
public Response createRawCollection (@Context SecurityContext context,
@Context Locale locale, String json) {
TokenContext c = (TokenContext) context.getUserPrincipal();
VirtualCollection cache = ResourceFactory.getCachedCollection(json);
User user;
try {
user = controller.getUser(c.getUsername());
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
VirtualCollection tmp = resourceHandler.getCache(cache.getId(),
VirtualCollection.class);
if (tmp == null) {
String query;
try {
query = this.processor.processQuery(cache.getData(), user);
}
catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
String stats = searchKrill.getStatistics(query);
cache.setStats(JsonUtils.readSimple(stats, Map.class));
resourceHandler.cache(cache);
}
else
cache = tmp;
Map vals = new HashMap();
vals.put("id", cache.getId());
vals.put("statistics", cache.getStats());
return Response.ok(JsonUtils.toJSON(vals)).build();
}
@POST
@Path("{type}/{id}")
public Response updateResource (@Context SecurityContext context,
@Context Locale locale, @PathParam("type") String type,
@PathParam("id") String id, String json) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
User user;
try {
user = controller.getUser(ctx.getUsername());
KustvaktResource resource = this.resourceHandler.findbyStrId(id,
user, ResourceFactory.getResourceClass(type));
JsonNode node = JsonUtils.readTree(json);
if (node.isObject() && !node.path("name").isMissingNode()) {
String s = node.path("name").asText();
if (s.equals("null") || s.isEmpty())
throw KustvaktResponseHandler.throwit(
StatusCodes.ILLEGAL_ARGUMENT, "Name must be set",
"name");
resource.setName(s);
}
if (node.isObject() && !node.path("description").isMissingNode())
resource.setDescription(node.path("description").asText());
this.resourceHandler.updateResources(user, resource);
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
return Response.ok().build();
}
//todo: change or deprecate
@POST
@Path("nv/{type}")
public Response storeResource (@Context SecurityContext context,
@Context Locale locale,
@PathParam("type") String type,
@QueryParam("name") String name,
@QueryParam("description") String description,
// deprecate -> if you want to store a resource based on another, build the query first yourself or via a function
@QueryParam("ref") String reference,
@QueryParam("cache") Boolean cache,
@QueryParam("query") String query) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
cache = cache != null ? cache : false;
type = StringUtils.normalize(type);
reference = StringUtils.decodeHTML(reference);
Map vals = new HashMap();
User user;
try {
user = controller.getUser(ctx.getUsername());
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
if (VirtualCollection.class.equals(ResourceFactory
.getResourceClass(type))) {
VirtualCollection cachetmp, collection;
JsonNode base;
if (reference != null && !reference.equals("null")) {
try {
base = resourceHandler.findbyStrId(reference, user,
VirtualCollection.class).getData();
}
catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
}
else if (query != null)
base = JsonUtils.readTree(query);
else
// todo: throw exception response for no resource to save!
return null;
KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
cquery.setBaseQuery(base);
cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
// see if collection was cached!
VirtualCollection tmp = resourceHandler.getCache(cachetmp.getId(),
VirtualCollection.class);
// if not cached, fill with stats values
if (tmp == null) {
String stats = searchKrill.getStatistics(cquery.toJSON());
cachetmp.setStats(JsonUtils.readSimple(stats, Map.class));
}
if (!cache) {
collection = ResourceFactory.getPermanentCollection(cachetmp,
name, description);
vals = collection.toMap();
try {
resourceHandler.storeResources(user, collection);
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
}
else {
resourceHandler.cache(cachetmp);
vals = cachetmp.toMap();
}
}
return Response.ok(JsonUtils.toJSON(vals)).build();
}
/**
* store a virtual collection. Retrieve cached entry first and
* then store collection
*
* @param context
* @param locale
* @param query
* @return
*/
// todo: testing
@POST
@Path("{type}")
public Response storeResource (@Context SecurityContext context,
@Context Locale locale, @PathParam("type") String type,
@QueryParam("filter") Boolean filter,
@QueryParam("name") String name,
@QueryParam("description") String description,
@QueryParam("ref") String reference,
@QueryParam("cache") Boolean cache, String query) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
filter = filter != null ? filter : false;
cache = cache != null ? cache : false;
type = StringUtils.normalize(type);
reference = StringUtils.decodeHTML(reference);
Map vals = new HashMap();
User user;
try {
user = controller.getUser(ctx.getUsername());
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
if (VirtualCollection.class.equals(ResourceFactory
.getResourceClass(type))) {
VirtualCollection cachetmp, collection;
KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
if (reference != null && !reference.equals("null")) {
try {
cquery.setBaseQuery(resourceHandler.findbyStrId(reference,
user, VirtualCollection.class).getData());
}
catch (KustvaktException e) {
throw KustvaktResponseHandler.throwit(e);
}
}
if (query != null && !query.isEmpty())
cquery.with(query);
cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
// see if vc was cached!
VirtualCollection tmp = resourceHandler.getCache(cachetmp.getId(),
VirtualCollection.class);
// if not cached, fill with stats values
if (tmp == null) {
String stats = searchKrill.getStatistics(cquery.toJSON());
cachetmp.setStats(JsonUtils.readSimple(stats, Map.class));
}
if (!cache && !User.UserFactory.isDemo(ctx.getUsername())) {
collection = ResourceFactory.getPermanentCollection(cachetmp,
name, description);
vals = collection.toMap();
try {
resourceHandler.storeResources(user, collection);
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
}
else {
resourceHandler.cache(cachetmp);
vals = cachetmp.toMap();
}
}
return Response.ok(JsonUtils.toJSON(vals)).build();
}
@DELETE
@Path("{type}/{id}/{child}")
public Response deleteResourceChild (@Context SecurityContext context,
@Context Locale locale, @PathParam("type") String type,
@PathParam("id") String id, @PathParam("child") String child) {
return deleteResource(context, locale, type,
StringUtils.joinResources(id, child));
}
@DELETE
@Path("{type}/{id}")
public Response deleteResource (@Context SecurityContext context,
@Context Locale locale, @PathParam("type") String type,
@PathParam("id") String id) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
type = StringUtils.normalizeHTML(type);
id = StringUtils.decodeHTML(id);
try {
User user = controller.getUser(ctx.getUsername());
KustvaktResource r = ResourceFactory.getResource(type);
r.setPersistentID(id);
//todo: eliminate the need to find the resource first!
resourceHandler.deleteResources(user, r);
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
return Response.ok().build();
}
//fixme: only allowed for corpus?!
@GET
@Path("/corpus/{id}/{docid}/{rest}/matchInfo")
public Response getMatchInfo (@Context SecurityContext ctx,
@Context Locale locale, @PathParam("id") String id,
@PathParam("docid") String docid, @PathParam("rest") String rest,
@QueryParam("foundry") Set<String> foundries,
@QueryParam("layer") Set<String> layers,
@QueryParam("spans") Boolean spans) {
TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
spans = spans != null ? spans : false;
String matchid = searchKrill.getMatchId(id, docid, rest);
if (layers == null || layers.isEmpty())
layers = new HashSet<>();
boolean match_only = foundries == null || foundries.isEmpty();
User user;
try {
user = controller.getUser(tokenContext.getUsername());
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
String results;
// fixme: checks for policy matching
// fixme: currently disabled, due to mishab in foundry/layer spec
// fixme:
if (foundries != null && foundries.size() > 1000) {
Set<String> f_list = new HashSet<>();
Set<String> l_list = new HashSet<>();
for (String spl : new ArrayList<>(foundries)) {
try {
de.ids_mannheim.korap.security.ac.SecurityManager manager = SecurityManager
.init(spl, user, Permissions.Permission.READ);
if (!manager.isAllowed())
continue;
String[] sep = StringUtils.splitAnnotations(spl);
if (spl != null) {
f_list.add(sep[0]);
l_list.add(sep[1]);
}
results = searchKrill.getMatch(matchid, new ArrayList<>(
f_list), new ArrayList<>(l_list), spans, false,
true);
}
catch (EmptyResultException e) {
throw KustvaktResponseHandler.throwit(
StatusCodes.EMPTY_RESULTS, "Resource not found!",
id);
}
catch (NotAuthorizedException e) {
throw KustvaktResponseHandler.throwit(
StatusCodes.PERMISSION_DENIED, "Permission denied",
id);
}
}
// all foundries shall be returned
}
else if (foundries != null && foundries.contains("*")) {
Set<Layer> resources;
try {
resources = ResourceFinder.search(user, Layer.class);
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
// returns foundries and layers.
// todo: needs testing!
foundries = new HashSet<>();
layers = new HashSet<>();
for (Layer r : resources) {
String[] spl = StringUtils.splitAnnotations(r.getName());
if (spl != null) {
foundries.add(spl[0]);
layers.add(spl[1]);
}
}
}
try {
if (!match_only)
results = searchKrill
.getMatch(matchid, new ArrayList<>(foundries),
new ArrayList<>(layers), spans, false, true);
else
results = searchKrill.getMatch(matchid);
}
catch (Exception e) {
jlog.error("Exception encountered!", e);
throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
e.getMessage(), "");
}
return Response.ok(results).build();
}
// todo:?!
@POST
@Path("match/{id}")
@Deprecated
public Response save (@PathParam("{id}") String id,
@QueryParam("d") String description,
@Context SecurityContext context) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
// save match for user and later retrieval!
// KustvaktResource match = new QueryMatch(id);
// match.setDescription(description);
// match.setCreated(TimeUtils.getNow().getMillis());
// try {
// this.resourceHandler.storeResources(controller.getUser(ctx), match);
// } catch (KustvaktException | NotAuthorizedException e) {
// throw MappedHTTPResponse.throwit(e);
// }
return Response.ok().build();
}
@GET
@Path("matches")
@Deprecated
public Response get (@Context SecurityContext context) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
//todo save match for user and later retrieval!
//todo: retrieve matches in range! --choices: date, document, id (matchid)
return Response.ok().build();
}
@DELETE
@Path("match/{id}")
@Deprecated
public Response remove (@PathParam("{id}") String id,
@Context SecurityContext context) {
TokenContext ctx = (TokenContext) context.getUserPrincipal();
// save match for user and later retrieval!
try {
this.resourceHandler.deleteResources(
this.controller.getUser(ctx.getUsername()), id);
}
catch (KustvaktException e) {
jlog.error("Exception encountered: {}", e.string());
throw KustvaktResponseHandler.throwit(e);
}
return Response.ok().build();
}
}