/*
* Copyright (c) 2014.
*
* BaasBox - info@baasbox.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.baasbox.commands;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.ObjectUtils;
import com.baasbox.service.logging.BaasBoxLogger;
import com.baasbox.commands.exceptions.CommandException;
import com.baasbox.commands.exceptions.CommandExecutionException;
import com.baasbox.commands.exceptions.CommandGenericError;
import com.baasbox.commands.exceptions.CommandNotSupportedException;
import com.baasbox.commands.exceptions.CommandParsingException;
import com.baasbox.dao.exception.DocumentNotFoundException;
import com.baasbox.dao.exception.SqlInjectionException;
import com.baasbox.service.scripting.js.Json;
import com.baasbox.service.storage.LinkService;
import com.baasbox.util.JSONFormats;
import com.baasbox.util.QueryParams;
import com.baasbox.util.JSONFormats.Formats;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.orientechnologies.orient.core.record.impl.ODocument;
/**
* {resource: 'links',
* name: <'get'|'list'|'post'|'delete',
* params; {
* name: <name>,
* query: <query>,*
* id: <id>*,
* sourceId: <sourceid>*,
* destId: <sourceid>*
* }}
*
*
* {resource: 'links',
* name: 'get',
* params: {
* name: <name>,
* query: <query>
* }}
*
* {resource: 'links',
* name: 'post',
* params: {
* name: <name>,
* sourceId: <sourceid>,
* destId: <sourceid>
* }}
*
*
* Created by Claudio Tesoriero on 04/12/2014
*/
class LinksResource extends BaseRestResource {
public static final Resource INSTANCE = new LinksResource();
private static final String RESOURCE_NAME = "links";
private static final String QUERY = "query";
private static final String SOURCE_ID = "sourceId";
private static final String DEST_ID = "destId";
private static final String LINK_NAME = "label";
private static final String AUTHOR = "author";
@Override
protected JsonNode delete(JsonNode command) throws CommandException {
validateHasParams(command);
String id = getLinkId(command);
ODocument link=LinkService.getLink(id);
if (link==null) return null;
LinkService.deleteLink(id);
return null;
}
@Override
protected JsonNode put(JsonNode command) throws CommandException{
throw new CommandNotSupportedException(command, "It is not possible to update a link");
}
@Override
protected JsonNode post(JsonNode command) throws CommandException{
validateHasParams(command);
String sourceId = getSourceId(command);
String destId = getDestId(command);
String edgeName = getLinkName(command);
ODocument toReturn = null;
try {
ODocument link = LinkService.createLink(sourceId, destId, edgeName);
link.save();
toReturn = (ODocument)link.getRecord().copy();
//toReturn.detach();
toReturn.field("out",(ODocument)((ODocument)(link.field("out"))).field("_node"));
toReturn.field("in",(ODocument)((ODocument)(link.field("in"))).field("_node"));
}catch (DocumentNotFoundException e){
throw new CommandGenericError(command,"Source or Destination record was not found. Hint: do you have the read grant on them? Or ids are not valid",e);
}
toReturn.detach();
String fmt=JSONFormats.prepareDocToJson(toReturn, Formats.LINK);
toReturn=null;
JsonNode node;
ObjectNode n;
try {
node = Json.mapper().readTree(fmt);
n =(ObjectNode)node;
} catch (IOException e) {
throw new CommandExecutionException(command,"error executing command: "+ExceptionUtils.getMessage(e),e);
}
n.remove(TO_REMOVE).remove("@rid");
return n;
}
private String getAuthorOverride(JsonNode command) throws CommandParsingException{
JsonNode node = command.get(ScriptCommand.PARAMS).get(AUTHOR);
if (node != null && !node.isTextual()){
throw new CommandParsingException(command,"author must be a string");
} else if (node != null){
return node.asText();
}
return null;
}
private String getSourceId(JsonNode command) throws CommandParsingException {
JsonNode node = command.get(ScriptCommand.PARAMS).get(SOURCE_ID);
if (node == null||(!node.isTextual())){
throw new CommandParsingException(command,"missing sourceId");
}
return node.asText();
}
private String getDestId(JsonNode command) throws CommandParsingException {
JsonNode node = command.get(ScriptCommand.PARAMS).get(DEST_ID);
if (node == null||(!node.isTextual())){
throw new CommandParsingException(command,"missing destId");
}
return node.asText();
}
private String getLinkName(JsonNode command) throws CommandParsingException {
JsonNode node = command.get(ScriptCommand.PARAMS).get(LINK_NAME);
if (node == null||(!node.isTextual())){
throw new CommandParsingException(command,"missing destId");
}
return node.asText();
}
@Override
protected JsonNode list(JsonNode command) throws CommandException {
validateHasParams(command);
QueryParams params = QueryParams.getParamsFromJson(command.get(ScriptCommand.PARAMS).get(QUERY));
List<ODocument> listOfLinks;
try {
listOfLinks = LinkService.getLink(params);
String s = JSONFormats.prepareDocToJson(listOfLinks, JSONFormats.Formats.LINK);
ArrayNode lst = (ArrayNode)Json.mapper().readTree(s);
lst.forEach((j)->((ObjectNode)j).remove(TO_REMOVE).remove("@rid"));
StreamSupport.stream(lst.spliterator(),false)
.flatMap(x -> Stream.of(x.get("in"),x.get("out")))
.filter(x -> x instanceof ObjectNode)
.forEach(x -> ((ObjectNode)x).remove(TO_REMOVE).remove("@rid"));
return lst;
} catch (SqlInjectionException | IOException e) {
throw new CommandExecutionException(command,"error executing command: "+ExceptionUtils.getMessage(e),e);
}
}
@Override
protected JsonNode get(JsonNode command) throws CommandException{
validateHasParams(command);
String id = getLinkId(command);
ODocument link=LinkService.getLink(id);
if (link==null) return null;
ObjectNode node=null;
String s = JSONFormats.prepareDocToJson(link, JSONFormats.Formats.LINK);
try {
node = (ObjectNode)Json.mapper().readTree(s);
node.remove(TO_REMOVE).remove("@rid");
((ObjectNode)node.get("in")).remove(TO_REMOVE).remove("@rid");
((ObjectNode)node.get("out")).remove(TO_REMOVE).remove("@rid");
} catch ( IOException e) {
throw new CommandExecutionException(command,"error executing command: "+ExceptionUtils.getMessage(e),e);
}
return node;
}
private String getLinkId(JsonNode command) throws CommandException{
JsonNode params = command.get(ScriptCommand.PARAMS);
JsonNode id = params.get("id");
if (id==null||!id.isTextual()){
throw new CommandParsingException(command,"missing link id");
}
String idString = id.asText();
return idString;
}
@Override
public String name() {
return RESOURCE_NAME;
}
}