001/* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * <a href="mailto:grenard@nuxeo.com">Guillaume Renard</a> 018 * 019 */ 020package org.nuxeo.ecm.platform.routing.core.io; 021 022import static org.nuxeo.ecm.core.io.marshallers.json.document.DocumentPropertiesJsonReader.DEFAULT_SCHEMA_NAME; 023import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 024import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 025 026import java.io.Closeable; 027import java.io.IOException; 028import java.io.Serializable; 029import java.lang.reflect.ParameterizedType; 030import java.lang.reflect.Type; 031import java.util.HashMap; 032import java.util.List; 033import java.util.Map; 034 035import javax.inject.Inject; 036import javax.ws.rs.core.MediaType; 037 038import org.apache.commons.lang3.reflect.TypeUtils; 039import org.nuxeo.ecm.core.api.CoreSession; 040import org.nuxeo.ecm.core.api.DocumentModel; 041import org.nuxeo.ecm.core.api.IdRef; 042import org.nuxeo.ecm.core.api.model.Property; 043import org.nuxeo.ecm.core.io.marshallers.json.EntityJsonReader; 044import org.nuxeo.ecm.core.io.registry.context.RenderingContext.SessionWrapper; 045import org.nuxeo.ecm.core.io.registry.reflect.Setup; 046import org.nuxeo.ecm.core.schema.SchemaManager; 047import org.nuxeo.ecm.core.schema.types.CompositeType; 048import org.nuxeo.ecm.platform.routing.api.DocumentRoutingConstants; 049import org.nuxeo.ecm.platform.routing.core.impl.GraphNode; 050import org.nuxeo.ecm.platform.routing.core.impl.GraphRoute; 051import org.nuxeo.ecm.platform.task.Task; 052import org.nuxeo.runtime.api.Framework; 053 054import com.fasterxml.jackson.databind.JsonNode; 055 056/** 057 * @since 8.2 058 */ 059@Setup(mode = SINGLETON, priority = REFERENCE) 060public class TaskCompletionRequestJsonReader extends EntityJsonReader<TaskCompletionRequest> { 061 062 public static final String ENTITY_TYPE = "task"; 063 064 private static final String USE_LEGACY_CONF_KEY = "nuxeo.document.routing.json.format.legacy"; 065 066 private Boolean useLegacy = null; 067 068 @Inject 069 SchemaManager schemaManager; 070 071 public TaskCompletionRequestJsonReader() { 072 super(TaskCompletionRequestJsonReader.ENTITY_TYPE); 073 String prop = Framework.getProperty(USE_LEGACY_CONF_KEY); 074 if (prop != null && Boolean.parseBoolean(prop)) { 075 useLegacy = Boolean.TRUE; 076 } else { 077 useLegacy = Boolean.FALSE; 078 } 079 } 080 081 @Override 082 public boolean accept(Class<?> clazz, Type genericType, MediaType mediatype) { 083 return !useLegacy && !ctx.getBooleanParameter(USE_LEGACY_CONF_KEY) 084 && super.accept(clazz, genericType, mediatype); 085 } 086 087 @Override 088 public TaskCompletionRequest readEntity(JsonNode jn) throws IOException { 089 090 String comment = getStringField(jn, "comment"); 091 092 // get the task and workflow schema names 093 String nodeSchema; 094 String workflowSchema; 095 Map<String, Serializable> variables = new HashMap<>(); 096 try (SessionWrapper closeable = ctx.getSession(null)) { 097 CoreSession session = closeable.getSession(); 098 099 String taskId = getStringField(jn, "id"); 100 101 DocumentModel taskDoc = session.getDocument(new IdRef(taskId)); 102 Task task = taskDoc.getAdapter(Task.class); 103 String routeId = task.getVariable(DocumentRoutingConstants.TASK_ROUTE_INSTANCE_DOCUMENT_ID_KEY); 104 String nodeId = task.getVariable(DocumentRoutingConstants.TASK_NODE_ID_KEY); 105 106 NodeAccessRunner nar = new NodeAccessRunner(session, routeId, nodeId); 107 nar.runUnrestricted(); 108 GraphRoute graphRoute = nar.getWorkflowInstance(); 109 GraphNode node = nar.getNode(); 110 111 // get the variables 112 JsonNode variablesNode = jn.get("variables"); 113 if (variablesNode != null) { 114 String workflowSchemaFacet = (String) graphRoute.getDocument().getPropertyValue( 115 GraphRoute.PROP_VARIABLES_FACET); 116 CompositeType type = schemaManager.getFacet(workflowSchemaFacet); 117 workflowSchema = type.getSchemaNames()[0]; 118 variables.putAll(getVariables(variablesNode, workflowSchema)); 119 120 String nodeSchemaFacet = (String) node.getDocument().getPropertyValue(GraphNode.PROP_VARIABLES_FACET); 121 type = schemaManager.getFacet(nodeSchemaFacet); 122 nodeSchema = type.getSchemaNames()[0]; 123 variables.putAll(getVariables(variablesNode, nodeSchema)); 124 } 125 126 } 127 128 return new TaskCompletionRequest(comment, variables, false); 129 } 130 131 private Map<String, Serializable> getVariables(JsonNode variables, String schemaName) throws IOException { 132 Map<String, Serializable> variable = new HashMap<>(); 133 ParameterizedType genericType = TypeUtils.parameterize(List.class, Property.class); 134 try (Closeable resource = ctx.wrap().with(DEFAULT_SCHEMA_NAME, schemaName).open()) { 135 List<Property> properties = readEntity(List.class, genericType, variables); 136 for (Property property : properties) { 137 variable.put(property.getName().substring(schemaName.length() + 1), property.getValue()); 138 } 139 } 140 return variable; 141 } 142 143}