class ArtefactFunctionHandler extends JsonBasedFunctionHandler {

	@Override
	protected Output<JsonObject> handle(Input<JsonObject> input) {
		OutputBuilder output = new OutputBuilder();

		ExecutionContext executionContext = (ExecutionContext) getTokenReservationSession().get(AbstractFunctionHandler.EXECUTION_CONTEXT_KEY);
		
		if(executionContext == null) {
			output.setError("Running composite Keyword on agent not supported. Please change the keyword configuration accordingly.");
		} else {
			String planId = input.getProperties().get(PLANID_KEY);
			String parentReportId = input.getProperties().get(AbstractFunctionHandler.PARENTREPORTID_KEY);
			
			ReportNode parentNode;
			if(parentReportId!=null) {
				parentNode = executionContext.getReportNodeAccessor().get(parentReportId);
				if(parentNode == null) {
					parentNode = executionContext.getCurrentReportNode();
				}
			} else {
				parentNode = executionContext.getCurrentReportNode();
				//throw new RuntimeException("Parent node id is null. This should never occur");
			}
			
			ReportNode previousCurrentNode = executionContext.getCurrentReportNode();
			executionContext.setCurrentReportNode(parentNode);
			executionContext.getReportNodeCache().put(parentNode);
			
			AbstractArtefact artefact = executionContext.getPlanAccessor().get(planId).getRoot();
			
			executionContext.getVariablesManager().putVariable(parentNode, INPUT, input.getPayload());
			executionContext.getVariablesManager().putVariable(parentNode, VariableType.IMMUTABLE, OUTPUT, output);
			
			try {
				ReportNode node = executionContext.getArtefactHandlerManager().execute(artefact, parentNode);
				if(node.getStatus()== ReportNodeStatus.TECHNICAL_ERROR || node.getStatus()== ReportNodeStatus.FAILED) {
					Error error = new Error();
					error.setCode(0);
					error.setMsg("Error in composite keyword");
					error.setRoot(false);
					error.setType(node.getStatus().equals(ReportNodeStatus.FAILED)?ErrorType.BUSINESS:ErrorType.TECHNICAL);
					output.setError(error);
				}
			} finally {
				executionContext.getVariablesManager().removeVariable(parentNode, OUTPUT);
				executionContext.setCurrentReportNode(previousCurrentNode);
			}
		}
		
		return output.build();
	}

}