/*
 * Copyright (C) 2009-2011 Mathias Doenitz
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.fge.grappa.support;

import java.util.Arrays;
import java.util.Objects;

/**
 * An immutable, set-like aggregation of (relatively few) characters that allows
 * for an inverted semantic ("all chars except these few").
 */
public final class Characters
{
    private static final char[] NO_CHARS = new char[0];

    /**
     * The empty Characters set
     */
    public static final Characters NONE = new Characters(false, NO_CHARS);

    /**
     * The Characters set including all character.
     */
    public static final Characters ALL = new Characters(true, NO_CHARS);

    // if the set is subtractive its semantics change from "includes all
    // characters in the set" to "includes all characters not in the set"
    private final boolean subtractive;
    private final char[] chars;

    /**
     * Creates a new Characters instance containing only the given char.
     *
     * @param c the char
     * @return a new Characters object
     */
    public static Characters of(final char c)
    {
        return new Characters(false, new char[]{ c });
    }

    /**
     * Creates a new Characters instance containing only the given chars.
     *
     * @param chars the chars
     * @return a new Characters object
     */
    public static Characters of(final char... chars)
    {
        final int length = chars.length;
        if (length == 0)
            return NONE;
        final char[] array = Arrays.copyOf(chars, length);
        Arrays.sort(array);
        return new Characters(false, array);
    }

    /**
     * Creates a new Characters instance containing only the given chars.
     *
     * @param chars the chars
     * @return a new Characters object
     */
    public static Characters of(final String chars)
    {
        return chars.isEmpty() ? NONE : of(chars.toCharArray());
    }

    /**
     * Creates a new Characters instance containing all characters minus the given ones.
     *
     * @param chars the chars to NOT include
     * @return a new Characters object
     */
    public static Characters allBut(final char... chars)
    {
        final int length = chars.length;
        if (length == 0)
            return ALL;
        final char[] array = Arrays.copyOf(chars, length);
        Arrays.sort(array);
        return new Characters(true, array);
    }

    private Characters(final boolean subtractive, final char[] chars)
    {
        this.subtractive = subtractive;
        this.chars = Objects.requireNonNull(chars, "chars");
    }

    /**
     * @return true if the set is subtractive
     */
    public boolean isSubtractive()
    {
        return subtractive;
    }

    /**
     * Returns the characters in this set, if it is additive.
     * If the set is subtractive the method returns the characters <b>not</b> in the set.
     *
     * @return the characters
     */
    public char[] getChars()
    {
        return chars;
    }

    /**
     * Determines whether this instance contains the given character.
     *
     * @param c the character to check for
     * @return true if this instance contains c
     */
    public boolean contains(final char c)
    {
        final int index = Arrays.binarySearch(chars, c);
        return index < 0 == subtractive;
    }

    @Override
    public String toString()
    {
        final StringBuilder sb = new StringBuilder();
        sb.append(subtractive ? "![" : "[");
        for (final char c : chars) {
            sb.append(Chars.escape(c));
        }
        sb.append(']');
        return sb.toString();
    }

    @Override
    public boolean equals(final Object obj)
    {
        if (this == obj)
            return true;
        if (!(obj instanceof Characters))
            return false;
        final Characters other = (Characters) obj;
        return subtractive == other.subtractive
            && Arrays.equals(chars, other.chars);
    }

    @Override
    public int hashCode()
    {
        return Arrays.hashCode(chars) + (subtractive ? 31 : 0);
    }
}


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2014.01.23 at 10:11:20 AM CET
//

package com.tibco.xmlns.applicationmanagement;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.tibco.xmlns.authentication.RequiresAuthentication;
import com.tibco.xmlns.dd.ClassLoaderExtension;
import com.tibco.xmlns.dd.CustomTSMPlugInConfiguration;
import com.tibco.xmlns.dd.DeploymentDescriptorFactory;
import com.tibco.xmlns.dd.DeploymentDescriptorType;
import com.tibco.xmlns.dd.DiffExcludeFilter;
import com.tibco.xmlns.dd.Modules;
import com.tibco.xmlns.dd.NameValuePairs;
import com.tibco.xmlns.dd.RequiredComponents;
import com.tibco.xmlns.dd.StartAsOneOf;
import com.tibco.xmlns.dd.SupportsFaultTolerance;

/**
 *
Java class for anonymous complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType>
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element ref="{http://www.tibco.com/xmlns/dd}DeploymentDescriptor" maxOccurs="unbounded" minOccurs="0"/>
 *         <element name="extends" type="{http://www.tibco.com/xmlns/ApplicationManagement}anyObject" minOccurs="0"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "deploymentDescriptor",
    "_extends"
})
@XmlRootElement(name = "plugins")
public class Plugins {

    @XmlElementRef(name = "DeploymentDescriptor", namespace = "http://www.tibco.com/xmlns/dd", type = JAXBElement.class)
    protected List<JAXBElement<? extends DeploymentDescriptorType>> deploymentDescriptor;
    @XmlElementRef(name = "extends", namespace = "http://www.tibco.com/xmlns/ApplicationManagement", type = JAXBElement.class)
    protected JAXBElement<AnyObject> _extends;

    /**
     * Gets the value of the deploymentDescriptor property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the deploymentDescriptor property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getDeploymentDescriptor().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link JAXBElement }{@code <}{@link DeploymentDescriptorFactory }{@code >}
     * {@link JAXBElement }{@code <}{@link Modules }{@code >}
     * {@link JAXBElement }{@code <}{@link DeploymentDescriptorType }{@code >}
     * {@link JAXBElement }{@code <}{@link StartAsOneOf }{@code >}
     * {@link JAXBElement }{@code <}{@link CustomTSMPlugInConfiguration }{@code >}
     * {@link JAXBElement }{@code <}{@link DiffExcludeFilter }{@code >}
     * {@link JAXBElement }{@code <}{@link ClassLoaderExtension }{@code >}
     * {@link JAXBElement }{@code <}{@link RequiresAuthentication }{@code >}
     * {@link JAXBElement }{@code <}{@link NameValuePairs }{@code >}
     * {@link JAXBElement }{@code <}{@link SupportsFaultTolerance }{@code >}
     * {@link JAXBElement }{@code <}{@link RequiredComponents }{@code >}
     *
     *
     */
    public List<JAXBElement<? extends DeploymentDescriptorType>> getDeploymentDescriptor() {
        if (deploymentDescriptor == null) {
            deploymentDescriptor = new ArrayList<JAXBElement<? extends DeploymentDescriptorType>>();
        }
        return this.deploymentDescriptor;
    }

    /**
     * Gets the value of the extends property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link AnyObject }{@code >}
     *
     */
    public JAXBElement<AnyObject> getExtends() {
        return _extends;
    }

    /**
     * Sets the value of the extends property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link AnyObject }{@code >}
     *
     */
    public void setExtends(JAXBElement<AnyObject> value) {
        this._extends = ((JAXBElement<AnyObject> ) value);
    }

}


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2014.01.23 at 10:11:20 AM CET
//

package com.tibco.xmlns.authentication;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;

/**
 * This object contains factory methods for each
 * Java content interface and Java element interface
 * generated in the com.tibco.xmlns.authentication package.
 *
An ObjectFactory allows you to programatically
 * construct new instances of the Java representation
 * for XML content. The Java representation of XML
 * content can consist of schema derived interfaces
 * and classes representing the binding of schema
 * type definitions, element declarations and model
 * groups.  Factory methods for each of these are
 * provided in this class.
 *
 */
@XmlRegistry
public class ObjectFactory {

    private final static QName _CookieAuthenticationConfiguration_QNAME = new QName("http://www.tibco.com/xmlns/authentication", "CookieAuthenticationConfiguration");
    private final static QName _URLAuthenticationConfiguration_QNAME = new QName("http://www.tibco.com/xmlns/authentication", "URLAuthenticationConfiguration");
    private final static QName _RequiresAuthentication_QNAME = new QName("http://www.tibco.com/xmlns/authentication", "RequiresAuthentication");
    private final static QName _WebServerAuthenticationConfiguration_QNAME = new QName("http://www.tibco.com/xmlns/authentication", "WebServerAuthenticationConfiguration");
    private final static QName _HttpSessionAuthenticationConfiguration_QNAME = new QName("http://www.tibco.com/xmlns/authentication", "HttpSessionAuthenticationConfiguration");
    private final static QName _CustomAuthenticationConfiguration_QNAME = new QName("http://www.tibco.com/xmlns/authentication", "CustomAuthenticationConfiguration");
    private final static QName _AuthenticationConfiguration_QNAME = new QName("http://www.tibco.com/xmlns/authentication", "AuthenticationConfiguration");

    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.tibco.xmlns.authentication
     *
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link HttpSessionAuthenticationConfiguration }
     *
     */
    public HttpSessionAuthenticationConfiguration createHttpSessionAuthenticationConfiguration() {
        return new HttpSessionAuthenticationConfiguration();
    }

    /**
     * Create an instance of {@link CredentialAuthenticationConfigurationType }
     *
     */
    public CredentialAuthenticationConfigurationType createCredentialAuthenticationConfigurationType() {
        return new CredentialAuthenticationConfigurationType();
    }

    /**
     * Create an instance of {@link URLAuthenticationConfiguration }
     *
     */
    public URLAuthenticationConfiguration createURLAuthenticationConfiguration() {
        return new URLAuthenticationConfiguration();
    }

    /**
     * Create an instance of {@link WebServerAuthenticationConfiguration }
     *
     */
    public WebServerAuthenticationConfiguration createWebServerAuthenticationConfiguration() {
        return new WebServerAuthenticationConfiguration();
    }

    /**
     * Create an instance of {@link AuthenticationConfigurationType }
     *
     */
    public AuthenticationConfigurationType createAuthenticationConfigurationType() {
        return new AuthenticationConfigurationType();
    }

    /**
     * Create an instance of {@link CookieAuthenticationConfiguration }
     *
     */
    public CookieAuthenticationConfiguration createCookieAuthenticationConfiguration() {
        return new CookieAuthenticationConfiguration();
    }

    /**
     * Create an instance of {@link RequiresAuthentication }
     *
     */
    public RequiresAuthentication createRequiresAuthentication() {
        return new RequiresAuthentication();
    }

    /**
     * Create an instance of {@link CustomAuthenticationConfiguration }
     *
     */
    public CustomAuthenticationConfiguration createCustomAuthenticationConfiguration() {
        return new CustomAuthenticationConfiguration();
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link CookieAuthenticationConfiguration }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://www.tibco.com/xmlns/authentication", name = "CookieAuthenticationConfiguration", substitutionHeadNamespace = "http://www.tibco.com/xmlns/authentication", substitutionHeadName = "AuthenticationConfiguration")
    public JAXBElement<CookieAuthenticationConfiguration> createCookieAuthenticationConfiguration(CookieAuthenticationConfiguration value) {
        return new JAXBElement<CookieAuthenticationConfiguration>(_CookieAuthenticationConfiguration_QNAME, CookieAuthenticationConfiguration.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link URLAuthenticationConfiguration }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://www.tibco.com/xmlns/authentication", name = "URLAuthenticationConfiguration", substitutionHeadNamespace = "http://www.tibco.com/xmlns/authentication", substitutionHeadName = "AuthenticationConfiguration")
    public JAXBElement<URLAuthenticationConfiguration> createURLAuthenticationConfiguration(URLAuthenticationConfiguration value) {
        return new JAXBElement<URLAuthenticationConfiguration>(_URLAuthenticationConfiguration_QNAME, URLAuthenticationConfiguration.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link RequiresAuthentication }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://www.tibco.com/xmlns/authentication", name = "RequiresAuthentication", substitutionHeadNamespace = "http://www.tibco.com/xmlns/dd", substitutionHeadName = "DeploymentDescriptor")
    public JAXBElement<RequiresAuthentication> createRequiresAuthentication(RequiresAuthentication value) {
        return new JAXBElement<RequiresAuthentication>(_RequiresAuthentication_QNAME, RequiresAuthentication.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link WebServerAuthenticationConfiguration }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://www.tibco.com/xmlns/authentication", name = "WebServerAuthenticationConfiguration", substitutionHeadNamespace = "http://www.tibco.com/xmlns/authentication", substitutionHeadName = "AuthenticationConfiguration")
    public JAXBElement<WebServerAuthenticationConfiguration> createWebServerAuthenticationConfiguration(WebServerAuthenticationConfiguration value) {
        return new JAXBElement<WebServerAuthenticationConfiguration>(_WebServerAuthenticationConfiguration_QNAME, WebServerAuthenticationConfiguration.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link HttpSessionAuthenticationConfiguration }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://www.tibco.com/xmlns/authentication", name = "HttpSessionAuthenticationConfiguration", substitutionHeadNamespace = "http://www.tibco.com/xmlns/authentication", substitutionHeadName = "AuthenticationConfiguration")
    public JAXBElement<HttpSessionAuthenticationConfiguration> createHttpSessionAuthenticationConfiguration(HttpSessionAuthenticationConfiguration value) {
        return new JAXBElement<HttpSessionAuthenticationConfiguration>(_HttpSessionAuthenticationConfiguration_QNAME, HttpSessionAuthenticationConfiguration.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link CustomAuthenticationConfiguration }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://www.tibco.com/xmlns/authentication", name = "CustomAuthenticationConfiguration", substitutionHeadNamespace = "http://www.tibco.com/xmlns/authentication", substitutionHeadName = "AuthenticationConfiguration")
    public JAXBElement<CustomAuthenticationConfiguration> createCustomAuthenticationConfiguration(CustomAuthenticationConfiguration value) {
        return new JAXBElement<CustomAuthenticationConfiguration>(_CustomAuthenticationConfiguration_QNAME, CustomAuthenticationConfiguration.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link AuthenticationConfigurationType }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://www.tibco.com/xmlns/authentication", name = "AuthenticationConfiguration")
    public JAXBElement<AuthenticationConfigurationType> createAuthenticationConfiguration(AuthenticationConfigurationType value) {
        return new JAXBElement<AuthenticationConfigurationType>(_AuthenticationConfiguration_QNAME, AuthenticationConfigurationType.class, null, value);
    }

}


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2014.01.23 at 10:11:20 AM CET
//

package com.tibco.xmlns.applicationmanagement;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.tibco.xmlns.authentication.AuthenticationConfigurationType;
import com.tibco.xmlns.authentication.CookieAuthenticationConfiguration;
import com.tibco.xmlns.authentication.CustomAuthenticationConfiguration;
import com.tibco.xmlns.authentication.HttpSessionAuthenticationConfiguration;
import com.tibco.xmlns.authentication.URLAuthenticationConfiguration;
import com.tibco.xmlns.authentication.WebServerAuthenticationConfiguration;

/**
 *
Java class for anonymous complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType>
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element ref="{http://www.tibco.com/xmlns/authentication}AuthenticationConfiguration" maxOccurs="unbounded" minOccurs="0"/>
 *       </sequence>
 *       <attribute name="selected" type="{http://www.w3.org/2001/XMLSchema}string" />
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "authenticationConfiguration"
})
@XmlRootElement(name = "authentications")
public class Authentications {

    @XmlElementRef(name = "AuthenticationConfiguration", namespace = "http://www.tibco.com/xmlns/authentication", type = JAXBElement.class)
    protected List<JAXBElement<? extends AuthenticationConfigurationType>> authenticationConfiguration;
    @XmlAttribute
    protected String selected;

    /**
     * Gets the value of the authenticationConfiguration property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the authenticationConfiguration property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getAuthenticationConfiguration().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link JAXBElement }{@code <}{@link CookieAuthenticationConfiguration }{@code >}
     * {@link JAXBElement }{@code <}{@link URLAuthenticationConfiguration }{@code >}
     * {@link JAXBElement }{@code <}{@link CustomAuthenticationConfiguration }{@code >}
     * {@link JAXBElement }{@code <}{@link WebServerAuthenticationConfiguration }{@code >}
     * {@link JAXBElement }{@code <}{@link AuthenticationConfigurationType }{@code >}
     * {@link JAXBElement }{@code <}{@link HttpSessionAuthenticationConfiguration }{@code >}
     *
     *
     */
    public List<JAXBElement<? extends AuthenticationConfigurationType>> getAuthenticationConfiguration() {
        if (authenticationConfiguration == null) {
            authenticationConfiguration = new ArrayList<JAXBElement<? extends AuthenticationConfigurationType>>();
        }
        return this.authenticationConfiguration;
    }

    /**
     * Gets the value of the selected property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getSelected() {
        return selected;
    }

    /**
     * Sets the value of the selected property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setSelected(String value) {
        this.selected = value;
    }

}


/**
 * (C) Copyright 2011-2015 FastConnect SAS
 * (http://www.fastconnect.fr/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package fr.fastconnect.factory.tibco.bw.maven.doc;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.xml.bind.JAXBException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.maven.model.FileSet;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;

import fr.fastconnect.factory.tibco.bw.maven.AbstractBWMojo;
import fr.fastconnect.factory.tibco.bw.maven.source.AbstractProjectsListMojo;
import fr.fastconnect.factory.tibco.bw.maven.source.ProcessModel;

/**
 * <p>
 * This goal generates an XML documentation file from TIBCO BusinessWorks source
 * files.
 * </p>
 *
 * @author Mathieu Debove
 *
 */
public abstract class AbstractDocMojo extends AbstractBWMojo {

	/**
	 * Path to the output folder.
	 *
	 * Default is "target/doc"
	 */
	@Parameter( property = "project.doc.directory",
				required=true,
				defaultValue = "target/doc" )
	protected File docDirectory;

	/**
	 * The list of files to process for documentation.
	 */
	private List<File> files;

	public abstract void processFile(File f) throws MojoExecutionException;

	/**
	 * @throws JAXBException
	 *
	 */
	protected String getDescription(File f) throws JAXBException {
		ProcessModel pm = new ProcessModel(f);

		String description = pm.getProcess().getDescription();

		return description;
	}

	@Override
	public void execute() throws MojoExecutionException {
		super.execute();

		if (!docDirectory.exists()) {
			docDirectory.mkdirs();
		}

		getLog().info("Generating project documentation in '" + docDirectory + '"');

		try {
			files = initFiles(); // look for ".process" files in "target/src" folder
		} catch (IOException e) {
			throw new MojoExecutionException(e.getMessage(), e);
		}

		for (File f : this.getFiles()) {
			processFile(f);
		}
	}

	public List<File> getFiles() {
		return files;
	}

	protected File getDirectoryToProcess() {
		return buildSrcDirectory;
	}

	protected List<File> initFiles() throws IOException {
		getLog().debug("Looking for files to process...");

		FileSet restriction = new FileSet();
		File directory = getDirectoryToProcess();
		if (directory == null) {
			directory = new File(".");
		}
		restriction.setDirectory(directory.getAbsolutePath());

		restriction.addInclude("**/*.process");

		return AbstractProjectsListMojo.toFileList(restriction);
	}

    public void applyXSL(File in, File out, InputStream inputStream) throws MojoExecutionException {
        try {
            TransformerFactory factory = TransformerFactory.newInstance();

            Templates template = factory.newTemplates(new StreamSource(inputStream));

            Transformer xformer = template.newTransformer();

            Source source = new StreamSource(new FileInputStream(in));
            Result result = new StreamResult(new FileOutputStream(out));

            xformer.transform(source, result);
        } catch (Exception e) {
        	throw new MojoExecutionException(e.getMessage(), e);
        }
    }
}


/**
 * (C) Copyright 2011-2015 FastConnect SAS
 * (http://www.fastconnect.fr/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package fr.fastconnect.factory.tibco.bw.maven.packaging;

import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;

import org.apache.commons.io.FilenameUtils;

import com.tibco.xmlns.applicationmanagement.ActionType;
import com.tibco.xmlns.applicationmanagement.Actions;
import com.tibco.xmlns.applicationmanagement.Adapter;
import com.tibco.xmlns.applicationmanagement.AlertAction;
import com.tibco.xmlns.applicationmanagement.ApplicationType;
import com.tibco.xmlns.applicationmanagement.Binding;
import com.tibco.xmlns.applicationmanagement.Bindings;
import com.tibco.xmlns.applicationmanagement.Bw;
import com.tibco.xmlns.applicationmanagement.Bwprocess;
import com.tibco.xmlns.applicationmanagement.Bwprocesses;
import com.tibco.xmlns.applicationmanagement.Checkpoints;
import com.tibco.xmlns.applicationmanagement.CustomAction;
import com.tibco.xmlns.applicationmanagement.EmailAction;
import com.tibco.xmlns.applicationmanagement.Events;
import com.tibco.xmlns.applicationmanagement.EventType;
import com.tibco.xmlns.applicationmanagement.FailureEvent;
import com.tibco.xmlns.applicationmanagement.FaultTolerant;
import com.tibco.xmlns.applicationmanagement.LogEvent;
import com.tibco.xmlns.applicationmanagement.Monitor;
import com.tibco.xmlns.applicationmanagement.NVPairType;
import com.tibco.xmlns.applicationmanagement.NVPairs;
import com.tibco.xmlns.applicationmanagement.NameValuePair;
import com.tibco.xmlns.applicationmanagement.Product;
import com.tibco.xmlns.applicationmanagement.RepoInstances;
import com.tibco.xmlns.applicationmanagement.ServiceType;
import com.tibco.xmlns.applicationmanagement.Setting;
import com.tibco.xmlns.applicationmanagement.Setting.Java;
import com.tibco.xmlns.applicationmanagement.Setting.NTService;
import com.tibco.xmlns.applicationmanagement.Shutdown;

/**
 *

 * This class will

 *
unmarshall XML file of the schema with
 * "http://www.tibco.com/xmlns/ApplicationManagement" namespace to JAXB objects.
 *

 *

 * marshall the {@link ApplicationType} object back to XML file with the same
 * schema.
 *

 *

 *

 *
 * @author Mathieu Debove
 *
 */
public class ApplicationManagement {
	private static final String APPLICATION_MANAGEMENT_NAMESPACE = "http://www.tibco.com/xmlns/ApplicationManagement";

	private ApplicationType application;
	private JAXBContext jaxbContext;
	private HashMap<String, Object> map;
	private Pattern patternElement;
	private File xmlFile;

	public ApplicationManagement(File xmlFile) throws JAXBException {
		this.map = new HashMap<String, Object>();
		this.patternElement = Pattern.compile("(\\w+)(\\[([\\w- \\*\\.\\/?]*)\\])?");
		this.xmlFile = xmlFile;
		initApplication();
	}

	/**
	 *

	 * This will initialize the {@link ApplicationType} object which is a JAXB
	 * representation of the "application" root-element of TIBCO XML Deployment
	 * Descriptor files using the schema with
	 * "http://www.tibco.com/xmlns/ApplicationManagement" namespace.
	 *

	 *
	 * @throws JAXBException
	 */
	private void initApplication() throws JAXBException {
		jaxbContext = JAXBContext.newInstance(
				com.tibco.xmlns.applicationmanagement.ObjectFactory.class,
				com.tibco.xmlns.applicationmanagement.bw.ObjectFactory.class,
				com.tibco.xmlns.dd.ObjectFactory.class);

		Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
		Object o =  jaxbUnmarshaller.unmarshal(xmlFile);
		try {
			this.application = (ApplicationType) o;
		} catch (ClassCastException e) {
			// strange workaround: sometimes we get an ApplicationType object,
			// sometimes a JAXBElement<ApplicationType> object

			@SuppressWarnings("unchecked")
			JAXBElement<ApplicationType> j = (JAXBElement<ApplicationType>) o;
			this.application = j.getValue();
		}
	}

	/**
	 *

	 * This inner-class extends java.util.Properties with all properties sorted
	 * alphabetically. Also, the setProperty method is overridden to support
	 * multiple input types and check for null values.
	 *

	 *
	 */
	public static class SortedProperties extends Properties {
		private static final long serialVersionUID = 3733070302160913988L;

		@Override
	    public synchronized Enumeration<Object> keys() {
	        return Collections.enumeration(new TreeSet<Object>(super.keySet()));
	    }

		@Override
		public synchronized Object setProperty(String key, String value) {
			if (value != null) {
				return super.setProperty(key, value);
			}
			return null;
		}

		public synchronized Object setProperty(String key, BigInteger value) {
			if (value != null) {
				return super.setProperty(key, value.toString());
			}
			return null;
		}

		public synchronized Object setProperty(String key, Boolean value) {
			if (value != null) {
				return super.setProperty(key, value.toString());
			}
			return null;
		}

	}

	/**
	 *

	 * This will marshall the object back to the XML file.
	 *

	 *
	 * @throws JAXBException
	 */
	public void save() throws JAXBException {
		Marshaller m = jaxbContext.createMarshaller();
		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		m.marshal(application, xmlFile);
	}

	// private helpers
	/**
	* This method retrieves the Global Variables at application level
	*/
	private NVPairs getGlobalVariablesPairs() {
		if (application.getNVPairs().getName().equals("Global Variables")) {
			return application.getNVPairs();
		} else {
			return null;
		}
	}

	/**
	* This method retrieves the list of objects of type "BWServiceType".
	*/
	private List<Bw> getBWServices() {
		List<Bw> result = new ArrayList<Bw>();

		for (JAXBElement<? extends ServiceType> jaxbElement : application.getServices().getBaseService()) {
			if (jaxbElement.getName().getLocalPart().equals("bw")) {
				result.add((Bw) jaxbElement.getValue());
			}
		}

		return result;
	}

	private List<Adapter> getAdapterServices() {
		List<Adapter> result = new ArrayList<Adapter>();

		for (JAXBElement<? extends ServiceType> jaxbElement : application.getServices().getBaseService()) {
			if (jaxbElement.getName().getLocalPart().equals("adapter")) {
				result.add((Adapter) jaxbElement.getValue());
			}
		}

		return result;
	}

	public List<String> getInstancesNames(boolean onlyEnabledServices) {
		List<String> result = new ArrayList<String>();

		List<Bw> bwServices = getBWServices();

		for (Bw bw : bwServices) {
			Bindings bindings = bw.getBindings();
			boolean enabled = bw.isEnabled();

			if (!enabled && onlyEnabledServices) {
				continue; // keep only enabled services
			}

			for (Binding binding : bindings.getBinding()) {
				String name = binding.getName();
				if (name == null || name.isEmpty()) {
					name = FilenameUtils.getBaseName(bw.getName());
				}
				result.add(name);
			}
		}

		return result;
	}

	/**
	* This method retrieves {@link Bwprocesses} object from Bw.getRest() objects
	*/
	private Bwprocesses getBWProcesses(Bw bwService) {
		for (Object o : bwService.getRest()) {
			if (o.getClass().equals(Bwprocesses.class)) {
				return (Bwprocesses) o;
			}
		}

		return null;
	}

	/**
	* This method retrieves {@link Checkpoints} object from Bw.getRest() objects
	*/
	private Checkpoints getBWCheckpoints(Bw bwService) {
		for (Object o : bwService.getRest()) {
			if (o.getClass().equals(Checkpoints.class)) {
				return (Checkpoints) o;
			}
		}

		return null;
	}

	/**
	* This method retrieves {@link FaultTolerant} object from Bw.getRest()
	* objects
	*/
	private FaultTolerant getBWFaultTolerant(Bw bwService) {
		for (Object o : bwService.getRest()) {
			if (o.getClass().equals(FaultTolerant.class)) {
				return (FaultTolerant) o;
			}
		}

		return null;
	}

	/**
	* This method retrieves "isFt" property from Bw.getRest() objects
	*/
	private Boolean isIsFt(Bw bw) {
		Boolean value = false; // default to false (?)
		for (Object o : bw.getRest()) {
			if (o.getClass().equals(JAXBElement.class)) {
				//  should never be other than Boolean according to
				// com.tibco.xmlns.applicationmanagement.BWServiceType
				@SuppressWarnings("unchecked")
				JAXBElement<Boolean> e = (JAXBElement<Boolean>) o;
				value = e.getValue();
			}
		}

		return value;
	}

	/**
	 * This method sets "isFt" property in Bw.getRest() objects
	 */
	private void setIsFt(Bw bw, Boolean value) {
		for (Object o : bw.getRest()) {
			if (o.getClass().equals(JAXBElement.class)) {
				//  should never be other than Boolean according to
				// com.tibco.xmlns.applicationmanagement.BWServiceType
				@SuppressWarnings("unchecked")
				JAXBElement<Boolean> e = (JAXBElement<Boolean>) o;
				e.setValue(value);
			}
		}
	}
	//

	// unmarshalling part / XML (JAXB) to properties
	/**
	 *

	 * The Global Variables are inside the NVPairs element with @name attribute
	 * equals to "Global Variables" at the root level.
	 *

	 *
	 * @return The Global Variables of the xmlFile in a {@link SortedProperties}
	 * object.
	 */
	public Properties getGlobalVariables() {
		SortedProperties result = new SortedProperties();

		NVPairs globalVariablesPairs = getGlobalVariablesPairs();

		if (globalVariablesPairs != null) {
			for (JAXBElement<? extends NVPairType> nvPair : globalVariablesPairs.getNVPair()) {
				String key = nvPair.getValue().getName();
				String value = nvPair.getValue().getValue();
				result.setProperty(key, value);
			}
		}

		return result;
	}

	public void setGlobalVariable(String key, String value) {
		if (key == null) return;

		NVPairs globalVariablesPairs = getGlobalVariablesPairs();

		if (globalVariablesPairs != null) {
			for (JAXBElement<? extends NVPairType> nvPair : globalVariablesPairs.getNVPair()) {
				if (key.equals(nvPair.getValue().getName())) {
					nvPair.getValue().setValue(value);
				}
			}
		}

	}

	public Properties getServices() {
		SortedProperties result = new SortedProperties();

		result.putAll(getProcessArchives());
		result.putAll(getAdapterArchives());

		return result;
	}

	/**
	 *

	 * This method focuses on all child elements of <bw name="par">. These
	 * elements are defined in the "ServiceType" & "BWServiceType" complexTypes
	 * of the XSD schema.
	 *

	 */
	protected Properties getProcessArchives() {
		SortedProperties result = new SortedProperties();

		List<Bw> bwServices = getBWServices();

		String key;

		for (Bw bwService : bwServices) {
			String serviceKey = "bw[" + bwService.getName() + "]";

			/// "ServiceType" complexType
			// enabled
			key = serviceKey + "/enabled";
			result.setProperty(key, bwService.isEnabled());

			// bindings
			result.putAll(getBindings(bwService));
			// NVPairs
			result.putAll(getNVPairs(bwService));

			// failureCount
			key = serviceKey + "/failureCount";
			result.setProperty(key, bwService.getFailureCount());

			// failureInterval
			key = serviceKey + "/failureInterval";
			result.setProperty(key, bwService.getFailureInterval());

			// monitor

			/// "BWServiceType" complexType
			// bwprocesses
			result.putAll(getProcesses(bwService));

			// checkpoints
			result.putAll(getCheckpoints(bwService));

			// isFt
			key = serviceKey + "/isFt";
			result.setProperty(key, isIsFt(bwService));

			// faultTolerant
			result.putAll(getFaultTolerant(bwService));

			// plugins
			// not supported (too complex)
		}

		return result;
	}

	/**
	 *

	 * This method focuses on all child elements of <adapter name="aar">. These
	 * elements are defined in the "ServiceType" complexType of the XSD schema.
	 *

	 */
	protected Properties getAdapterArchives() {
		SortedProperties result = new SortedProperties();

		List<Adapter> adapters = getAdapterServices();

		String key;

		for (Adapter adapter : adapters) {
			String serviceKey = "adapter[" + adapter.getName() + "]";

			/// "ServiceType" complexType
			// enabled
			key = serviceKey + "/enabled";
			result.setProperty(key, adapter.isEnabled());

			// bindings
			result.putAll(getBindings(adapter));
			// NVPairs
			result.putAll(getNVPairs(adapter));

			// failureCount
			key = serviceKey + "/failureCount";
			result.setProperty(key, adapter.getFailureCount());

			// failureInterval
			key = serviceKey + "/failureInterval";
			result.setProperty(key, adapter.getFailureInterval());

			// monitor

			// plugins
			// not supported (too complex)
		}

		return result;
	}

	private <T extends ServiceType> String getElementKey(T service) {
		String elementKey;
		if (service.getClass().getCanonicalName().contains("Adapter")) {
			elementKey = "adapter";
		} else { // WARN: could be another value but only support for "bw" and "adapter"
			elementKey = "bw";
		}

		return elementKey;
	}

	/**
	 *

	 * This method focuses on bindings found in these paths :
	 * "/application/services/bw/bindings/binding"
	 * "/application/services/adapter/bindings/binding"
	 *

	 */
	protected <T extends ServiceType> Properties getBindings(T service) {
		SortedProperties result = new SortedProperties();

		String serviceKey = getElementKey(service) + "[" + service.getName() + "]";

		Bindings bindings = service.getBindings();
		if (bindings != null) {
			for (Binding binding : bindings.getBinding()) {
				String processKey = serviceKey + "/bindings/binding[" + binding.getName() + "]";
				String key;

				// machine
				key = processKey + "/machine";
				result.setProperty(key, binding.getMachine());

				// product
				if (binding.getProduct() != null) {
					key = processKey + "/product/type";
					result.setProperty(key, binding.getProduct().getType());
					key = processKey + "/product/version";
					result.setProperty(key, binding.getProduct().getVersion());
					key = processKey + "/product/location";
					result.setProperty(key, binding.getProduct().getLocation());
				}

				// container
				key = processKey + "/container";
				result.setProperty(key, binding.getContainer());

				// description
				key = processKey + "/description";
				result.setProperty(key, binding.getDescription());

				// contact
				key = processKey + "/contact";
				result.setProperty(key, binding.getContact());

				// setting
				Setting setting = binding.getSetting();
				if (setting != null) {
					key = processKey + "/setting/startOnBoot";
					result.setProperty(key,  setting.isStartOnBoot());
					key = processKey + "/setting/enableVerbose";
					result.setProperty(key, setting.isEnableVerbose());
					key = processKey + "/setting/maxLogFileSize";
					result.setProperty(key, setting.getMaxLogFileSize());
					key = processKey + "/setting/maxLogFileCount";
					result.setProperty(key, setting.getMaxLogFileCount());
					key = processKey + "/setting/threadCount";
					result.setProperty(key, setting.getThreadCount());
					NTService ntService = setting.getNTService();
					if (ntService != null) {
						key = processKey + "/setting/NTService/runAsNT";
						result.setProperty(key, ntService.isRunAsNT());
						key = processKey + "/setting/NTService/startupType";
						result.setProperty(key,  ntService.getStartupType());
						key = processKey + "/setting/NTService/loginAs";
						result.setProperty(key, ntService.getLoginAs());
						key = processKey + "/setting/NTService/password";
						result.setProperty(key, ntService.getPassword());
					}
					Java java = setting.getJava();
					if (java != null) {
						key = processKey + "/setting/java/prepandClassPath";
						result.setProperty(key, java.getPrepandClassPath());
						key = processKey + "/setting/java/appendClassPath";
						result.setProperty(key, java.getAppendClassPath());
						key = processKey + "/setting/java/initHeapSize";
						result.setProperty(key, java.getInitHeapSize());
						key = processKey + "/setting/java/maxHeapSize";
						result.setProperty(key, java.getMaxHeapSize());
						key = processKey + "/setting/java/threadStackSize";
						result.setProperty(key, java.getThreadStackSize());
					}
				}

				// ftWeight
				key = processKey + "/ftWeight";
				result.setProperty(key, binding.getFtWeight());

				// shutdown
				Shutdown shutdown = binding.getShutdown();
				if (shutdown != null) {
					key = processKey + "/shutdown/checkpoint";
					result.setProperty(key, shutdown.isCheckpoint());
					key = processKey + "/shutdown/timeout";
					result.setProperty(key, shutdown.getTimeout());
				}

				// plugins
				// not supported (too complex)

				// NVPairs
				if (binding.getNVPairs() != null) {
					for (JAXBElement<? extends NVPairType> nvPair : binding.getNVPairs().getNVPair()) {
						key = processKey + "/variables/variable[" + nvPair.getValue().getName() + "]";
						result.setProperty(key, nvPair.getValue().getValue());
					}
				}
			}
		}

		return result;
	}

	/**
	 *

	 * This method focuses on Global Variables found in this path :
	 * "/application/services/bw/NVPairs"
	 * "/application/services/adapter/NVPairs"
	 *

	 */
	private <T extends ServiceType> Properties getNVPairs(T service) {
		SortedProperties result = new SortedProperties();

		String serviceKey = getElementKey(service) + "[" + service.getName() + "]";

		List<NVPairs> nvPairsList = new ArrayList<NVPairs>();
		nvPairsList = service.getNVPairs();

		String variablesKey;

		for (NVPairs nvPairs : nvPairsList) {
			variablesKey = serviceKey + "/variables[" + nvPairs.getName() + "]";
			String key;
			for (JAXBElement<? extends NVPairType> nvPair : nvPairs.getNVPair()) {
				key = variablesKey + "/variable[" + nvPair.getValue().getName() + "]";
				result.setProperty(key, nvPair.getValue().getValue());
			}
		}

		return result;
	}

	/**
	 *

	 * This method focuses on processes found in this path :
	 * "/application/services/bw/bwprocesses/bwprocess"
	 *

	 */
	protected Properties getProcesses(Bw bwService) {
		SortedProperties result = new SortedProperties();

		String serviceKey = "bw[" + bwService.getName() + "]";

		Bwprocesses bwProcesses = getBWProcesses(bwService);
		if (bwProcesses != null) {
			for (Bwprocess process : bwProcesses.getBwprocess()) {
				String processKey = serviceKey + "/bwprocesses/bwprocess[" + process.getName() + "]";
				String key;

				// starter
				key = processKey + "/starter";
				result.setProperty(key, process.getStarter());

				// enabled
				key = processKey + "/enabled";
				result.setProperty(key, process.isEnabled());

				// maxJob
				key = processKey + "/maxJob";
				result.setProperty(key, process.getMaxJob());

				// activation
				key = processKey + "/activation";
				result.setProperty(key, process.isActivation());

				// flowLimit
				key = processKey + "/flowLimit";
				result.setProperty(key, process.getFlowLimit());
			}
		}

		return result;
	}

	/**
	 *

	 * This method focuses on checkpoints found in this path :
	 * "/application/services/bw/checkpoints/checkpoint"
	 *

	 */
	protected Properties getCheckpoints(Bw bwService) {
		SortedProperties result = new SortedProperties();

		String serviceKey = "bw[" + bwService.getName() + "]";

		Checkpoints checkpoints = getBWCheckpoints(bwService);
		if (checkpoints != null) {
			String key;

			// tablePrefix
			key = serviceKey + "/checkpoints/tablePrefix";
			result.setProperty(key, checkpoints.getTablePrefix());

			for (String checkpoint : checkpoints.getCheckpoint()) {
				if (checkpoint == null) continue;

				// checkpoint
				key = serviceKey + "/checkpoints/checkpoint["+checkpoint+"]";
				result.setProperty(key, checkpoint.equals(checkpoints.getSelected()));
			}
		}

		return result;
	}

	/**
	 *

	 * This method focuses on faultTolerant object found in this path :
	 * "/application/services/bw/faultTolerant"
	 *

	 */
	protected Properties getFaultTolerant(Bw bwService) {
		SortedProperties result = new SortedProperties();

		String serviceKey = "bw[" + bwService.getName() + "]";

		FaultTolerant faultTolerant = getBWFaultTolerant(bwService);
		if (faultTolerant != null) {
			String key;
			// hbInterval
			key = serviceKey + "/faultTolerant/hbInterval";
			result.setProperty(key, faultTolerant.getHbInterval());

			// activationInterval
			key = serviceKey + "/faultTolerant/activationInterval";
			result.setProperty(key, faultTolerant.getActivationInterval());

			// preparationDelay
			key = serviceKey + "/faultTolerant/preparationDelay";
			result.setProperty(key, faultTolerant.getPreparationDelay());
		}

		return result;
	}
	// end of unmarshalling part

	// marshalling part / Properties to XML (JAXB)
	/**
	 * /application/services/bw
	 */
	private Bw getBw(String name) {
		List<Bw> services = getBWServices();

		if (services != null) {
			for (Bw service : services) {
				if (service.getName().equals(name)) {
					return service;
				}
			}
		}

		Bw result = new Bw();
		result.setName(name);
		services.add(result);

		QName qName = new QName(APPLICATION_MANAGEMENT_NAMESPACE, "bw");
		JAXBElement<Bw> j = new JAXBElement<Bw>(qName, Bw.class, result);
		application.getServices().getBaseService().add(j);

		return result;
	}

	/**
	 * /application/services/adapter
	 */
	private Adapter getAdapter(String name) {
		List<Adapter> services = getAdapterServices();

		if (services != null) {
			for (Adapter service : services) {
				if (service.getName().equals(name)) {
					return service;
				}
			}
		}

		Adapter result = new Adapter();
		result.setName(name);
		services.add(result);

		QName qName = new QName(APPLICATION_MANAGEMENT_NAMESPACE, "adapter");
		JAXBElement<Adapter> j = new JAXBElement<Adapter>(qName, Adapter.class, result);
		application.getServices().getBaseService().add(j);

		return result;
	}

	/**
	 * /application/services/bw/bindings/binding
	 * /application/services/adapter/bindings/binding
	 */
	private <T extends ServiceType> Binding getBinding(String nameAttribute, T parent) {
		Bindings bindings = parent.getBindings();

		if (bindings != null) {
			for (Binding binding : bindings.getBinding()) {
				if (binding.getName().equals(nameAttribute)) {
					return binding;
				}
			}
		} else {
			bindings = new Bindings();
			parent.setBindings(bindings);
		}

		// create new Binding
		Binding binding = new Binding();
		binding.setName(nameAttribute);
		Product p = new Product();
		p.setType("bwengine");
		p.setLocation("");
		p.setVersion("");
		binding.setProduct(p);
		binding.setDescription("");
		binding.setContact("");
		Shutdown s = new Shutdown();
		s.setCheckpoint(false);
		s.setTimeout(new BigInteger("0"));
		binding.setShutdown(s);

		bindings.getBinding().add(binding);

		return binding;
	}

	/**
	 * /application/services/bw/bindings/binding/*
	 */
	private Object addBindingParameter(Binding binding, String key, String value) {
		if ("machine".equals(key)) {
			binding.setMachine(value);
		} else if ("product".equals(key)) {
			if (binding.getProduct() == null) {
				binding.setProduct(new Product());
			}
			return binding.getProduct();
		} else if ("container".equals(key)) {
			binding.setContainer(value);
		} else if ("description".equals(key)) {
			binding.setDescription(value);
		} else if ("contact".equals(key)) {
			binding.setContact(value);
		} else if ("setting".equals(key)) {
			if (binding.getSetting() == null) {
				binding.setSetting(new Setting());
			}
			return binding.getSetting();
		} else if ("ftWeight".equals(key)) {
			binding.setFtWeight(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("shutdown".equals(key)) {
			if (binding.getShutdown() == null) {
				binding.setShutdown(new Shutdown());
			}
			return binding.getShutdown();
		}

		return binding;
	}

	/**
	 * /application/services/bw/bindings/binding/product/*
	 */
	private Object addProductParameter(Product product, String key, String value) {
		if ("type".equals(key)) {
			product.setType(value);
		} else if ("version".equals(key)) {
			product.setVersion(value);
		} else if ("location".equals(key)) {
			product.setLocation(value);
		}
		return product;
	}

	/**
	 * /application/services/bw/bindings/binding/setting/*
	 */
	private Object addSettingParameter(Setting setting, String key, String value) {
		if ("startOnBoot".equals(key)) {
			setting.setStartOnBoot(Boolean.parseBoolean(value));
		} else if ("enableVerbose".equals(key)) {
			setting.setEnableVerbose(Boolean.parseBoolean(value));
		} else if ("maxLogFileSize".equals(key)) {
			setting.setMaxLogFileSize(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("maxLogFileCount".equals(key)) {
			setting.setMaxLogFileCount(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("threadCount".equals(key)) {
			setting.setThreadCount(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("NTService".equals(key)) {
			if (setting.getNTService() == null) {
				setting.setNTService(new NTService());
			}
			return setting.getNTService();
		} else if ("java".equals(key)) {
			if (setting.getJava() == null) {
				setting.setJava(new Java());
			}
			return setting.getJava();
		}
		return setting;
	}

	/**
	 * /application/services/bw/bindings/binding/setting/NTService/*
	 */
	private Object addNTServiceParameter(NTService ntService, String key, String value) {
		if ("runAsNT".equals(key)) {
			ntService.setRunAsNT(Boolean.parseBoolean(value));
		} else if ("startupType".equals(key)) {
			ntService.setStartupType(value);
		} else if ("loginAs".equals(key)) {
			ntService.setLoginAs(value);
		} else if ("password".equals(key)) {
			ntService.setPassword(value);
		}
		return ntService;
	}

	/**
	 * /application/services/bw/bindings/binding/setting/java/*
	 */
	private Object addJavaParameter(Java java, String key, String value) {
		if ("prepandClassPath".equals(key)) {
			java.setPrepandClassPath(value);
		} else if ("appendClassPath".equals(key)) {
			java.setAppendClassPath(value);
		} else if ("initHeapSize".equals(key)) {
			java.setInitHeapSize(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("maxHeapSize".equals(key)) {
			java.setMaxHeapSize(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("threadStackSize".equals(key)) {
			java.setThreadStackSize(BigInteger.valueOf(Long.parseLong(value)));
		}

		return java;
	}

	/**
	 * /application/services/bw/bindings/binding/shutdown/*
	 */
	private Object addShutdownParameter(Shutdown shutdown, String key, String value) {
		if ("checkpoint".equals(key)) {
			shutdown.setCheckpoint(Boolean.parseBoolean(value));
		} else if ("timeout".equals(key)) {
			shutdown.setTimeout(BigInteger.valueOf(Long.parseLong(value)));
		}

		return shutdown;
	}

	/**
	 * /application/services/bw/bwprocesses/bwprocess
	 */
	private Bwprocess getBWProcess(String nameAttribute, Bw parent) {
		Bwprocesses bwProcesses = getBWProcesses(parent);

		if (bwProcesses != null) {
			for (Bwprocess bwProcess : bwProcesses.getBwprocess()) {
				if (bwProcess.getName().equals(nameAttribute)) {
					return bwProcess;
				}
			}
		} else {
			bwProcesses = new Bwprocesses();
			parent.getRest().add(bwProcesses);
		}

		Bwprocess bwProcess = new Bwprocess();
		bwProcess.setName(nameAttribute);
		bwProcesses.getBwprocess().add(bwProcess);

		return bwProcess;
	}

	/**
	 * /application/services/bw/bwprocesses/bwprocess/*
	 */
	private void addBWProcessParameter(Bwprocess bwProcess, String key, String value) {
		if ("starter".equals(key)) {
			bwProcess.setStarter(value);
		} else if ("enabled".equals(key)) {
			bwProcess.setEnabled(Boolean.parseBoolean(value));
		} else if ("maxJob".equals(key)) {
			bwProcess.setMaxJob(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("activation".equals(key)) {
			bwProcess.setActivation(Boolean.parseBoolean(value));
		} else if ("flowLimit".equals(key)) {
			bwProcess.setFlowLimit(BigInteger.valueOf(Long.parseLong(value)));
		}
	}

	/**
	 * /application/services/bw/faultTolerant/*
	 */
	private void addFaultTolerantParameter(FaultTolerant faultTolerant, String key, String value) {
		if ("activationInterval".equals(key)) {
			faultTolerant.setActivationInterval(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("hbInterval".equals(key)) {
			faultTolerant.setHbInterval(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("preparationDelay".equals(key)) {
			faultTolerant.setPreparationDelay(BigInteger.valueOf(Long.parseLong(value)));
		}
	}

	/**
	 * /application/services/bw/checkpoints/*
	 */
	private void addCheckpointsParameter(Checkpoints parent, String key, String value) {
		// TODO Auto-generated method stub

	}

	/**
	 * /application/services/bw/*
	 */
	private Object addBwParameter(Bw bw, String key, String value) {
		if ("enabled".equals(key)) {
			bw.setEnabled(Boolean.parseBoolean(value));
		} else if ("failureCount".equals(key)) {
			bw.setFailureCount(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("failureInterval".equals(key)) {
			bw.setFailureInterval(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("isFt".equals(key)) {
			setIsFt(bw, Boolean.parseBoolean(value));
		} else if ("faultTolerant".equals(key)) {
			return getBWFaultTolerant(bw);
		}
		return bw;
	}

	/**
	 * /application/services/adapter/*
	 */
	private Object addAdapterParameter(Adapter adapter, String key, String value) {
		if ("enabled".equals(key)) {
			adapter.setEnabled(Boolean.parseBoolean(value));
		} else if ("failureCount".equals(key)) {
			adapter.setFailureCount(BigInteger.valueOf(Long.parseLong(value)));
		} else if ("failureInterval".equals(key)) {
			adapter.setFailureInterval(BigInteger.valueOf(Long.parseLong(value)));
		}
		return adapter;
	}

	/**
	 *

	 * This method will create JAXB objects from Properties through recursive
	 * calls.
	 * Each property has a path. The last part of a path (after last /) is the
	 * element.
	 *

	 */
	public Object getElement(String path, String element, String value, Object parent) {
		if (map.containsKey(path)) {
			return map.get(path);
		} else {
			Matcher matcherElement = patternElement.matcher(element);
			if (matcherElement.matches()) {
				String elementName = matcherElement.group(1);
				String nameAttribute = matcherElement.group(3);

				if (nameAttribute != null) {

					if (elementName.equals("variables")) {
						NVPairs gvs = null;
						if (parent.getClass().equals(Bw.class) || parent.getClass().equals(Adapter.class)) {
							ServiceType service = (ServiceType) parent;
							for (NVPairs nvPairs : service.getNVPairs()) {
								if (nvPairs.getName().equals(nameAttribute)) {
									gvs = nvPairs;
									break;
								}
							}
							if (gvs == null) {
								gvs = new NVPairs();
								service.getNVPairs().add(gvs);
							}
						} else if (parent.getClass().equals(Binding.class)) {
							gvs = new NVPairs();
							gvs.setName(nameAttribute);
							((Binding) parent).setNVPairs(gvs);
						}
						map.put(path, gvs);
						return gvs;
					} else if (elementName.equals("variable")) {
						NameValuePair simpleGV = new NameValuePair();
						simpleGV.setName(nameAttribute);
						simpleGV.setValue(value);

						QName name = new QName(APPLICATION_MANAGEMENT_NAMESPACE, "NameValuePair");
						JAXBElement<NameValuePair> _simpleGV = new JAXBElement<NameValuePair>(name, NameValuePair.class, simpleGV);
						boolean found = false;
						for (JAXBElement<? extends NVPairType> nvPair : ((NVPairs) parent).getNVPair()) {
							if (nameAttribute.equals(nvPair.getValue().getName())) {
								nvPair.getValue().setValue(value);
								found = true;
							}
						}
						if (!found) {
							((NVPairs) parent).getNVPair().add(_simpleGV);
						}

						return simpleGV;
					} else if (elementName.equals("bw")) {
						Bw service = this.getBw(nameAttribute);
						map.put(path, service);
						return service;
					} else if (elementName.equals("adapter")) {
						Adapter service = this.getAdapter(nameAttribute);
						map.put(path, service);
						return service;
					} else if (elementName.equals("binding")) {
						Binding binding = null;
						if (parent.getClass().equals(Bw.class)) {
							binding = this.getBinding(nameAttribute, (Bw) parent);
						} else if (parent.getClass().equals(Adapter.class)) {
							binding = this.getBinding(nameAttribute, (Adapter) parent);
						} else {
							// throw ?
						}
						map.put(path, binding);
						return binding;
					} else if (elementName.equals("bwprocess")) {
						Bwprocess bwProcess = this.getBWProcess(nameAttribute, (Bw) parent);
						map.put(path, bwProcess);
						return bwProcess;
					} else if (elementName.equals("checkpoint")) {
						Checkpoints checkpoints = (Checkpoints) parent;
						if (!checkpoints.getCheckpoint().contains(nameAttribute)) {
							checkpoints.getCheckpoint().add(nameAttribute);
						}
						if ("true".equals(value)) {
							checkpoints.setSelected(nameAttribute);
						}
					}
				} else {
					if (elementName.equals("variables")) {
						NVPairs gvs = null;
						if (parent.getClass().equals(Bw.class) || parent.getClass().equals(Adapter.class)) {
							ServiceType service = (ServiceType) parent;
							for (NVPairs nvPairs : service.getNVPairs()) {
								if (nvPairs.getName().equals("Runtime Variables")) {
									gvs = nvPairs;
									break;
								}
							}
							if (gvs == null) {
								gvs = new NVPairs();
								service.getNVPairs().add(gvs);
							}
						} else if (parent.getClass().equals(Binding.class)) {
							gvs = new NVPairs();
							gvs.setName("Runtime Variables");
							((Binding) parent).setNVPairs(gvs);
						}
						map.put(path, gvs);
						return gvs;
					} else if (elementName.equals("checkpoints")) {
						Checkpoints checkpoints = this.getBWCheckpoints((Bw) parent);
						map.put(path, checkpoints);
						return checkpoints;
					} else if (elementName.equals("tablePrefix")) {
						Checkpoints checkpoints = (Checkpoints) parent;
						checkpoints.setTablePrefix(value);
					// Binding children
					} else if (parent.getClass().equals(Binding.class)) {
						return addBindingParameter((Binding) parent, elementName, value);
					} else if (parent.getClass().equals(Product.class)) {
						return addProductParameter((Product) parent, elementName, value);
					} else if (parent.getClass().equals(Setting.class)) {
						return addSettingParameter((Setting) parent, elementName, value);
					} else if (parent.getClass().equals(NTService.class)) {
						return addNTServiceParameter((NTService) parent, elementName, value);
					} else if (parent.getClass().equals(Java.class)) {
						return addJavaParameter((Java) parent, elementName, value);
					} else if (parent.getClass().equals(Shutdown.class)) {
						return addShutdownParameter((Shutdown) parent, elementName, value);
					//
					// Bwprocess children
					} else if (parent.getClass().equals(Bwprocess.class)) {
						addBWProcessParameter((Bwprocess) parent, elementName, value);
					} else if (parent.getClass().equals(FaultTolerant.class)) {
						addFaultTolerantParameter((FaultTolerant) parent, elementName, value);
					} else if (parent.getClass().equals(Checkpoints.class)) {
						addCheckpointsParameter((Checkpoints) parent, elementName, value);
					// Bw chidren (direct children)
					} else if (parent.getClass().equals(Bw.class)) {
						return addBwParameter((Bw) parent, elementName, value);
					} else if (parent.getClass().equals(Adapter.class)) {
						return addAdapterParameter((Adapter) parent, elementName, value);
					}
				}

			}
			return parent;
		}
	}

	/**
	 *

	 * This will remove from the XML the second duplicate default binding (with
	 * empty name attribute) to keep only the first one.
	 * This is is because "AppManage -export -max" exports two empty bindings
	 * to prepare fault tolerance configuration.
	 *

	 */
	public void removeDuplicateBinding() {
		List<Bw> bwServices = this.getBWServices();

		for (Bw bw : bwServices) {
			boolean first = true;

			List<Binding> bindings = bw.getBindings().getBinding();
			for (Iterator<Binding> iterator = bindings.iterator(); iterator.hasNext();) {
				Binding binding = (Binding) iterator.next();

				if (!first && binding.getName().equals("")) {
					iterator.remove();
				}
				first = false;
			}
		}

		List<Adapter> adapterServices = this.getAdapterServices();

		for (Adapter adapter : adapterServices) {
			boolean first = true;

			List<Binding> bindings = adapter.getBindings().getBinding();
			for (Iterator<Binding> iterator = bindings.iterator(); iterator.hasNext();) {
				Binding binding = (Binding) iterator.next();

				if (!first && binding.getName().equals("")) {
					iterator.remove();
				}
				first = false;
			}
		}
	}

	/**
	 *

	 * This will remove from the XML the default binding (with empty name
	 * attribute) if it is not found in the properties.
	 *

	 */
	public void removeDefaultBindingIfNotExists(Properties properties) {
		List<Bw> bwServices = this.getBWServices();

		for (Bw bw : bwServices) {
			String path = "bw[" + bw.getName() + "]/bindings/binding[]/machine";

			List<Binding> bindings = bw.getBindings().getBinding();
			for (Iterator<Binding> iterator = bindings.iterator(); iterator.hasNext();) {
				Binding binding = (Binding) iterator.next();
//				if (binding.getName().equals("") && properties.getString(path) == null) {
				if (binding.getName().equals("") && !properties.containsKey(path)) {
					iterator.remove();
				}
			}
		}

		List<Adapter> adapterServices = this.getAdapterServices();

		for (Adapter adapter : adapterServices) {
			String path = "adapter[" + adapter.getName() + "]/bindings/binding[]/machine";

			List<Binding> bindings = adapter.getBindings().getBinding();
			for (Iterator<Binding> iterator = bindings.iterator(); iterator.hasNext();) {
				Binding binding = (Binding) iterator.next();
//				if (binding.getName().equals("") && properties.getString(path) == null) {
				if (binding.getName().equals("") && !properties.containsKey(path)) {
					iterator.remove();
				}
			}
		}
	}
	// end of marshalling part

	public String getName() {
		if (this.application == null) {
			return null;
		}
		return this.application.getName();
	}

	public String getDescription() {
		if (this.application == null) {
			return null;
		}
		return this.application.getDescription();
	}

	public String getContact() {
		if (this.application == null) {
			return null;
		}
		return this.application.getContact();
	}

	public String getMaxDeploymentRevision() {
		if (this.application == null) {
			return null;
		}
		return this.application.getMaxdeploymentrevision();
	}

	public void setName(String name) {
		if (this.application == null) {
			return;
		}
		this.application.setName(name);
	}

	public void setContact(String contact) {
		if (this.application == null) {
			return;
		}
		this.application.setContact(contact);
	}

	public void setDescription(String description) {
		if (this.application == null) {
			return;
		}
		this.application.setDescription(description);
	}

	public void setMaxDeploymentRevision(String maxDeploymentRevision) {
		if (this.application == null) {
			return;
		}
		this.application.setMaxdeploymentrevision(maxDeploymentRevision);
	}

	public RepoInstances getRepoInstances() {
		return this.application.getRepoInstances();
	}

	public Monitor getMonitor(String service) {
		Monitor result = null;
		Bw bw = this.getBw(service);
		if (bw != null) {
			result = bw.getMonitor();
		}
		return result;
	}

	public static <E extends fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.AbstractEvent> void addEvent(Events events, E event) {
		if (events == null || event == null) return;

		String eventType = event.getClass().getName();
		EventType e;
		if (fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.FailureEvent.class.getName().equals(eventType)) {
			e = new FailureEvent();
			((FailureEvent) e).setFailure(((fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.FailureEvent) event).getFailure());
		} else if (fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.LogEvent.class.getName().equals(eventType)) {
			e = new LogEvent();
			((LogEvent) e).setMatch(((fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.LogEvent) event).getMatch());
		} else {
			throw new UnsupportedOperationException();
		}
		fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.Actions _actions = event.getActions();

		Actions actions = new Actions();
		for (fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.AlertAction alert : _actions.getAlerts()) {
			AlertAction action = new AlertAction();
			action.setEnabled(alert.getEnabled());
			action.setPerformPolicy(alert.getPerformPolicy());
			action.setLevel(alert.getLevel());
			action.setMessage(alert.getMessage());
			addAction(actions, action);
		}
		for (fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.CustomAction custom : _actions.getCustoms()) {
			CustomAction action = new CustomAction();
			action.setEnabled(custom.getEnabled());
			action.setPerformPolicy(custom.getPerformPolicy());
			action.setArguments(custom.getArguments());
			action.setCommand(custom.getCommand());
			addAction(actions, action);
		}
		for (fr.fastconnect.factory.tibco.bw.maven.packaging.monitoring.EmailAction email : _actions.getEmails()) {
			EmailAction action = new EmailAction();
			action.setEnabled(email.getEnabled());
			action.setPerformPolicy(email.getPerformPolicy());
			action.setCc(email.getCc());
			action.setMessage(email.getMessage());
			action.setSMTPServer(email.getSmtpServer());
			action.setSubject(email.getSubject());
			action.setTo(email.getTo());
			addAction(actions, action);
		}

		e.setActions(actions);
		e.setDescription(event.getDescription());
		e.setRestart(event.getRestart());

		addEvent(events, e);
	}

	protected static <E extends EventType> void addEvent(Events events, E event) {
		if (events == null || event == null) return;

		@SuppressWarnings("unchecked")
		Class<E> c = (Class<E>) event.getClass();
		JAXBElement<E> e = new JAXBElement<E>(new QName("name"), c, event);
		events.getEvent().add(e);
	}

	public static  void addAction(Actions actions, A action) {
		if (actions == null || action == null) return;

		@SuppressWarnings("unchecked")
		Class c = (Class) action.getClass();
		JAXBElement a = new JAXBElement(new QName("name"), c, action);
		actions.getAction().add(a);
	}

	/**
	 * Add <events> in <monitor> element of all <bw> elements.
	 * @param events
	 */
	public void addMonitoringEventsToAllServices(Events events) {
		List<JAXBElement<? extends EventType>> events_ = events.getEvent();
		if (events_ != null && !events_.isEmpty()) {
			for (Bw service : this.getBWServices()) {
				Monitor monitor = service.getMonitor();
				if (monitor != null) {
					monitor.setEvents(events);
				}
			}
		}
	}

}


/**
 * (C) Copyright 2011-2015 FastConnect SAS
 * (http://www.fastconnect.fr/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
//
// Ce fichier a été généré par l'implémentation de référence JavaTM Architecture for XML Binding (JAXB), v2.2.7
// Voir http://java.sun.com/xml/jaxb
// Toute modification apportée à ce fichier sera perdue lors de la recompilation du schéma source.
// Généré le : 2014.09.10 à 11:00:34 AM CEST
//

package fr.fastconnect.factory.tibco.bw.maven.compile.repository;

import java.util.ArrayList;
import java.util.List;
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.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

/**
 *
Classe Java pour anonymous complex type.
 *
 *
Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe.
 *
 *

 * <complexType>
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="globalVariable" maxOccurs="unbounded" minOccurs="0">
 *           <complexType>
 *             <complexContent>
 *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *                 <all>
 *                   <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *                   <element name="value" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *                   <element name="description" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *                   <element name="deploymentSettable" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
 *                   <element name="serviceSettable" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
 *                   <element name="type" minOccurs="0">
 *                     <simpleType>
 *                       <restriction base="{http://www.w3.org/2001/XMLSchema}token">
 *                         <enumeration value="String"/>
 *                         <enumeration value="Integer"/>
 *                         <enumeration value="Boolean"/>
 *                         <enumeration value="Password"/>
 *                       </restriction>
 *                     </simpleType>
 *                   </element>
 *                   <element name="constraint" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *                   <element name="modTime" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
 *                 </all>
 *               </restriction>
 *             </complexContent>
 *           </complexType>
 *         </element>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "globalVariable"
})
@XmlRootElement(name = "globalVariables")
public class GlobalVariables {

    protected List<GlobalVariables.GlobalVariable> globalVariable;

    /**
     * Gets the value of the globalVariable property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the globalVariable property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getGlobalVariable().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link GlobalVariables.GlobalVariable }
     *
     *
     */
    public List<GlobalVariables.GlobalVariable> getGlobalVariable() {
        if (globalVariable == null) {
            globalVariable = new ArrayList<GlobalVariables.GlobalVariable>();
        }
        return this.globalVariable;
    }

    /**
     *
Classe Java pour anonymous complex type.
     *
     *
Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe.
     *
     *

     * <complexType>
     *   <complexContent>
     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *       <all>
     *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="value" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="description" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
     *         <element name="deploymentSettable" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
     *         <element name="serviceSettable" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
     *         <element name="type" minOccurs="0">
     *           <simpleType>
     *             <restriction base="{http://www.w3.org/2001/XMLSchema}token">
     *               <enumeration value="String"/>
     *               <enumeration value="Integer"/>
     *               <enumeration value="Boolean"/>
     *               <enumeration value="Password"/>
     *             </restriction>
     *           </simpleType>
     *         </element>
     *         <element name="constraint" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
     *         <element name="modTime" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
     *       </all>
     *     </restriction>
     *   </complexContent>
     * </complexType>
     *

     *
     *
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {

    })
    public static class GlobalVariable {

        @XmlElement(required = true)
        protected String name;
        @XmlElement(required = true)
        protected String value;
        protected String description;
        protected Boolean deploymentSettable;
        protected Boolean serviceSettable;
        @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
        protected String type;
        protected String constraint;
        protected Long modTime;

        /**
         * Obtient la valeur de la propriété name.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getName() {
            return name;
        }

        /**
         * Définit la valeur de la propriété name.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setName(String value) {
            this.name = value;
        }

        /**
         * Obtient la valeur de la propriété value.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getValue() {
            return value;
        }

        /**
         * Définit la valeur de la propriété value.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setValue(String value) {
            this.value = value;
        }

        /**
         * Obtient la valeur de la propriété description.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getDescription() {
            return description;
        }

        /**
         * Définit la valeur de la propriété description.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setDescription(String value) {
            this.description = value;
        }

        /**
         * Obtient la valeur de la propriété deploymentSettable.
         *
         * @return
         *     possible object is
         *     {@link Boolean }
         *
         */
        public Boolean isDeploymentSettable() {
            return deploymentSettable;
        }

        /**
         * Définit la valeur de la propriété deploymentSettable.
         *
         * @param value
         *     allowed object is
         *     {@link Boolean }
         *
         */
        public void setDeploymentSettable(Boolean value) {
            this.deploymentSettable = value;
        }

        /**
         * Obtient la valeur de la propriété serviceSettable.
         *
         * @return
         *     possible object is
         *     {@link Boolean }
         *
         */
        public Boolean isServiceSettable() {
            return serviceSettable;
        }

        /**
         * Définit la valeur de la propriété serviceSettable.
         *
         * @param value
         *     allowed object is
         *     {@link Boolean }
         *
         */
        public void setServiceSettable(Boolean value) {
            this.serviceSettable = value;
        }

        /**
         * Obtient la valeur de la propriété type.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getType() {
            return type;
        }

        /**
         * Définit la valeur de la propriété type.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setType(String value) {
            this.type = value;
        }

        /**
         * Obtient la valeur de la propriété constraint.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getConstraint() {
            return constraint;
        }

        /**
         * Définit la valeur de la propriété constraint.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setConstraint(String value) {
            this.constraint = value;
        }

        /**
         * Obtient la valeur de la propriété modTime.
         *
         * @return
         *     possible object is
         *     {@link Long }
         *
         */
        public Long getModTime() {
            return modTime;
        }

        /**
         * Définit la valeur de la propriété modTime.
         *
         * @param value
         *     allowed object is
         *     {@link Long }
         *
         */
        public void setModTime(Long value) {
            this.modTime = value;
        }

    }

}


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2014.01.23 at 10:11:20 AM CET
//

package com.tibco.xmlns.applicationmanagement;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
Java class for anonymous complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType>
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element ref="{http://www.tibco.com/xmlns/ApplicationManagement}baseService" maxOccurs="unbounded" minOccurs="0"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "baseService"
})
@XmlRootElement(name = "services")
public class Services {

    @XmlElementRef(name = "baseService", namespace = "http://www.tibco.com/xmlns/ApplicationManagement", type = JAXBElement.class)
    protected List<JAXBElement<? extends ServiceType>> baseService;

    /**
     * Gets the value of the baseService property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the baseService property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getBaseService().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link JAXBElement }{@code <}{@link Bw }{@code >}
     * {@link JAXBElement }{@code <}{@link Service }{@code >}
     * {@link JAXBElement }{@code <}{@link ServiceType }{@code >}
     * {@link JAXBElement }{@code <}{@link Im }{@code >}
     * {@link JAXBElement }{@code <}{@link FormFlow }{@code >}
     * {@link JAXBElement }{@code <}{@link Adapter }{@code >}
     *
     *
     */
    public List<JAXBElement<? extends ServiceType>> getBaseService() {
        if (baseService == null) {
            baseService = new ArrayList<JAXBElement<? extends ServiceType>>();
        }
        return this.baseService;
    }

}


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2014.01.23 at 10:11:20 AM CET
//

package com.tibco.xmlns.applicationmanagement;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
Java class for anonymous complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType>
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element ref="{http://www.tibco.com/xmlns/ApplicationManagement}event" maxOccurs="unbounded" minOccurs="0"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "event"
})
@XmlRootElement(name = "events")
public class Events {

    @XmlElementRef(name = "event", namespace = "http://www.tibco.com/xmlns/ApplicationManagement", type = JAXBElement.class)
    protected List<JAXBElement<? extends EventType>> event;

    /**
     * Gets the value of the event property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the event property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getEvent().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link JAXBElement }{@code <}{@link EventType }{@code >}
     * {@link JAXBElement }{@code <}{@link LogEvent }{@code >}
     * {@link JAXBElement }{@code <}{@link SuspendProcessEvent }{@code >}
     * {@link JAXBElement }{@code <}{@link FailureEvent }{@code >}
     *
     *
     */
    public List<JAXBElement<? extends EventType>> getEvent() {
        if (event == null) {
            event = new ArrayList<JAXBElement<? extends EventType>>();
        }
        return this.event;
    }

}