/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012-2013, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotoolkit.processing.chain;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import javax.xml.bind.JAXBException;
import org.geotoolkit.process.ProcessDescriptor;
import org.geotoolkit.process.Process;
import org.geotoolkit.process.ProcessException;
import org.geotoolkit.processing.chain.model.Chain;
import org.geotoolkit.processing.chain.model.ElementProcess;
import org.geotoolkit.processing.chain.model.Constant;
import org.geotoolkit.processing.chain.model.ElementCondition;
import org.geotoolkit.processing.chain.model.FlowLink;
import org.geotoolkit.processing.chain.model.Parameter;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.geotoolkit.processing.chain.model.Element.*;
import org.opengis.parameter.ParameterValueGroup;
/**
*
* @author Johann Sorel (Geomatys)
*/
public class ChainProcessTest extends org.geotoolkit.test.TestBase {
private Chain createSimpleChain(){
//produce a chain equivalent to : ($1 + 10) / $2
final Chain chain = new Chain("myChain");
int id = 1;
//input/out/constants parameters
final Parameter a = chain.addInputParameter("a", Double.class, "desc",1,1,null);
final Parameter b = chain.addInputParameter("b", Double.class, "desc",1,1,null);
final Parameter r = chain.addOutputParameter("r", Double.class, "desc",1,1,null);
final Constant c = chain.addConstant(id++, Double.class, 10d);
//chain blocks
final ElementProcess add = chain.addProcessElement(id++, "demo", "add");
final ElementProcess divide = chain.addProcessElement(id++, "demo", "divide");
//execution flow links
chain.addFlowLink(BEGIN.getId(), add.getId());
chain.addFlowLink(add.getId(), divide.getId());
chain.addFlowLink(divide.getId(), END.getId());
//data flow links
chain.addDataLink(BEGIN.getId(), a.getCode(), add.getId(), "first");
chain.addDataLink(c.getId(), "", add.getId(), "second");
chain.addDataLink(add.getId(), "result", divide.getId(), "first");
chain.addDataLink(BEGIN.getId(), b.getCode(), divide.getId(), "second");
chain.addDataLink(divide.getId(), "result", END.getId(), r.getCode());
return chain;
}
private Chain createBranchChain(){
//produce a chain equivalent to : (($a+10) > 20) ? *10 : /10
final Chain chain = new Chain("branchChain");
int id = 1;
//input/out/constants parameters
final Parameter a = chain.addInputParameter("a", Double.class, "desc",1,1,null);
final Parameter r = chain.addOutputParameter("r", Double.class, "desc",1,1,null);
final Constant c10 = chain.addConstant(id++, Double.class, 10d);
//chain blocks
final ElementProcess add = chain.addProcessElement(id++, "demo", "add");
final ElementProcess multi = chain.addProcessElement(id++, "demo", "multiply");
final ElementProcess divide = chain.addProcessElement(id++, "demo", "divide");
final ElementCondition condition = chain.addConditionElement(id++);
condition.getInputs().add(new Parameter("value", Double.class, "", 1, 1));
condition.setSyntax("CQL");
condition.setExpression("value > 20");
//execution flow links
chain.addFlowLink(BEGIN.getId(), add.getId());
chain.addFlowLink(add.getId(), condition.getId());
final FlowLink success = chain.addFlowLink(condition.getId(), multi.getId()); condition.getSuccess().add(success);
final FlowLink fail = chain.addFlowLink(condition.getId(), divide.getId()); condition.getFailed().add(fail);
chain.addFlowLink(divide.getId(), END.getId());
chain.addFlowLink(multi.getId(), END.getId());
//data flow links
chain.addDataLink(c10.getId(), "", add.getId(), "second");
chain.addDataLink(c10.getId(), "", multi.getId(), "second");
chain.addDataLink(c10.getId(), "", divide.getId(), "second");
chain.addDataLink(BEGIN.getId(), a.getCode(), add.getId(), "first");
chain.addDataLink(add.getId(), "result", condition.getId(), "value");
chain.addDataLink(add.getId(), "result", multi.getId(), "first");
chain.addDataLink(add.getId(), "result", divide.getId(), "first");
chain.addDataLink(divide.getId(), "result", END.getId(), r.getCode());
chain.addDataLink(multi.getId(), "result", END.getId(), r.getCode());
return chain;
}
@Test
public void testSimpleChain() throws ProcessException{
final Chain chain = createSimpleChain();
//process registries to use
final Set<MockProcessRegistry> registries = Collections.singleton(new MockProcessRegistry());
//create a process descriptor to use it like any process.
final ProcessDescriptor desc = new ChainProcessDescriptor(chain, MockProcessRegistry.IDENTIFICATION, registries);
//input params
final ParameterValueGroup input = desc.getInputDescriptor().createValue();
input.parameter("a").setValue(15d);
input.parameter("b").setValue(2d);
final Process process = desc.createProcess(input);
final ParameterValueGroup result = process.call();
assertEquals(12.5d, result.parameter("r").doubleValue(),0.000001);
}
@Test
public void testSimpleXmlRW() throws ProcessException, JAXBException, IOException{
final Chain before = createSimpleChain();
final File f = File.createTempFile("chain", ".xml");
before.write(f);
final Chain chain = Chain.read(f);
//process registries to use
final Set<MockProcessRegistry> registries = Collections.singleton(new MockProcessRegistry());
//create a process descriptor to use it like any process.
final ProcessDescriptor desc = new ChainProcessDescriptor(chain, MockProcessRegistry.IDENTIFICATION, registries);
//input params
final ParameterValueGroup input = desc.getInputDescriptor().createValue();
input.parameter("a").setValue(15d);
input.parameter("b").setValue(2d);
final Process process = desc.createProcess(input);
final ParameterValueGroup result = process.call();
assertEquals(12.5d, result.parameter("r").doubleValue(),0.000001);
}
@Test
public void testBranchChain() throws ProcessException{
final Chain chain = createBranchChain();
//process registries to use
final Set<MockProcessRegistry> registries = Collections.singleton(new MockProcessRegistry());
//create a process descriptor to use it like any process.
final ProcessDescriptor desc = new ChainProcessDescriptor(chain, MockProcessRegistry.IDENTIFICATION, registries);
//input params , condition evaluates to TRUE----------------------------
ParameterValueGroup input = desc.getInputDescriptor().createValue();
input.parameter("a").setValue(15d);
Process process = desc.createProcess(input);
ParameterValueGroup result = process.call();
assertEquals(250d, result.parameter("r").doubleValue(),0.000001);
//input params , condition evaluates to FALSE---------------------------
input = desc.getInputDescriptor().createValue();
input.parameter("a").setValue(-5d);
process = desc.createProcess(input);
result = process.call();
assertEquals(0.5d, result.parameter("r").doubleValue(),0.000001);
}
@Test
public void testBranchXmlRW() throws ProcessException, JAXBException, IOException{
final Chain before = createBranchChain();
final File f = File.createTempFile("chain", ".xml");
before.write(f);
final Chain chain = Chain.read(f);
//process registries to use
final Set<MockProcessRegistry> registries = Collections.singleton(new MockProcessRegistry());
//create a process descriptor to use it like any process.
final ProcessDescriptor desc = new ChainProcessDescriptor(chain, MockProcessRegistry.IDENTIFICATION, registries);
//input params , condition evaluates to TRUE----------------------------
ParameterValueGroup input = desc.getInputDescriptor().createValue();
input.parameter("a").setValue(15d);
Process process = desc.createProcess(input);
ParameterValueGroup result = process.call();
assertEquals(250d, result.parameter("r").doubleValue(),0.000001);
//input params , condition evaluates to FALSE---------------------------
input = desc.getInputDescriptor().createValue();
input.parameter("a").setValue(-5d);
process = desc.createProcess(input);
result = process.call();
assertEquals(0.5d, result.parameter("r").doubleValue(),0.000001);
}
}