org.n52.ifgicopter.spf.xml.PluginXMLTools.java Source code

Java tutorial

Introduction

Here is the source code for org.n52.ifgicopter.spf.xml.PluginXMLTools.java

Source

/**
 * Copyright (C) 2009
 * by 52 North Initiative for Geospatial Open Source Software GmbH
 *
 * Contact: Andreas Wytzisk
 * 52 North Initiative for Geospatial Open Source Software GmbH
 * Martin-Luther-King-Weg 24
 * 48155 Muenster, Germany
 * info@52north.org
 *
 * This program is free software; you can redistribute and/or modify it under
 * the terms of the GNU General Public License version 2 as published by the
 * Free Software Foundation.
 *
 * This program is distributed WITHOUT ANY WARRANTY; even without 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 (see gnu-gpl v2.txt). If not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA or
 * visit the Free Software Foundation web page, http://www.fsf.org.
 */

package org.n52.ifgicopter.spf.xml;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import net.opengis.gml.BoundingShapeType;
import net.opengis.gml.DirectPositionType;
import net.opengis.gml.EnvelopeType;
import net.opengis.sensorML.x101.AbstractProcessType;
import net.opengis.sensorML.x101.IoComponentPropertyType;
import net.opengis.sensorML.x101.ResponsiblePartyDocument.ResponsibleParty;
import net.opengis.sensorML.x101.SensorMLDocument.SensorML;
import net.opengis.sensorML.x101.SensorMLDocument.SensorML.Member;
import net.opengis.sensorML.x101.TermDocument.Term;
import net.opengis.sensorML.x101.SystemType;
import net.opengis.sensorML.x101.ContactDocument.Contact;
import net.opengis.sensorML.x101.ContactInfoDocument.ContactInfo;
import net.opengis.sensorML.x101.ContactInfoDocument.ContactInfo.Address;
import net.opengis.sensorML.x101.IdentificationDocument.Identification;
import net.opengis.sensorML.x101.IdentificationDocument.Identification.IdentifierList;
import net.opengis.sensorML.x101.IdentificationDocument.Identification.IdentifierList.Identifier;
import net.opengis.sensorML.x101.InputsDocument.Inputs.InputList;
import net.opengis.sensorML.x101.PositionDocument.Position;
import net.opengis.swe.x101.AbstractDataRecordType;
import net.opengis.swe.x101.PositionType;
import net.opengis.swe.x101.TimeDocument;
import net.opengis.swe.x101.UomPropertyType;
import net.opengis.swe.x101.VectorPropertyType;
import net.opengis.swe.x101.VectorType;
import net.opengis.swe.x101.BooleanDocument.Boolean;
import net.opengis.swe.x101.QuantityDocument.Quantity;
import net.opengis.swe.x101.TextDocument.Text;
import net.opengis.swe.x101.VectorType.Coordinate;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.n52.ifgicopter.spf.SPFRegistry;
import org.n52.ifgicopter.spf.xml.CompoundItem;
import org.n52.ifgicopter.spf.xml.Item;
import org.n52.ifgicopter.spf.xml.Location;
import org.n52.ifgicopter.spf.xml.Plugin;
import org.n52.ifgicopter.spf.xml.PluginMetadata;
import org.n52.ifgicopter.spf.xml.Time;
import org.n52.ifgicopter.spf.xml.parser.SWECommonParser;

import de.uniMuenster.ifgi.mRiek02.spf.x01.AbstractBehaviourType;
import de.uniMuenster.ifgi.mRiek02.spf.x01.AvailabilityBehaviourType;
import de.uniMuenster.ifgi.mRiek02.spf.x01.PeriodBehaviourType;
import de.uniMuenster.ifgi.mRiek02.spf.x01.PluginDocument;
import de.uniMuenster.ifgi.mRiek02.spf.x01.PluginType;
import de.uniMuenster.ifgi.mRiek02.spf.x01.AvailabilityBehaviourType.OutputProperties;
import de.uniMuenster.ifgi.mRiek02.spf.x01.PluginType.Output;
import de.uniMuenster.ifgi.mRiek02.spf.x01.PluginType.Output.MandatoryProperties;

public class PluginXMLTools {

    private static final Log log = LogFactory.getLog(PluginXMLTools.class);

    public static Plugin parsePlugin(InputStream is) throws Exception {
        /*
         * the final result get init
         */
        Plugin result = new Plugin();

        List<String> outputProperties = new ArrayList<String>();
        List<String> mandatoryProperties = new ArrayList<String>();
        List<String> inputProperties = new ArrayList<String>();
        Map<String, Item> items = new HashMap<String, Item>();

        StringBuilder sb = new StringBuilder();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        while (br.ready()) {
            sb.append(br.readLine());
        }

        PluginDocument doc = null;
        try {
            doc = PluginDocument.Factory.parse(sb.toString());
        } catch (XmlException e) {
            throw e;
        }

        /*
         * do we validate?
         */
        if (java.lang.Boolean
                .parseBoolean(SPFRegistry.getInstance().getConfigProperty(SPFRegistry.VALIDATE_XML_PROP))) {
            XmlOptions opts = new XmlOptions();
            List<XmlError> errors = new ArrayList<XmlError>();
            opts.setErrorListener(errors);
            if (!doc.validate(opts)) {
                throw new Exception("Document is not a valid plugin description. Please recheck: " + errors);
            }
        }

        PluginType plugin = doc.getPlugin();

        String name = plugin.getName().trim();

        /*
         * 
         * PARSE the SensorML
         * 
         */

        SensorML sensorML = plugin.getSensorML();

        PluginMetadata metadata = new PluginMetadata();
        metadata.setName(name);

        /*
         * do schematron XSLT transformations
         */
        SchematronValidator schematron = new SchematronValidator(sb);
        if (!schematron.validate()) {
            throw new Exception(
                    "The plugin description file is not a valid SPF-schematron SensorML profile instance: "
                            + schematron.getAssertFails());
        }
        /*
         * get the input items
         */
        boolean mobile = true;
        Location location = null;
        Time time = null;

        AbstractProcessType process = sensorML.getMemberArray(0).getProcess();
        if (process instanceof SystemType) {
            /*
             * parse the system
             */
            SystemType system = (SystemType) process;

            /*
             * parse contact and identification
             */
            Contact[] cont = system.getContactArray();
            if (cont.length > 0) {
                if (cont[0].isSetResponsibleParty() && cont[0].getResponsibleParty().isSetContactInfo()
                        && cont[0].getResponsibleParty().getContactInfo().isSetAddress() && cont[0]
                                .getResponsibleParty().getContactInfo().getAddress().isSetElectronicMailAddress()) {
                    metadata.setContactEmail(cont[0].getResponsibleParty().getContactInfo().getAddress()
                            .getElectronicMailAddress().trim());
                }
            }

            Identification[] ident = system.getIdentificationArray();
            if (ident.length > 0) {

                if (ident[0].isSetIdentifierList()) {
                    for (int j = 0; j < ident[0].getIdentifierList().getIdentifierArray().length; j++) {
                        if (ident[0].getIdentifierList().getIdentifierArray()[j].isSetName()
                                && ident[0].getIdentifierList().getIdentifierArray()[j].getName()
                                        .equals("uniqueID")) {
                            metadata.setUniqueID(ident[0].getIdentifierList().getIdentifierArray()[j].getTerm()
                                    .getValue().trim());
                        }
                    }
                }

            }

            /*
             * check if we have a mobile or a stationary platform
             */
            if (system.isSetBoundedBy()) {
                /*
                 * this indicates a mobile sensor
                 * -> a swe:Position should be available
                 * in the sml:inputs
                 */
                BoundingShapeType boundedBy = system.getBoundedBy();
                if (boundedBy.isSetEnvelope()) {
                    EnvelopeType envelope = boundedBy.getEnvelope();

                    if ((envelope.isSetLowerCorner() && envelope.isSetUpperCorner())
                            || envelope.getPosArray().length == 2) {
                        /*
                         * valid envelope defintion
                         */
                        mobile = true;
                        metadata.setMobile(true);
                        metadata.setPosition(envelope.getLowerCorner().getStringValue().trim());
                    }
                }

            }

            else if (system.isSetPosition()) {
                /*
                 * if we have a static platform use the sml:location element
                 * -> stationary
                 */
                location = new Location("staticPosition");

                Position position = system.getPosition();
                VectorPropertyType loc = position.getPosition().getLocation();
                if (loc.isSetVector()) {
                    VectorType vector = loc.getVector();
                    location.setReferenceFrame(position.getPosition().getReferenceFrame());

                    /*
                     * get the axis order dependent on
                     * the CRS.
                     * the coordinate array will then be treated
                     * according to this axis order.
                     */
                    String[] axisOrder = getAxisOrder(location.getReferenceFrame());

                    int axis = 0;
                    for (Coordinate coord : vector.getCoordinateArray()) {
                        if (coord.isSetQuantity()) {
                            location.setAxis(axisOrder[axis], coord.getQuantity().getValue());
                        } else if (coord.isSetCount()) {
                            location.setAxis(axisOrder[axis], coord.getCount().getValue().doubleValue());
                        }

                        location.setDimension(++axis);
                    }

                    mobile = false;
                    metadata.setPosition(location.getX() + " " + location.getY());
                    metadata.setMobile(false);
                }

            }

            InputList inputs = system.getInputs().getInputList();

            if (inputs != null) {
                for (IoComponentPropertyType input : inputs.getInputArray()) {
                    /*
                     * parse the time
                     */
                    if (input.isSetTime()) {
                        TimeDocument.Time prop = input.getTime();
                        time = new Time(input.getName());
                        time.setDefinition(SWECommonParser.getTimeDefinition(prop));
                        time.setReferenceFrame(prop.getReferenceFrame());

                        items.put(time.getProperty(), time);
                    } else if (input.isSetAbstractDataRecord()) {
                        AbstractDataRecordType prop = input.getAbstractDataRecord();

                        /*
                         * is this the position?
                         */
                        if (prop instanceof PositionType) {
                            PositionType pos = (PositionType) prop;
                            pos.getReferenceFrame();

                            /*
                             * use a temporary object because perhaps
                             * we have a stationary platform defined
                             * and are not allowed to overwrite the
                             * field "location"
                             */
                            Location tmp = new Location(input.getName());

                            /*
                             * use the reference frame attribute
                             */
                            tmp.setReferenceFrame(pos.getReferenceFrame());
                            items.put(tmp.getProperty(), tmp);

                            VectorPropertyType loc = pos.getLocation();
                            Coordinate[] coords = loc.getVector().getCoordinateArray();

                            /*
                             * go through all coordinates
                             * treat axis ordering according to their order
                             */
                            for (int i = 0; i < coords.length; i++) {
                                if (i == 0) {
                                    /*
                                     * first axis
                                     */
                                    Item first = new Item(coords[i].getName());
                                    tmp.addCompoundedItem(first);
                                    tmp.setFirstCoordinateName(first.getProperty());

                                    if (coords[i].isSetQuantity() || coords[i].isSetCount()) {
                                        first.setDataType(Double.class);
                                        if (coords[i].isSetQuantity()) {
                                            Quantity quan = coords[i].getQuantity();
                                            if (quan.isSetUom()) {
                                                first.setUom(quan.getUom().getCode());
                                            }
                                        }
                                    } else {
                                        first.setDataType(String.class);
                                    }

                                } else if (i == 1) {
                                    /*
                                     * second axis
                                     */
                                    Item second = new Item(coords[i].getName());
                                    tmp.addCompoundedItem(second);
                                    tmp.setSecondCoordinateName(second.getProperty());

                                    if (coords[i].isSetQuantity() || coords[i].isSetCount()) {
                                        second.setDataType(Double.class);
                                        if (coords[i].isSetQuantity()) {
                                            Quantity quan = coords[i].getQuantity();
                                            if (quan.isSetUom()) {
                                                second.setUom(quan.getUom().getCode());
                                            }
                                        }
                                    } else {
                                        second.setDataType(String.class);
                                    }

                                } else {
                                    /*
                                     * third axis
                                     */
                                    Item third = new Item(coords[i].getName());
                                    tmp.addCompoundedItem(third);
                                    tmp.setAltitudeName(third.getProperty());

                                    if (coords[i].isSetQuantity() || coords[i].isSetCount()) {
                                        third.setDataType(Double.class);
                                        if (coords[i].isSetQuantity()) {
                                            Quantity quan = coords[i].getQuantity();
                                            if (quan.isSetUom()) {
                                                third.setUom(quan.getUom().getCode());
                                            }
                                        }
                                    } else {
                                        third.setDataType(String.class);
                                    }
                                }

                            }

                            if (!mobile) {
                                log.warn(
                                        "The SensorML indicated a stationary platform (sml:position was specified). The input "
                                                + "property '" + input.getName()
                                                + "' will not be treated as the dynamic position "
                                                + "of the platform but as a normal input property.");
                            } else {
                                /*
                                 * we are allowed to use this object
                                 * as location because the platform
                                 * is defined mobile
                                 */
                                location = tmp;
                            }
                        } else {
                            //TODO: do other data records
                        }

                    }

                    /*
                     * parse other values, probably phenomenons
                     */
                    else if (input.isSetQuantity() || input.isSetCount()) {
                        /*
                         * real numbers
                         */
                        Item item = new Item(input.getName());
                        item.setDataType(Double.class);

                        if (input.isSetQuantity()) {
                            Quantity quan = input.getQuantity();
                            if (quan.isSetUom()) {
                                item.setUom(quan.getUom().getCode());
                            }
                            if (quan.isSetDefinition()) {
                                item.setDefinition(quan.getDefinition());
                            }
                        }
                        items.put(item.getProperty(), item);
                    }

                    if (input.isSetText() || input.isSetBoolean() || input.isSetCategory()) {
                        /*
                         * treat this as string
                         */
                        Item item = new Item(input.getName());
                        item.setDataType(String.class);
                        items.put(item.getProperty(), item);
                    }
                }
            }

            /*
             * check if a time is present, otherwise set default time property
             */
            if (time == null) {
                /*
                 * define default time property
                 */
                time = new Time(Plugin.TIME_DEFAULT_NAME);
                time.setReferenceFrame("urn:ogc:def:unit:iso8601");
                time.setDefinition("urn:ogc:def:phenomenon:time");
                items.put(time.getProperty(), time);
            }
        }

        /*
         * 
         * PARSE the outputType
         * 
         */
        Output outputElem = plugin.getOutput();
        AbstractBehaviourType behave = outputElem.getBehaviour();
        String outputType = "";
        if (behave instanceof AvailabilityBehaviourType) {
            outputType = Plugin.AVAILABLE_BEHAVIOUR;
            AvailabilityBehaviourType avail = (AvailabilityBehaviourType) behave;

            for (String prop : avail.getOutputProperties().getPropertyArray()) {
                Item item = items.get(prop);
                if (item instanceof CompoundItem) {
                    addLeafProperties((CompoundItem) item, outputProperties);
                } else {
                    outputProperties.add(prop);
                }
            }
        } else if (behave instanceof PeriodBehaviourType) {
            outputType = Plugin.PERIOD_BEHAVIOUR;
            result.setTimeDelta(((PeriodBehaviourType) behave).getTimedelta());
        }

        /*
         * output if and only if all items are present
         */

        /*
         * these properties are needed for a data tuple
         */
        if (outputElem.isSetMandatoryProperties()) {
            //get from the mandatory list
            for (String prop : outputElem.getMandatoryProperties().getPropertyArray()) {
                Item item = items.get(prop);
                if (item instanceof CompoundItem) {
                    addLeafProperties((CompoundItem) item, mandatoryProperties);
                } else {
                    mandatoryProperties.add(prop);
                }
            }
        } else if (outputElem.isSetOutputOnAllItems()) {
            // all items are needed
            for (Item item : items.values()) {
                if (item instanceof CompoundItem) {
                    addLeafProperties((CompoundItem) item, mandatoryProperties);
                } else if (item instanceof Time) {
                    //do not add this as the time property is the key
                    //for maps and hence not hold separatly
                } else {
                    mandatoryProperties.add(item.getProperty());
                }
            }
        } else if (outputElem.isSetSingleOutputAllowed()) {
            /*
             * nothing. leave mandatoryProperties empty
             */
        }

        /*
         * finally save all leaf properties (a CompoundField never comes in as a
         * property of its name. get its leafs as the input properties ->
         * SimpleFields)
         */
        for (Item item : items.values()) {
            if (item instanceof CompoundItem) {
                addLeafProperties((CompoundItem) item, inputProperties);
            } else {
                inputProperties.add(item.getProperty());
            }
        }

        result.setLocation(location);
        result.setTime(time);
        result.setMobile(mobile);
        result.setMetadata(metadata);
        result.setName(name);
        result.setSensorML(sensorML);
        result.setInputProperties(inputProperties);
        result.setOutputProperties(outputProperties);
        result.setMandatoryProperties(mandatoryProperties);
        result.setItems(items);
        result.setOutputType(outputType);

        return result;
    }

    /**
     * helper method to get CRS specific axis ordering.
     * this can be understood as some kind of catalog.
     * 
     * @param referenceFrame the CRS
     * @return 3-element String array containg "x", "y" and "z"
     */
    private static String[] getAxisOrder(String referenceFrame) {
        if (referenceFrame.equals("urn:ogc:def:crs:EPSG::4326")) {
            return new String[] { "y", "x", "z" };
        }

        return new String[] { "x", "y", "z" };
    }

    /**
     * adds all leaf properties of a {@link CompoundItem} (e.g., 
     * {@link Location}) to a collection.
     * 
     * @param item the {@link CompoundItem}
     * @param coll the collection
     */
    private static void addLeafProperties(CompoundItem item, Collection<String> coll) {
        for (Item it : item.getCompoundItems()) {
            if (it instanceof CompoundItem) {
                addLeafProperties((CompoundItem) it, coll);
            } else {
                coll.add(it.getProperty());
            }
        }
    }

    public static void updateSensorML(Plugin plug) {
        AbstractProcessType prcs = plug.getSensorML().getMemberArray(0).getProcess();

        if (prcs instanceof SystemType) {
            SystemType system = (SystemType) prcs;

            /*
             * metadata
             */
            if (plug.getMetadata() != null) {

                /*
                 * contact
                 */
                if (system.getContactArray().length > 0) {
                    for (int i = 0; i < system.getContactArray().length; i++) {
                        system.removeContact(0);
                    }
                }
                Contact contact = system.addNewContact();
                ResponsibleParty party = contact.addNewResponsibleParty();
                ContactInfo info = party.addNewContactInfo();
                Address addr = info.addNewAddress();
                addr.setElectronicMailAddress(plug.getMetadata().getContactEmail());

                /*
                 * identification
                 */
                if (system.getIdentificationArray().length > 0) {
                    for (int i = 0; i < system.getIdentificationArray().length; i++) {
                        system.removeIdentification(0);
                    }
                }
                Identification ident = system.addNewIdentification();
                IdentifierList list = ident.addNewIdentifierList();
                Identifier id = list.addNewIdentifier();
                id.setName("uniqueID");
                Term term = id.addNewTerm();
                term.setDefinition("urn:ogc:def:identifier:OGC:uniqueID");
                term.setValue(plug.getMetadata().getUniqueID());

                if (plug.getMetadata().isMobile()) {
                    /*
                     * generate a boundedBy element
                     */
                    BoundingShapeType bby = null;
                    if (system.isSetBoundedBy()) {
                        bby = system.getBoundedBy();
                    } else {
                        bby = system.addNewBoundedBy();
                    }

                    EnvelopeType enve = EnvelopeType.Factory.newInstance();
                    enve.setSrsName("urn:ogc:def:crs:EPSG::4326");
                    DirectPositionType low = enve.addNewLowerCorner();
                    DirectPositionType hi = enve.addNewUpperCorner();
                    String[] pos = plug.getMetadata().getPosition().split(" ");
                    if (pos.length == 2) {
                        double lowLat = Double.parseDouble(pos[0]) - 1.0;
                        double lowLon = Double.parseDouble(pos[1]) - 1.0;
                        double hiLat = Double.parseDouble(pos[0]) + 1.0;
                        double hiLon = Double.parseDouble(pos[1]) + 1.0;

                        low.setStringValue(lowLat + " " + lowLon);
                        hi.setStringValue(hiLat + " " + hiLon);
                    } else {
                        low.setStringValue(plug.getMetadata().getPosition());
                        hi.setStringValue(plug.getMetadata().getPosition());
                    }

                    bby.setEnvelope(enve);
                } else {
                    /*
                     * generate a static position
                     */
                    Position posi = null;
                    if (system.isSetPosition()) {
                        posi = system.getPosition();
                    } else {
                        posi = system.addNewPosition();
                    }

                    posi.setName("position");
                    PositionType postype = PositionType.Factory.newInstance();
                    postype.setReferenceFrame("urn:ogc:def:crs:EPSG::4326");
                    VectorPropertyType loc = postype.addNewLocation();
                    VectorType vec = loc.addNewVector();

                    String[] pos = plug.getMetadata().getPosition().split(" ");
                    if (pos.length == 2) {
                        /*
                         * latitude
                         */
                        Coordinate coord = vec.addNewCoordinate();
                        coord.setName("latitude");
                        Quantity quan = coord.addNewQuantity();
                        UomPropertyType uom = quan.addNewUom();
                        uom.setCode("deg");
                        quan.setValue(Double.parseDouble(pos[0]));

                        /*
                         * longitude
                         */
                        Coordinate coord2 = vec.addNewCoordinate();
                        coord2.setName("longitude");
                        Quantity quan2 = coord2.addNewQuantity();
                        UomPropertyType uom2 = quan2.addNewUom();
                        uom2.setCode("deg");
                        quan2.setValue(Double.parseDouble(pos[1]));
                    }

                    posi.setPosition(postype);
                }
            }

            /*
             * generate output xml of inputlist
             */
            InputList inputs = system.getInputs().getInputList();

            if (inputs == null) {
                /*
                 * minimal document before. create inputlist
                 */
                inputs = system.getInputs().addNewInputList();
            }

            List<String> smlInputNames = new ArrayList<String>();
            /*
             * first gather all names
             */
            for (IoComponentPropertyType in : inputs.getInputArray()) {
                smlInputNames.add(in.getName());
            }

            /*
             * we need to check if outputs are there
             */
            if (!system.getOutputs().isSetOutputList()) {
                system.getOutputs().addNewOutputList();
            }

            for (String key : plug.getItems().keySet()) {
                if (!smlInputNames.contains(key)) {
                    /*
                     * perhaps its the time?
                     */
                    if (plug.getTime().getProperty().equals(key)) {
                        IoComponentPropertyType newIn = system.getInputs().getInputList().addNewInput();
                        IoComponentPropertyType newOut = system.getOutputs().getOutputList().addNewOutput();
                        newIn.setName(key);
                        newOut.setName(key);

                        TimeDocument.Time t = newIn.addNewTime();
                        t.setReferenceFrame(plug.getTime().getReferenceFrame());
                        t.setDefinition(plug.getTime().getDefinition());

                        TimeDocument.Time t2 = newOut.addNewTime();
                        t2.setReferenceFrame(plug.getTime().getReferenceFrame());
                        t2.setDefinition(plug.getTime().getDefinition());

                        continue;
                    }

                    /*
                     * this has been added probably by pnp mode
                     */
                    IoComponentPropertyType newIn = system.getInputs().getInputList().addNewInput();
                    IoComponentPropertyType newOut = system.getOutputs().getOutputList().addNewOutput();
                    newIn.setName(key);
                    newOut.setName(key);
                    Item item = plug.getItems().get(key);
                    Class<?> type = item.getDataType();

                    if (type == Double.class) {
                        Quantity quan = newIn.addNewQuantity();
                        Quantity quan2 = newOut.addNewQuantity();
                        UomPropertyType uom = UomPropertyType.Factory.newInstance();
                        uom.setCode(item.getUom());
                        quan.setUom(uom);
                        quan2.setUom(uom);
                        quan.setDefinition(item.getDefinition());
                        quan2.setDefinition(item.getDefinition());
                    } else if (type == String.class) {
                        Text text = newIn.addNewText();
                        Text text2 = newOut.addNewText();
                        text.setDefinition(item.getDefinition());
                        text2.setDefinition(item.getDefinition());
                    } else if (type == Boolean.class) {
                        Boolean bool = newIn.addNewBoolean();
                        Boolean bool2 = newOut.addNewBoolean();
                        bool.setDefinition(item.getDefinition());
                        bool2.setDefinition(item.getDefinition());
                    }
                }
            }
        }
    }

    public static void newSensorML(Plugin plug) {
        SensorML sml = SensorML.Factory.newInstance();

        sml.setVersion("1.0.1");
        Member member = sml.addNewMember();

        SystemType system = SystemType.Factory.newInstance();

        system.addNewInputs().addNewInputList();
        system.addNewOutputs().addNewOutputList();

        member.setProcess(system);
        XMLTools.replaceXsiTypeWithInstance(member.getProcess(), new QName(Plugin.SENSORML_NAMESPACE, "System"));

        plug.setSensorML(sml);
        updateSensorML(plug);
    }

    public static String toXML(Plugin plug) {
        /*
         * define some settings
         */
        Map<String, String> pres = new HashMap<String, String>();
        pres.put(Plugin.SENSORML_NAMESPACE, "sml");
        pres.put(Plugin.SPF_PLUGIN_NAMESPACE, "spf");

        XmlOptions opts = new XmlOptions();
        opts.setSavePrettyPrint();
        opts.setSaveSuggestedPrefixes(pres);
        opts.setSaveAggressiveNamespaces();

        PluginDocument pdoc = PluginDocument.Factory.newInstance(opts);
        PluginType plugin = pdoc.addNewPlugin();

        Output output = plugin.addNewOutput();

        /*
         * we have period behaviour
         */
        if (plug.getOutputType().equals(Plugin.PERIOD_BEHAVIOUR)) {
            PeriodBehaviourType period = PeriodBehaviourType.Factory.newInstance(opts);
            period.setTimedelta(plug.getTimeDelta());

            output.setBehaviour(period);
            XMLTools.replaceXsiTypeWithInstance(output.getBehaviour(),
                    new QName(Plugin.SPF_PLUGIN_NAMESPACE, "PeriodBehaviour"));
        }
        /*
         * we have availability behaviour
         */
        else {
            AvailabilityBehaviourType avail = AvailabilityBehaviourType.Factory.newInstance(opts);
            OutputProperties props = avail.addNewOutputProperties();

            for (String key : plug.getOutputProperties()) {
                props.addProperty(key);
            }

            output.setBehaviour(avail);
            XMLTools.replaceXsiTypeWithInstance(output.getBehaviour(),
                    new QName(Plugin.SPF_PLUGIN_NAMESPACE, "AvailabilityBehaviour"));
        }

        /*
         * check if we have mandatories
         */
        if (plug.getInputProperties().size() == plug.getMandatoryProperties().size()) {
            /*
             * "on all"
             */
            output.setOutputOnAllItems(true);
        } else if (plug.getMandatoryProperties().size() == 0) {
            /*
             * "single allowed"
             */
            output.setSingleOutputAllowed(true);
        } else {
            /*
             * mandatories
             */
            MandatoryProperties mandas = output.addNewMandatoryProperties();

            for (String key : plug.getMandatoryProperties()) {
                mandas.addProperty(key);
            }
        }

        /*
         * we need a Time item
         */
        boolean hasTime = false;
        for (Item item : plug.getItems().values()) {
            if (item instanceof Time) {
                hasTime = true;
                break;
            }
        }

        if (!hasTime) {
            /*
             * add a standard time item
             */
            plug.setTime(new Time("time"));
            plug.getTime().setReferenceFrame("urn:ogc:def:unit:iso8601");
            plug.getTime().setDefinition("urn:ogc:def:phenomenon:time");
            plug.getItems().put(plug.getTime().getProperty(), plug.getTime());
        }

        /*
         * SensorML parts
         */
        if (plug.getSensorML() != null) {
            updateSensorML(plug);
        } else {
            newSensorML(plug);
        }

        plugin.setSensorML(plug.getSensorML());

        plugin.setName(plug.getName());

        /*
         * output of the xml
         */
        XmlOptions opts2 = new XmlOptions();
        opts2.setSavePrettyPrint();
        pres = new HashMap<String, String>();
        pres.put(Plugin.SENSORML_NAMESPACE, "sml");
        opts2.setSaveSuggestedPrefixes(pres);

        try {
            PluginDocument tmp = PluginDocument.Factory.parse(pdoc.getDomNode());
            return tmp.xmlText(opts2);
        } catch (XmlException e) {
            log.error(e);
        }

        return pdoc.xmlText(opts2);
    }
}