/* * 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.model; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Objects; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.adapters.XmlAdapter; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.Result; import javax.xml.transform.Source; import org.apache.sis.util.ArgumentChecks; import org.geotoolkit.gui.swing.tree.Trees; import javax.xml.bind.JAXBContext; import org.apache.sis.xml.MarshallerPool; import org.w3c.dom.Node; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; /** * Represents a process chain. * * @author Johann Sorel (Geomatys) */ @XmlRootElement(name="chain") @XmlAccessorType(XmlAccessType.FIELD) public class Chain implements Comparable<Chain>,Parameterized { @XmlTransient private static MarshallerPool POOL; @XmlElement(name="name") protected String name; @XmlElement(name="input") protected List<Parameter> inputs; @XmlElement(name="output") protected List<Parameter> outputs; @XmlElement(name="constant") protected List<Constant> constants; @XmlElement(name="element") protected List<Element> chainElements; @XmlElement(name="dataLink") protected List<DataLink> links; @XmlElement(name="flowLink") protected List<FlowLink> executionLinks; private Chain() { } public Chain(String name) { ArgumentChecks.ensureNonEmpty("name", name); this.name = name; } /** * Constructor by copy. * Each sub element is all copied. * * @param chain */ public Chain(final Chain chain) { if(chain == null) {return;} this.name = chain.getName(); //deep copy for(Constant cdt : chain.getConstants()){ getConstants().add(new Constant(cdt)); } for(Element cdt : chain.getElements()){ getElements().add(cdt.copy()); } for(Parameter cdt : chain.getInputs()){ getInputs().add(new Parameter(cdt)); } for(DataLink cdt : chain.getDataLinks()){ getDataLinks().add(new DataLink(cdt)); } for(FlowLink cdt : chain.getFlowLinks()){ getFlowLinks().add(new FlowLink(cdt)); } for(Parameter cdt : chain.getOutputs()){ getOutputs().add(new Parameter(cdt)); } } public Parameter addInputParameter(final String code, final Class type, final String remarks, final int minOccurs, final int maxOccurs, final Object defaultValue){ final Parameter param = new Parameter(code, type, remarks, minOccurs, maxOccurs, defaultValue); getInputs().add(param); return param; } public Parameter addOutputParameter(final String code, final Class type, final String remarks, final int minOccurs, final int maxOccurs, final Object defaultValue){ final Parameter param = new Parameter(code, type, remarks, minOccurs, maxOccurs, defaultValue); getOutputs().add(param); return param; } public Constant addConstant(final int id, final Class type, final Object value){ final Constant constant = new Constant(id, type, value,0,0); getConstants().add(constant); return constant; } public ElementProcess addProcessElement(final int id, final String authority, final String code){ final ElementProcess ele = new ElementProcess(id, authority, code); getElements().add(ele); return ele; } public ElementCondition addConditionElement(final int id){ final ElementCondition ele = new ElementCondition(id); getElements().add(ele); return ele; } public ElementManual addManualElement(final int id){ final ElementManual ele = new ElementManual(id); getElements().add(ele); return ele; } public FlowLink addFlowLink(int inId, int outId){ final FlowLink link = new FlowLink(inId, outId); getFlowLinks().add(link); return link; } public DataLink addDataLink(int inId, String inCode, int outId, String outCode){ final DataLink link = new DataLink(inId, inCode, outId, outCode); getDataLinks().add(link); return link; } /** * Return all link which come from a source id. * * @param sourceId * @return a list of LinkDto */ public List<DataLink> getInputLinks(final int sourceId) { final List<DataLink> result = new ArrayList<DataLink>(); if (links != null) { for (DataLink link : links) { if (link.getSourceId() == sourceId) { result.add(link); } } } return result; } /** * Return all link which point to target id. * * @param targetId * @return a list of LinkDto */ public List<DataLink> getOutputLinks(final int targetId) { final List<DataLink> result = new ArrayList<DataLink>(); if (links != null) { for (DataLink link : links) { if (link.getTargetId() == targetId) { result.add(link); } } } return result; } public List<DataLink> getDataLinks() { if(links == null){ links = new ArrayList<DataLink>(); } return links; } public void setDataLinks(final List<DataLink> links) { this.links = links; } public List<FlowLink> getFlowLinks() { if (executionLinks == null) { executionLinks = new ArrayList<FlowLink>(); } return executionLinks; } public void setFlowLinks(final List<FlowLink> executionLinks) { this.executionLinks = executionLinks; } public List<Element> getElements() { if(chainElements == null){ chainElements = new ArrayList<Element>(); } return chainElements; } public void setElements(final List<Element> descriptors) { this.chainElements = descriptors; } public List<Constant> getConstants() { if(constants == null){ constants = new ArrayList<Constant>(); } return constants; } public void setConstants(final List<Constant> constants) { this.constants = constants; } public List<Parameter> getInputs() { if(inputs == null){ inputs = new ArrayList<Parameter>(); } return inputs; } public void setInputs(final List<Parameter> inputs) { this.inputs = inputs; } public List<Parameter> getOutputs() { if(outputs == null){ outputs = new ArrayList<Parameter>(); } return outputs; } public void setOutputs(final List<Parameter> outputs) { this.outputs = outputs; } public String getName() { return name; } public void setName(final String name) { this.name = name; } public List<ClassFull> getAllUsedClasses() { final List<ClassFull> result = new ArrayList<ClassFull>(); if (inputs != null) { for (Parameter param : inputs) { if (!result.contains(param.getType())) { result.add(param.getType()); } } } if (outputs != null) { for (Parameter param : outputs) { if (!result.contains(param.getType())) { result.add(param.getType()); } } } return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj instanceof Chain) { final Chain that = (Chain) obj; return Objects.equals(this.getConstants(), that.getConstants()) && Objects.equals(this.getElements(), that.getElements()) && Objects.equals(this.getDataLinks(), that.getDataLinks()) && Objects.equals(this.getFlowLinks(), that.getFlowLinks()) && Objects.equals(this.name, that.name) && Objects.equals(this.getOutputs(), that.getOutputs()) && Objects.equals(this.getInputs(), that.getInputs()); } return false; } @Override public int hashCode() { return 97; } @Override public String toString() { final StringBuilder sb = new StringBuilder("[ChainDto]"); if (name != null) { sb.append("name:").append(name).append('\n'); } sb.append(Trees.toString("Inputs", getInputs())); sb.append(Trees.toString("Outputs", getOutputs())); sb.append(Trees.toString("Constants", getConstants())); sb.append(Trees.toString("Chain elements", getElements())); sb.append(Trees.toString("Links", getDataLinks())); sb.append(Trees.toString("ExecutionLinks", getFlowLinks())); return sb.toString(); } @Override public int compareTo(Chain o) { if (o != null) { return this.getName().compareTo(o.getName()); } return -1; } public static class ClassAdaptor extends XmlAdapter<String, Class>{ @Override public Class unmarshal(final String v) throws Exception { return Class.forName(v); } @Override public String marshal(final Class v) throws Exception { return v.getName(); } } /** * Write this ProcessSequence in given output. * @throws JAXBException */ public void write(final Object output) throws JAXBException{ final MarshallerPool pool = getPoolInstance(); final Marshaller marshaller = pool.acquireMarshaller(); try{ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); if(output instanceof ContentHandler){ marshaller.marshal(this, (ContentHandler)output); }else if(output instanceof File){ marshaller.marshal(this, (File)output); }else if(output instanceof Node){ marshaller.marshal(this, (Node)output); }else if(output instanceof OutputStream){ marshaller.marshal(this, (OutputStream)output); }else if(output instanceof Result){ marshaller.marshal(this, (Result)output); }else if(output instanceof Writer){ marshaller.marshal(this, (Writer)output); }else if(output instanceof XMLEventWriter){ marshaller.marshal(this, (XMLEventWriter)output); }else if(output instanceof XMLStreamWriter){ marshaller.marshal(this, (XMLStreamWriter)output); }else{ throw new JAXBException("Unsupported output : "+output); } }finally{ pool.recycle(marshaller); } } /** * Read the given input and return an ProcessSequence. * * @param input * @return * @throws JAXBException */ public static Chain read(final Object input) throws JAXBException{ final MarshallerPool pool = getPoolInstance(); final Unmarshaller unmarshaller = pool.acquireUnmarshaller(); final Chain set; try{ if(input instanceof File){ set = (Chain) unmarshaller.unmarshal((File)input); }else if(input instanceof InputSource){ set = (Chain) unmarshaller.unmarshal((InputSource)input); }else if(input instanceof InputStream){ set = (Chain) unmarshaller.unmarshal((InputStream)input); }else if(input instanceof Node){ set = (Chain) unmarshaller.unmarshal((Node)input); }else if(input instanceof Reader){ set = (Chain) unmarshaller.unmarshal((Reader)input); }else if(input instanceof Source){ set = (Chain) unmarshaller.unmarshal((Source)input); }else if(input instanceof URL){ set = (Chain) unmarshaller.unmarshal((URL)input); }else if(input instanceof XMLEventReader){ set = (Chain) unmarshaller.unmarshal((XMLEventReader)input); }else if(input instanceof XMLStreamReader){ set = (Chain) unmarshaller.unmarshal((XMLStreamReader)input); }else{ throw new JAXBException("Unsupported input : "+input); } }finally{ pool.recycle(unmarshaller); } return set; } public static synchronized MarshallerPool getPoolInstance() throws JAXBException{ if(POOL == null){ POOL = new MarshallerPool(JAXBContext.newInstance(Chain.class), null); } return POOL; } }