au.org.ands.vocabs.toolkit.tasks.TaskRunner.java Source code

Java tutorial

Introduction

Here is the source code for au.org.ands.vocabs.toolkit.tasks.TaskRunner.java

Source

/** See the file "LICENSE" for the full license governing this code. */
package au.org.ands.vocabs.toolkit.tasks;

import java.lang.invoke.MethodHandles;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.TimeZone;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import au.org.ands.vocabs.toolkit.db.TaskUtils;
import au.org.ands.vocabs.toolkit.db.model.Task;
import au.org.ands.vocabs.toolkit.provider.harvest.HarvestProvider;
import au.org.ands.vocabs.toolkit.provider.harvest.HarvestProviderUtils;
import au.org.ands.vocabs.toolkit.provider.importer.ImporterProvider;
import au.org.ands.vocabs.toolkit.provider.importer.ImporterProviderUtils;
import au.org.ands.vocabs.toolkit.provider.publish.PublishProvider;
import au.org.ands.vocabs.toolkit.provider.publish.PublishProviderUtils;
import au.org.ands.vocabs.toolkit.provider.transform.TransformProvider;
import au.org.ands.vocabs.toolkit.provider.transform.TransformProviderUtils;
import au.org.ands.vocabs.toolkit.utils.ToolkitFileUtils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/** Top level runner for tasks. */
public class TaskRunner {

    /** Logger for this class. */
    private Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    /** The TaskInfo object for this task. */
    private TaskInfo taskInfo;

    /** The Task object for this task. */
    private Task task;

    /** Status of the task. */
    private String status;

    /** The results of running the task. */
    private HashMap<String, String> results = new HashMap<String, String>();

    /** Constructor.
     * @param aTaskInfo The TaskInfo structure describing this task.
     */
    public TaskRunner(final TaskInfo aTaskInfo) {
        taskInfo = aTaskInfo;
    }

    /** Get the task status.
     * @return The task status.
     */
    public final String getStatus() {
        return status;
    }

    /** Run the task.
     */
    public final void runTask() {
        status = TaskStatus.SUCCESS;
        task = taskInfo.getTask();
        results.put("task_id", task.getId().toString());
        ArrayNode subtasks = TaskUtils.getSubtasks(task.getParams());
        if (subtasks == null || subtasks.size() == 0) {
            status = TaskStatus.ERROR;
            results.put("runTask", "No subtasks specified, or invalid" + " format.");
            addTimestamp(results);
            TaskUtils.updateMessageAndTaskStatus(logger, task, results, status,
                    "No subtasks specified. Nothing to do.");
            return;
        }
        boolean success = false;
        for (JsonNode subtask : subtasks) {
            logger.debug("Got subtask: " + subtask.toString());
            if (!(subtask instanceof ObjectNode)) {
                logger.error("runTask() didn't get an object:" + subtask.toString());
                status = TaskStatus.ERROR;
                addTimestamp(results);
                TaskUtils.updateMessageAndTaskStatus(logger, task, results, status, "Bad subtask specification.");
                return;
            }
            logger.debug("subtask type: " + subtask.get("type"));
            String thisTask = subtask.get("type").textValue();
            switch (thisTask) {
            case "HARVEST":
            case "UNHARVEST":
                success = runHarvest(subtask, thisTask);
                break;
            case "TRANSFORM":
            case "UNTRANSFORM":
                success = runTransform(subtask, thisTask);
                break;
            case "IMPORT":
            case "UNIMPORT":
                success = runImport(subtask, thisTask);
                break;
            case "PUBLISH":
            case "UNPUBLISH":
                success = runPublish(subtask, thisTask);
                break;
            //                case "DELETE":
            //                    success = runDelete(subtask);
            //                    break;
            default:
                status = TaskStatus.ERROR;
                results.put("invalid_sub_task", thisTask);
                TaskUtils.updateMessageAndTaskStatus(logger, task, results, status,
                        "Invalid subtask specification.");
                break;
            }
            if (!success) {
                logger.error("ERROR while running task: " + thisTask);
                results.put("error_subtask", thisTask);
                status = TaskStatus.ERROR;
                addTimestamp(results);
                TaskUtils.updateMessageAndTaskStatus(logger, task, results, status, "Error in subtask.");
                return;
            }
        }
        status = TaskStatus.SUCCESS;
        results.put("output_path", ToolkitFileUtils.getTaskOutputPath(taskInfo, null));
        addTimestamp(results);
        TaskUtils.updateMessageAndTaskStatus(logger, task, results, status, "All tasks completed.");
    }

    /** Run a harvest.
     * @param subtask Details of the subtask
     * @param taskType The type of harvest operation to be performed.
     * @return True, iff the harvest was successful.
     */
    public final boolean runHarvest(final JsonNode subtask, final String taskType) {
        HarvestProvider provider;
        String providerName = subtask.get("provider_type").textValue();
        logger.debug("runHarvest, task type: " + taskType);
        status = taskType + "ING";
        TaskUtils.updateMessageAndTaskStatus(logger, task, results, status, "Harvest in progress");
        try {
            provider = HarvestProviderUtils.getProvider(providerName);
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            logger.error("runHarvest exception: ", e);
            results.put(TaskStatus.EXCEPTION, e.toString());
            return false;
        }

        if (provider == null) {
            status = TaskStatus.ERROR;
            TaskUtils.updateMessageAndTaskStatus(logger, task, results, status,
                    "Could not find Provider: " + providerName);
            return false;
        }
        switch (taskType) {
        case "HARVEST":
            return provider.harvest(taskInfo, subtask, results);
        case "UNHARVEST":
            return provider.unharvest(taskInfo, subtask, results);
        default:
            return false;
        }
    }

    /** Run a transform.
     * @param subtask Details of the subtask
     * @param taskType The type of transform operation to be performed.
     * @return True, iff the transform was successful.
     */
    public final boolean runTransform(final JsonNode subtask, final String taskType) {
        logger.debug("runTransform");
        TransformProvider provider;
        String providerName = subtask.get("provider_type").textValue();
        status = "TRANSFORMING";
        TaskUtils.updateMessageAndTaskStatus(logger, task, results, status, "Import in progress");
        try {
            provider = TransformProviderUtils.getProvider(providerName);
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            logger.error("runTransform exception: ", e);
            results.put(TaskStatus.EXCEPTION, e.toString());
            return false;
        }

        if (provider == null) {
            status = TaskStatus.ERROR;
            TaskUtils.updateMessageAndTaskStatus(logger, task, results, status,
                    "Could not find Provider: " + providerName);
            return false;
        }
        switch (taskType) {
        case "TRANSFORM":
            return provider.transform(taskInfo, subtask, results);
        case "UNTRANSFORM":
            return provider.untransform(taskInfo, subtask, results);
        default:
            return false;
        }
    }

    /** Run an import operation.
     * @param subtask Details of the subtask
     * @param taskType The type of import operation to be performed.
     * @return True, iff the import was successful.
     */
    public final boolean runImport(final JsonNode subtask, final String taskType) {
        ImporterProvider provider;
        String providerName = subtask.get("provider_type").textValue();
        logger.debug("runImport, task type: " + taskType);
        status = taskType + "ING";
        TaskUtils.updateMessageAndTaskStatus(logger, task, results, status, "Import in progress");
        try {
            provider = ImporterProviderUtils.getProvider(providerName);
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            logger.error("runImport exception: ", e);
            results.put(TaskStatus.EXCEPTION, e.toString());
            return false;
        }

        if (provider == null) {
            status = TaskStatus.ERROR;
            TaskUtils.updateMessageAndTaskStatus(logger, task, results, status,
                    "Could not find Provider: " + providerName);
            return false;
        }
        switch (taskType) {
        case "IMPORT":
            return provider.doImport(taskInfo, subtask, results);
        case "UNIMPORT":
            return provider.unimport(taskInfo, subtask, results);
        default:
            return false;
        }
    }

    /** Run a publish operation.
     * @param subtask Details of the subtask
     * @param taskType The type of publish operation to be performed.
     * @return True, iff the publish was successful.
     */
    public final boolean runPublish(final JsonNode subtask, final String taskType) {
        PublishProvider provider;
        String providerName = subtask.get("provider_type").textValue();
        logger.debug("runPublish, task type: " + taskType);
        status = taskType + "ING";
        TaskUtils.updateMessageAndTaskStatus(logger, task, results, status, "Import in progress");
        try {
            provider = PublishProviderUtils.getProvider(providerName);
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            logger.error("runPublish exception: ", e);
            results.put(TaskStatus.EXCEPTION, e.toString());
            return false;
        }

        if (provider == null) {
            status = TaskStatus.ERROR;
            TaskUtils.updateMessageAndTaskStatus(logger, task, results, status,
                    "Could not find Provider: " + providerName);
            return false;
        }
        switch (taskType) {
        case "PUBLISH":
            return provider.publish(taskInfo, subtask, results);
        case "UNPUBLISH":
            return provider.unpublish(taskInfo, subtask, results);
        default:
            return false;
        }
    }

    // Possible future work: support a "DELETE" task type.
    //    /** Run a Delete.
    //     * @param subtask Details of the subtask
    //     * @return True, iff the deleting was successful.
    //     */
    //    public final boolean runDelete(final JsonNode subtask) {
    //        logger.debug("runDelete");
    //        return true;
    //    }

    /** Format to use for timestamps. */
    private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    /**
     * Add a timestamp to the results map.
     * @param resultsMap The results map to which the timestamp is to be added.
     */
    public final void addTimestamp(final HashMap<String, String> resultsMap) {
        final SimpleDateFormat dateFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

        // In case you need to undo the conversion in some other part
        // of the code, here's how to do it:
        //        final SimpleDateFormat dateFormat =
        //                new SimpleDateFormat(TIMESTAMP_FORMAT);
        //        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        //        // Get timestamp some other way than this, of course.
        //        String timestamp = dateFormat.format(new Date());
        //        try {
        //            Date date = dateFormat.parse(timestamp);
        //            logger.debug("Timestamp string is: " + timestamp);
        //            logger.debug("Date is: " + date);
        //        } catch (ParseException e) {
        //            logger.error("Exception parsing timestamp", e);
        //        }

        resultsMap.put("timestamp", dateFormat.format(new Date()));
    }

    /** Return the results of running the task.
     * @return The HashMap for the results. */
    public final HashMap<String, String> getResults() {
        results.put("status", status);
        logger.debug("getResults results:" + results.toString());
        return results;
    }

    // Code previously considered but rejected for now.
    //    /** Return the results of running the task as a String.
    //     * @return The results as a String. */
    //    public final String getResultsString() {
    //        return getResults().toString();
    //    }

}