/* * Copyright (C) 2015 Jan Pokorsky * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package cz.cas.lib.proarc.common.workflow.profile; import cz.cas.lib.proarc.common.CustomTemporaryFolder; import cz.cas.lib.proarc.common.workflow.model.MaterialType; import cz.cas.lib.proarc.common.workflow.model.ValueType; import cz.cas.lib.proarc.common.workflow.profile.ValueMapDefinition.ValueMapItemDefinition; import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.JAXB; import javax.xml.bind.JAXBContext; import javax.xml.bind.SchemaOutputResolver; import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; import org.junit.Rule; /** * * @author Jan Pokorsky */ public class WorkflowProfilesTest { @Rule public CustomTemporaryFolder temp = new CustomTemporaryFolder(true); public WorkflowProfilesTest() { } @BeforeClass public static void setUpClass() { } @AfterClass public static void tearDownClass() { } @Before public void setUp() { } @After public void tearDown() { } @Test public void testReadXmlFile() throws Exception { String xml = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n" + "<workflow xmlns='http://proarc.lib.cas.cz/xml/common/workflow/v1'>\n" + " <job name='ndk' priority='1'>\n" + " <worker actual='true'/>\n" + " <step taskRef='task.id1'>\n" + " <worker>step1Worker</worker>\n" + " <setParam paramRef='param.id1'>param.id1.value</setParam>\n" + " </step>\n" + " <step taskRef='task.id2' optional='true'>\n" + " <blocker taskRef='task.id1'/>\n" + " </step>\n" + " <title>defaultTitle</title>\n" + " <title lang='cs'>csTitle</title>\n" + " </job>\n" + " <material name='material0' type='FOLDER'/>\n" + " <material name='material1' type='DIGITAL_OBJECT'/>\n" + " <task name='task.id1'>\n" + " <param name='param.id1' required='true' datasource='workflow.valuemap.colors'/>\n" + " <param name='param.id2' required='false' datasource='proarc.devices'\n" + " type='NUMBER' displayType='SELECT'/>\n" + " <setMaterial materialRef='material0' way='INPUT'/>\n" + " <title lang='cs'>Úkol 1</title>\n" + " <title lang='en'>Task 1</title>\n" + " </task>\n" + " <task name='task.id2'>\n" + " <setMaterial materialRef='material0' way='OUTPUT'/>\n" + " </task>\n" + " <valuemap name='workflow.valuemap.colors'>\n" + " <value>barevně</value>\n" + " <value>v šedi</value>\n" + " </valuemap>\n" + " <valuemap name='workflow.valuemap.colorsWithKeys' >\n" + " <value key='colorful'>barevně</value>\n" + " <value key='grey'>v šedi</value>\n" + " </valuemap>\n" + " <valuemap name='proarc.devices' source='PROARC'/>\n" + "</workflow>\n" ; File xmlFile = new File(temp.getRoot(), "workflow.xml"); FileUtils.write(xmlFile, xml, StandardCharsets.UTF_8); WorkflowProfiles profiles = new WorkflowProfiles(xmlFile); WorkflowDefinition wf = profiles.getProfiles(); assertNotNull(wf); List<JobDefinition> jobs = wf.getJobs(); assertFalse(jobs.isEmpty()); JobDefinition job0 = jobs.get(0); assertEquals("ndk", job0.getName()); assertTrue(job0.getWorker().getActual()); assertEquals(1, job0.getPriority()); assertEquals("csTitle", job0.getTitles().get("cs")); assertEquals("defaultTitle", job0.getTitles().get(null)); assertEquals("step1Worker", job0.getSteps().get(0).getWorker().getUsername()); assertFalse(job0.getSteps().get(0).getWorker().getActual()); assertEquals(false, job0.getSteps().get(0).isOptional()); assertEquals(true, job0.getSteps().get(1).isOptional()); List<SetParamDefinition> paramSetters = job0.getSteps().get(0).getParamSetters(); assertFalse(paramSetters.isEmpty()); assertEquals("param.id1", paramSetters.get(0).getParam().getName()); assertEquals("param.id1.value", paramSetters.get(0).getValue()); List<MaterialDefinition> materials = wf.getMaterials(); assertFalse(materials.isEmpty()); assertEquals("material0", materials.get(0).getName()); List<TaskDefinition> tasks = wf.getTasks(); assertFalse(tasks.isEmpty()); // step/task1 assertEquals(job0.getSteps().get(0).getTask(), tasks.get(0)); assertEquals("task.id1", tasks.get(0).getName()); assertEquals(Way.INPUT, tasks.get(0).getMaterialSetters().get(0).getWay()); assertEquals("material0", tasks.get(0).getMaterialSetters().get(0).getMaterial().getName()); assertEquals(MaterialType.FOLDER, tasks.get(0).getMaterialSetters().get(0).getMaterial().getType()); // step/task1/param1 assertEquals("param.id1", tasks.get(0).getParams().get(0).getName()); assertEquals(DisplayType.TEXT, tasks.get(0).getParams().get(0).getDisplayType()); assertEquals(ValueType.STRING, tasks.get(0).getParams().get(0).getValueType()); assertEquals("workflow.valuemap.colors", tasks.get(0).getParams().get(0).getDatasource().getId()); assertEquals(true, tasks.get(0).getParams().get(0).isRequired()); // step/task1/param2 assertEquals("param.id2", tasks.get(0).getParams().get(1).getName()); assertEquals(DisplayType.SELECT, tasks.get(0).getParams().get(1).getDisplayType()); assertEquals(ValueType.NUMBER, tasks.get(0).getParams().get(1).getValueType()); assertEquals("proarc.devices", tasks.get(0).getParams().get(1).getDatasource().getId()); assertEquals(false, tasks.get(0).getParams().get(1).isRequired()); // step/task2 assertEquals(job0.getSteps().get(1).getTask(), tasks.get(1)); assertEquals(job0.getSteps().get(1).getBlockers().get(0).getTask(), tasks.get(0)); assertEquals("task.id2", tasks.get(1).getName()); assertEquals(Way.OUTPUT, tasks.get(1).getMaterialSetters().get(0).getWay()); assertEquals("material0", tasks.get(0).getMaterialSetters().get(0).getMaterial().getName()); // valuemap1 assertEquals("workflow.valuemap.colors", wf.getValueMaps().get(0).getId()); assertEquals(ValueMapSource.INTERNAL, wf.getValueMaps().get(0).getSource()); assertEquals("v šedi", wf.getValueMaps().get(0).getItems().get(1).getValue()); assertNull(wf.getValueMaps().get(0).getItems().get(1).getKey()); // valuemap2 assertEquals("workflow.valuemap.colorsWithKeys", wf.getValueMaps().get(1).getId()); assertEquals(ValueMapSource.INTERNAL, wf.getValueMaps().get(1).getSource()); assertEquals("v šedi", wf.getValueMaps().get(1).getItems().get(1).getValue()); assertEquals("grey", wf.getValueMaps().get(1).getItems().get(1).getKey()); assertEquals(Arrays.asList("task.id1", "task.id2"), profiles.getSortedTaskNames(job0)); } @Test public void testCopyDefaultFile() throws Exception { File wfFile = new File(temp.getRoot(), "wf.xml"); WorkflowProfiles.copyDefaultFile(wfFile); assertTrue(wfFile.exists()); assertTrue(wfFile.length() > 0); WorkflowProfiles wp = new WorkflowProfiles(wfFile); assertNotNull(wp.getProfiles()); } // @Test public void testCreateSchema() throws Exception { JAXBContext jctx = JAXBContext.newInstance(WorkflowDefinition.class); final Map<String, StreamResult> schemas = new HashMap<String, StreamResult>(); jctx.generateSchema(new SchemaOutputResolver() { @Override public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { StreamResult sr = new StreamResult(new StringWriter()); sr.setSystemId(namespaceUri); schemas.put(namespaceUri, sr); return sr; } }); System.out.println(schemas.get(WorkflowProfileConsts.NS_WORKFLOW_V1).getWriter().toString()); } @Test public void testWriteXml() { WorkflowDefinition wf = new WorkflowDefinition(); MaterialDefinition material1 = new MaterialDefinition().setName("material1"); material1.getTitles().put("cs", "csMaterialTitle"); material1.getHints().put("cs", "csMaterialDescription"); TaskDefinition task1 = new TaskDefinition().setName("task.id1"); task1.getTitles().put("cs", "Úkol 1"); task1.getTitles().put("en", "Task 1"); task1.getMaterialSetters().add(new SetMaterialDefinition().setMaterial(material1).setWay(Way.INPUT)); ParamDefinition param1 = new ParamDefinition().setName("param.id1").setRequired(true); task1.getParams().add(param1); TaskDefinition task2 = new TaskDefinition().setName("task.id2"); JobDefinition job = new JobDefinition() .setName("job0") .setWorker(new WorkerDefinition().setUsername("worker")) .setPriority(3) .setDisabled(true); job.getTitles().put("cs", "csTitle"); job.getTitles().put("en", "enTitle"); job.getTitles().put(null, "defaultTitle"); StepDefinition step1 = new StepDefinition().setTask(task1).setWorker(new WorkerDefinition().setActual(true)); step1.getParamSetters().add(new SetParamDefinition().setParam(param1).setValue("param1.value")); job.getSteps().add(step1); StepDefinition step2 = new StepDefinition().setTask(task2).setWorker(new WorkerDefinition().setActual(true)); step2.getBlockers().add(new BlockerDefinition().setTask(task1)); job.getSteps().add(step2); wf.getJobs().add(job); wf.getMaterials().add(material1); wf.getTasks().add(task1); wf.getTasks().add(task2); ValueMapDefinition vmap = new ValueMapDefinition().setId("workflow.valuemap.id1"); vmap.getItems().add(new ValueMapItemDefinition().setKey("grey").setValue("v šedi")); wf.getValueMaps().add(vmap); JAXB.marshal(wf, System.out); } @Test public void testBlockers() throws Exception { String xml = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n" + "<workflow xmlns='http://proarc.lib.cas.cz/xml/common/workflow/v1'>\n" + " <job name='ndk'>\n" + " <step taskRef='task.id3'/>\n" + " <step taskRef='task.id6'>\n" + " <blocker taskRef='task.id5'/>\n" + " <blocker taskRef='task.id2'/>\n" + " <blocker taskRef='task.idNotStep'/>\n" + " </step>\n" + " <step taskRef='task.id1' optional='true'>\n" + " <blocker taskRef='task.id2'/>\n" + " </step>\n" + " <step taskRef='task.id5'>\n" + " <blocker taskRef='task.id3'/>\n" + " </step>\n" + " <step taskRef='task.id2'>\n" + " <blocker taskRef='task.id3'/>\n" + " </step>\n" + " <step taskRef='task.id4'/>\n" + " </job>\n" + " <task name='task.id2'/>\n" + " <task name='task.id1'/>\n" + " <task name='task.id4'/>\n" + " <task name='task.id3'/>\n" + " <task name='task.id5'/>\n" + " <task name='task.id6'/>\n" + " <task name='task.idNotStep'/>\n" + "</workflow>\n" ; File xmlFile = new File(temp.getRoot(), "workflow.xml"); FileUtils.write(xmlFile, xml); WorkflowProfiles profiles = new WorkflowProfiles(xmlFile); WorkflowDefinition wf = profiles.getProfiles(); assertNotNull(wf); assertEquals(Arrays.asList("task.id3", "task.id4", "task.id5", "task.id2", "task.id6", "task.id1"), profiles.getSortedTaskNames(wf.getJobs().get(0))); } @Test public void testBlockerCycle() throws Exception { String xml = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n" + "<workflow xmlns='http://proarc.lib.cas.cz/xml/common/workflow/v1'>\n" + " <job name='ndk'>\n" + " <step taskRef='task.id1'/>\n" + " <step taskRef='task.id2'>\n" + " <blocker taskRef='task.id3'/>\n" + " </step>\n" + " <step taskRef='task.id3'>\n" + " <blocker taskRef='task.id4'/>\n" + " <blocker taskRef='task.id1'/>\n" + " </step>\n" + " <step taskRef='task.id4'>\n" + " <blocker taskRef='task.id2'/>\n" + " </step>\n" + " </job>\n" + " <task name='task.id1'/>\n" + " <task name='task.id2'/>\n" + " <task name='task.id3'/>\n" + " <task name='task.id4'/>\n" + "</workflow>\n" ; File xmlFile = new File(temp.getRoot(), "workflow.xml"); FileUtils.write(xmlFile, xml); WorkflowProfiles profiles = new WorkflowProfiles(xmlFile); try { WorkflowDefinition wf = profiles.getProfiles(); fail(String.valueOf(profiles.getSortedTaskNames(wf.getJobs().get(0)))); } catch (IllegalStateException ex) { assertTrue(ex.getMessage(), ex.getMessage().startsWith("There must be a cycle")); } } }