class FormProviderServiceImpl implements FormProviderService {

    @Override
    @SuppressWarnings("unchecked")
    public String getFormDisplayTask(long taskId) {
        Task task = taskService.execute(new GetUserTaskCommand(identityProvider.getName(), taskId));
        if (task == null) {
            return "";
        }
        String name = task.getName();
        final String deploymentId = task.getTaskData().getDeploymentId();
        final String processId = task.getTaskData().getProcessId();
        ProcessDefinition processDesc = null;
        if(deploymentId != null && processId != null) {
            processDesc = dataService.getProcessesByDeploymentIdProcessId(deploymentId, processId);
        }
        Map<String, Object> renderContext = new HashMap<String, Object>();

        ContentMarshallerContext marshallerContext = getMarshallerContext(task);
        // read task variables
        Object input = null;
        long inputContentId = task.getTaskData().getDocumentContentId();
        if (inputContentId != -1) {
            Content content = taskService.getContentById(inputContentId);
            input = ContentMarshallerHelper.unmarshall(content.getContent(), marshallerContext.getEnvironment(), marshallerContext.getClassloader());
        }
        if (input == null) {
            input = new HashMap<String, Object>();
        }

        Object output = null;
        long outputContentId = task.getTaskData().getOutputContentId();
        if (outputContentId != -1) {
            Content content = taskService.getContentById(outputContentId);
            output = ContentMarshallerHelper.unmarshall(content.getContent(), marshallerContext.getEnvironment(), marshallerContext.getClassloader());
        }
        if (output == null) {
            output = new HashMap<String, Object>();
        }

        // prepare task variables for rendering
        Map<String, Object> finalOutput = new HashMap<String, Object>();

        if (processId != null && !processId.equals("")) {
            // If task has an associated process let's merge the outputs
            Map<String, String> taskOutputMappings = bpmn2Service.getTaskOutputMappings(deploymentId, processId, task.getName());
            if (taskOutputMappings == null) {
                taskOutputMappings = new HashMap<String, String>();
            }

            // I need to replace the value that comes from the
            //process mappings with the value that can be stored in the output Content
            for (String key : taskOutputMappings.keySet()) {
                Object value = ((Map<String, Object>) output).get(key);
                if (value == null) {
                    value = "";
                }
                finalOutput.put(key, value);
            }

        } else if (output instanceof Map && !((Map)output).isEmpty()) {
            // If the task doesn't belongs to any project BUT it has outputs let's add them directly to the rendering context.
            finalOutput.putAll( (Map<String, Object>) output );
        }

        // merge template with process variables
        renderContext.put("task", task);
        renderContext.put("marshallerContext", marshallerContext);

        // add all inputs as direct entries
        if (input instanceof Map) {
            renderContext.put("inputs", input);
            for (Map.Entry<String, Object> inputVar : ((Map<String, Object>) input).entrySet()) {
                renderContext.put(inputVar.getKey(), inputVar.getValue());
            }
        } else {
            renderContext.put("input", input);
        }

        // add all outputs as direct entries
        renderContext.put("outputs", finalOutput);
        for (Map.Entry<String, Object> outputVar : ((Map<String, Object>) finalOutput).entrySet()) {
            renderContext.put(outputVar.getKey(), outputVar.getValue());
        }

        // find form
        for (FormProvider provider : providers) {
            String template = provider.render(name, task, processDesc, renderContext);
            if (!StringUtils.isEmpty(template)) {
                return template;
            }
        }

        logger.warn("Unable to find form to render for task '{}' on process '{}'", name, processDesc == null ? "" : processDesc.getName());
        return "";
    }

}