001package org.galaxyproject.gxformat2;
002
003import java.util.ArrayList;
004import java.util.List;
005import java.util.Map;
006
007public class NativeLinter implements GalaxyWorkflowLinter {
008  public static String LINT_FAILED_NO_OUTPUTS = "Workflow contained no outputs";
009  public static String LINT_FAILED_OUTPUT_NO_LABEL = "Workflow contained output without a label";
010
011  public void lint(final LintContext lintContext, final Map<String, Object> workflow) {
012    LintUtils.ensureKey(lintContext, workflow, "format-version", String.class, "0.1");
013    LintUtils.ensureKey(lintContext, workflow, "a_galaxy_workflow", String.class, "true");
014
015    final Map<String, Object> steps = LintUtils.stepMap(lintContext, workflow);
016    boolean foundOutputs = false;
017    boolean foundOutputsWithoutLabel = false;
018
019    for (Map.Entry<String, Object> stepEntry : steps.entrySet()) {
020      final String orderIndexStr = stepEntry.getKey();
021      try {
022        final int orderIndex = Integer.parseInt(orderIndexStr);
023      } catch (NumberFormatException e) {
024        lintContext.error("expected step_key to be integer not [%s]", orderIndexStr);
025      }
026      if (!(stepEntry.getValue() instanceof Map)) {
027        lintContext.error("expected step value to be Map not [%s]", stepEntry.getValue());
028      }
029      Map<String, Object> step = (Map<String, Object>) stepEntry.getValue();
030      List<String> workflowOutputs =
031          LintUtils.ensureKeyIfPresent(
032              lintContext, step, "workflow_outputs", new ArrayList<String>(), List.class);
033      for (Object workflowOutputObject : workflowOutputs) {
034        foundOutputs = true;
035        if (!(workflowOutputObject instanceof Map)) {
036          lintContext.error("Not a map");
037        }
038        final Map<String, String> workflowOutput = (Map<String, String>) workflowOutputObject;
039        final String label = workflowOutput.get("label");
040        if (label == null || label.length() == 0) {
041          foundOutputsWithoutLabel = true;
042        }
043      }
044      final String stepType =
045          LintUtils.ensureKeyIfPresent(lintContext, step, "type", "tool", String.class);
046      assert stepType != null;
047      if (stepType != null && stepType.equals("subworkflow")) {
048        final Map<String, Object> subworkflow =
049            (Map<String, Object>)
050                LintUtils.ensureKey(lintContext, step, "subworkflow", Map.class, null);
051        assert subworkflow != null;
052        lint(lintContext, subworkflow);
053      }
054      LintUtils.lintStepErrors(lintContext, step);
055    }
056    Map<String, Object> reportMap =
057        (Map<String, Object>)
058            LintUtils.ensureKeyIfPresent(
059                lintContext, workflow, "report", (Map<String, Object>) null, Map.class);
060    if (reportMap != null) {
061      LintUtils.ensureKey(lintContext, reportMap, "markdown", String.class, null);
062    }
063    if (!foundOutputs) {
064      lintContext.warn(LINT_FAILED_NO_OUTPUTS);
065    }
066    if (foundOutputsWithoutLabel) {
067      lintContext.warn(LINT_FAILED_OUTPUT_NO_LABEL);
068    }
069  }
070}