/**
 * Copyright (C) 2011-2015 Incapture Technologies LLC
 *
 * This is an autogenerated license statement. When copyright notices appear below
 * this one that copyright supercedes this statement.
 *
 * Unless required by applicable law or agreed to in writing, software is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied.
 *
 * Unless explicit permission obtained in writing this software cannot be distributed.
 */
package rapture.dp.invocable.ftp.steps;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.google.common.collect.ImmutableList;

import rapture.common.CallingContext;
import rapture.common.RaptureURI;
import rapture.common.RaptureURIInputStream;
import rapture.common.RaptureURIOutputStream;
import rapture.common.Scheme;
import rapture.common.api.DecisionApi;
import rapture.common.dp.AbstractInvocable;
import rapture.common.exception.ExceptionToString;
import rapture.common.impl.jackson.JacksonUtil;
import rapture.kernel.Kernel;
import rapture.kernel.dp.ExecutionContextUtil;

public class CopyFileStep extends AbstractInvocable {
    private static final Logger log = Logger.getLogger(CopyFileStep.class);

    DecisionApi decision;
    public CopyFileStep(String workerUri, String stepName) {
        super(workerUri, stepName);
        decision = Kernel.getDecision();
    }

    public boolean copy(String localName, String remoteName) {
        InputStream inStream;
        try {
            if (localName.startsWith("file://")) {
                localName = localName.substring(6);
            }
            if (localName.startsWith("//")) {
                inStream = new RaptureURIInputStream(new RaptureURI(localName, Scheme.DOCUMENT));
            } else if (localName.contains("://")) {
                inStream = new RaptureURIInputStream(new RaptureURI(localName));
            } else {
                inStream = new FileInputStream(new File(localName));
            }

            OutputStream outStream;
            if (remoteName.startsWith("file://")) {
                remoteName = remoteName.substring(6);
            }
            if (remoteName.startsWith("//")) {
                outStream = new RaptureURIOutputStream(new RaptureURI(remoteName, Scheme.DOCUMENT));
            } else if (remoteName.contains("://")) {
                outStream = new RaptureURIOutputStream(new RaptureURI(remoteName));
            } else {
                Path target = Paths.get(remoteName);
                Files.createDirectories(target.getParent());
                outStream = new FileOutputStream(target.toFile());
            }
            IOUtils.copy(inStream, outStream);
            outStream.close();
            inStream.close();
            return true;
        } catch (IOException e) {
            log.debug(ExceptionToString.format(e));
            return false;
        }
    }

    public String renderTemplate(CallingContext ctx, String template) {
        String workOrder = new RaptureURI(getWorkerURI()).toShortString();
        return ExecutionContextUtil.evalTemplateECF(ctx, workOrder, template, new HashMap<String, String>());
    }

    @Override
    public String invoke(CallingContext ctx) {

        String ftpStatus = StringUtils.stripToNull(Kernel.getDecision().getContextValue(ctx, getWorkerURI(), "FTP_STATUS"));
        String copy = StringUtils.stripToNull(Kernel.getDecision().getContextValue(ctx, getWorkerURI(), "COPY_FILES"));
        if (copy == null) {
            Kernel.getDecision().setContextLiteral(ctx, getWorkerURI(), "FTP_STATUS", ftpStatus + " " + getStepName() + ":No files to copy ");
            return getNextTransition();
        }

        Map<String, Object> map = JacksonUtil.getMapFromJson(renderTemplate(ctx, copy));

        String retval = getNextTransition();
        int failCount = 0;
        List<Entry<String, Object>> list = new ArrayList<>();
        for (Entry<String, Object> e : map.entrySet()) {
            String value = e.getValue().toString();
            List<String> targets;
            try {
                targets = JacksonUtil.objectFromJson(value, List.class);
            } catch (Exception ex) {
                targets = ImmutableList.of(value);
            }
            for (String target : targets) {
                if (!copy(e.getKey(), target)) {
                    log.warn("Unable to copy " + e.getKey());
                    retval = getFailTransition();
                    failCount++;
                    list.add(e);
                }
            }
        }
        if (failCount > 0) log.error("Unable to copy " + failCount + " files)");
        return retval;
    }

}

@@ -1671,16 +1671,53 @@
 ecision;
+%0A%0A    private CallingContext context;
 %0A    pub
@@ -2754,32 +2754,52 @@
 cheme.DOCUMENT))
+.setContext(context)
 ;%0A            %7D 
@@ -2915,24 +2915,44 @@
 remoteName))
+.setContext(context)
 ;%0A          
@@ -3744,16 +3744,43 @@
  ctx) %7B%0A
+        this.context = ctx;
 %0A       

Set context in copy file step