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 */ 020 021package org.nuxeo.ecm.platform.routing.core.io; 022 023import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; 024import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 025import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 026 027import java.io.Closeable; 028import java.io.IOException; 029import java.io.OutputStream; 030import javax.inject.Inject; 031import org.apache.commons.lang.StringUtils; 032import org.codehaus.jackson.JsonGenerationException; 033import org.codehaus.jackson.JsonGenerator; 034import org.nuxeo.ecm.core.api.IdRef; 035import org.nuxeo.ecm.core.api.NuxeoPrincipal; 036import org.nuxeo.ecm.core.api.model.Property; 037import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; 038import org.nuxeo.ecm.core.io.marshallers.json.OutputStreamWithJsonWriter; 039import org.nuxeo.ecm.core.io.marshallers.json.document.DocumentModelJsonWriter; 040import org.nuxeo.ecm.core.io.registry.MarshallerRegistry; 041import org.nuxeo.ecm.core.io.registry.Writer; 042import org.nuxeo.ecm.core.io.registry.context.RenderingContext; 043import org.nuxeo.ecm.core.io.registry.context.RenderingContext.SessionWrapper; 044import org.nuxeo.ecm.core.io.registry.reflect.Setup; 045import org.nuxeo.ecm.core.schema.SchemaManager; 046import org.nuxeo.ecm.core.schema.types.CompositeType; 047import org.nuxeo.ecm.core.schema.types.Field; 048import org.nuxeo.ecm.platform.routing.api.DocumentRoute; 049import org.nuxeo.ecm.platform.routing.core.impl.GraphRoute; 050import org.nuxeo.ecm.platform.usermanager.UserManager; 051 052/** 053 * @since 7.2 054 */ 055@Setup(mode = SINGLETON, priority = REFERENCE) 056public class DocumentRouteWriter extends ExtensibleEntityJsonWriter<DocumentRoute> { 057 058 public static final String ATTACHED_DOCUMENT_IDS = "attachedDocumentIds"; 059 060 public static final String FETCH_ATTACHED_DOCUMENTS = ATTACHED_DOCUMENT_IDS; 061 062 public static final String ENTITY_TYPE = "workflow"; 063 064 public static final String FETCH_INITATIOR = "initiator"; 065 066 @Inject 067 UserManager userManager; 068 069 @Inject 070 private SchemaManager schemaManager; 071 072 public DocumentRouteWriter() { 073 super(ENTITY_TYPE, DocumentRoute.class); 074 } 075 076 @Override 077 protected void writeEntityBody(DocumentRoute item, JsonGenerator jg) throws IOException { 078 jg.writeStringField("id", item.getDocument().getId()); 079 jg.writeStringField("name", item.getName()); 080 jg.writeStringField("title", item.getTitle()); 081 jg.writeStringField("state", item.getDocument().getCurrentLifeCycleState()); 082 jg.writeStringField("workflowModelName", item.getModelName()); 083 if (ctx.getFetched(ENTITY_TYPE).contains(FETCH_INITATIOR)) { 084 NuxeoPrincipal principal = userManager.getPrincipal(item.getInitiator()); 085 if (principal != null) { 086 writeEntityField("initiator", principal, jg); 087 } else { 088 jg.writeStringField("initiator", item.getInitiator()); 089 } 090 } else { 091 jg.writeStringField("initiator", item.getInitiator()); 092 } 093 094 jg.writeArrayFieldStart(ATTACHED_DOCUMENT_IDS); 095 try (SessionWrapper wrapper = ctx.getSession(item.getDocument())) { 096 final boolean isFetchAttachedDocumentIds = ctx.getFetched(ENTITY_TYPE).contains(FETCH_ATTACHED_DOCUMENTS); 097 for (String docId : item.getAttachedDocuments()) { 098 if (isFetchAttachedDocumentIds) { 099 IdRef idRef = new IdRef(docId); 100 if (wrapper.getSession().exists(idRef)) { 101 writeEntity(wrapper.getSession().getDocument(idRef), jg); 102 break; 103 } 104 } 105 jg.writeStartObject(); 106 jg.writeStringField("id", docId); 107 jg.writeEndObject(); 108 } 109 } 110 jg.writeEndArray(); 111 112 if (item instanceof GraphRoute) { 113 jg.writeFieldName("variables"); 114 jg.writeStartObject(); 115 116 writeVariables(item, jg, registry, ctx, schemaManager); 117 118 jg.writeEndObject(); 119 String graphResourceUrl = ""; 120 if (item.isValidated()) { 121 // it is a model 122 graphResourceUrl = ctx.getBaseUrl() + "api/v1/workflowModel/" + item.getDocument().getName() + "/graph"; 123 } else { 124 // it is an instance 125 graphResourceUrl = ctx.getBaseUrl() + "api/v1/workflow/" + item.getDocument().getId() + "/graph"; 126 } 127 jg.writeStringField("graphResource", graphResourceUrl); 128 } 129 } 130 131 /** 132 * @since 8.3 133 */ 134 public static void writeVariables(DocumentRoute item, JsonGenerator jg, MarshallerRegistry registry, 135 RenderingContext ctx, SchemaManager schemaManager) throws IOException, JsonGenerationException { 136 String facet = (String) item.getDocument().getPropertyValue(GraphRoute.PROP_VARIABLES_FACET); 137 if (StringUtils.isNotBlank(facet)) { 138 139 CompositeType type = schemaManager.getFacet(facet); 140 if (type != null) { 141 boolean hasFacet = item.getDocument().hasFacet(facet); 142 143 Writer<Property> propertyWriter = registry.getWriter(ctx, Property.class, APPLICATION_JSON_TYPE); 144 // provides the current route to the property marshaller 145 try (Closeable resource = ctx.wrap().with(DocumentModelJsonWriter.ENTITY_TYPE, 146 item.getDocument()).open()) { 147 for (Field f : type.getFields()) { 148 String name = f.getName().getLocalName(); 149 Property property = hasFacet ? item.getDocument().getProperty(name) : null; 150 OutputStream out = new OutputStreamWithJsonWriter(jg); 151 jg.writeFieldName(name); 152 propertyWriter.write(property, Property.class, Property.class, APPLICATION_JSON_TYPE, out); 153 } 154 } 155 } 156 } 157 } 158 159}