//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.5-b02-fcs 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2011.04.21 at 02:35:28 PM CDT 
//

package org.eclipse.ptp.rm.jaxb.core.data;

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.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 * 
 * The top-level tokenizer element: refers to an object, either to be
 * constructed at match time, or which pre-exists in the environment, on which
 * to apply the actions associated with matches and tests, along with a set of
 * possible matches and tests. All tests are run at the conclusion of the parse
 * operation. NOTE: when new targets are constructed, there is a merge operation
 * at the end of tokenization which attempts to combine objects into a single
 * instance identified by the 'name' attribute. This assumes that such names
 * will be unique and that any other values to be set on the object which are
 * not explicitly bound in some way to that name through the pattern will appear
 * on the stream before a new name does.
 * 
 * 
 * <p>
 * Java class for target-type complex type.
 * 
 * <p>
 * The following schema fragment specifies the expected content contained within
 * this class.
 * 
 * <pre>
 * &lt;complexType name="target-type">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="match" type="{http://org.eclipse.ptp/rm}match-type" maxOccurs="unbounded"/>
 *         &lt;element name="test" type="{http://org.eclipse.ptp/rm}test-type" maxOccurs="unbounded" minOccurs="0"/>
 *       &lt;/sequence>
 *       &lt;attribute name="matchAll" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
 *       &lt;attribute name="ref" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       &lt;attribute name="type" default="property">
 *         &lt;simpleType>
 *           &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
 *             &lt;enumeration value="property"/>
 *             &lt;enumeration value="attribute"/>
 *           &lt;/restriction>
 *         &lt;/simpleType>
 *       &lt;/attribute>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "target-type", propOrder = { "match", "test" })
public class TargetType {

	@XmlElement(required = true)
	protected List<MatchType> match;
	protected List<TestType> test;
	@XmlAttribute
	protected Boolean matchAll;
	@XmlAttribute
	protected String ref;
	@XmlAttribute
	protected String type;

	/**
	 * Gets the value of the match property.
	 * 
	 * <p>
	 * 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
	 * <CODE>set</CODE> method for the match property.
	 * 
	 * <p>
	 * For example, to add a new item, do as follows:
	 * 
	 * <pre>
	 * getMatch().add(newItem);
	 * </pre>
	 * 
	 * 
	 * <p>
	 * Objects of the following type(s) are allowed in the list
	 * {@link MatchType }
	 * 
	 * 
	 */
	public List<MatchType> getMatch() {
		if (match == null) {
			match = new ArrayList<MatchType>();
		}
		return this.match;
	}

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

	/**
	 * Gets the value of the test property.
	 * 
	 * <p>
	 * 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
	 * <CODE>set</CODE> method for the test property.
	 * 
	 * <p>
	 * For example, to add a new item, do as follows:
	 * 
	 * <pre>
	 * getTest().add(newItem);
	 * </pre>
	 * 
	 * 
	 * <p>
	 * Objects of the following type(s) are allowed in the list {@link TestType }
	 * 
	 * 
	 */
	public List<TestType> getTest() {
		if (test == null) {
			test = new ArrayList<TestType>();
		}
		return this.test;
	}

	/**
	 * Gets the value of the type property.
	 * 
	 * @return possible object is {@link String }
	 * 
	 */
	public String getType() {
		if (type == null) {
			return "property"; //$NON-NLS-1$
		} else {
			return type;
		}
	}

	/**
	 * Gets the value of the matchAll property.
	 * 
	 * @return possible object is {@link Boolean }
	 * 
	 */
	public boolean isMatchAll() {
		if (matchAll == null) {
			return false;
		} else {
			return matchAll;
		}
	}

	/**
	 * Sets the value of the matchAll property.
	 * 
	 * @param value
	 *            allowed object is {@link Boolean }
	 * 
	 */
	public void setMatchAll(Boolean value) {
		this.matchAll = value;
	}

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

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

}
