/***********************************************************
Copyright (C) 2018 VeriSign, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ***********************************************************/
package com.verisign.epp.codec.loginsecpolicy.v02;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.verisign.epp.codec.gen.EPPCodecComponent;
import com.verisign.epp.codec.gen.EPPCodecException;
import com.verisign.epp.codec.gen.EPPDecodeException;
import com.verisign.epp.codec.gen.EPPEncodeException;
import com.verisign.epp.codec.gen.EPPUtil;
import com.verisign.epp.util.EPPCatFactory;
import com.verisign.epp.util.EqualityUtil;

/**
 * This class is encoded into the &lt;loginSecPolicy:event&gt; element that
 * represents the policies of an individual login security event (warning or
 * error). The &lt;loginSecPolicy:event&gt; element contains the following child
 * elements:<br>
 * <ul>
 * <li>&lt;loginSecPolicy:level&gt; - One or two &lt;loginSecPolicy:level&gt;
 * elements that indicate the possible set of event levels ("warning" or
 * "error") the server will return to the client for the event type.</li>
 * <li>&lt;loginSecPolicy:exDate&gt; - OPTIONAL boolean element that indicates
 * whether the event type includes a &lt;loginSec:exDate&gt; element with the
 * default value of "0" (or "false").</li>
 * <li>&lt;loginSecPolicy:exPeriod&gt; - OPTIONAL duration element that the
 * event type must be reset. For example, the password will expire 30 days after
 * being set.</li>
 * <li>&lt;loginSecPolicy:warningPeriod&gt; - OPTIONAL duration element that
 * indicates how long prior to expiry the server will include a warning event.
 * For example, the server will include a password expiry warning event 15 days
 * prior to expiry.</li>
 * <li>&lt;loginSecPolicy:exError&gt; - OPTIONAL indication of what will error
 * will occur at expiry.</li>
 * <li>&lt;loginSecPolicy:threshold&gt; - OPTIONAL threshold value that triggers
 * a warning event for a specific "stat" event. For example, a "failedLogins"
 * "stat" warning event will occur if the number of failed logins exceeds 100.
 * </li>
 * <li>&lt;loginSecPolicy:period&gt; - OPTIONAL period value that is associated
 * with a warning event for a specific "stat" event.</li>
 * </ul>
 */
public class EPPLoginSecPolicyEvent implements EPPCodecComponent {

	/**
	 * Possible list of security event types.
	 */
	public static enum EventType implements java.io.Serializable,Cloneable {
		/**
		 * Password expiry event type.
		 */
		password,

		/**
		 * Client certificate expiry event type.
		 */
		certificate,
		/**
		 * Insecure or deprecated TLS cipher suite event type.
		 */
		cipher,
		/**
		 * Insecure or deprecated TLS protocol event type.
		 */
		tlsProtocol,
		/**
		 * New password does not meet server password complexity requirements
		 * event type.
		 */
		newPw,
		/**
		 * Login security statistical warning event type.
		 */
		stat,
		/**
		 * Custom event type.
		 */
		custom
	}

	/**
	 * Possible list of security event levels.
	 */
	public static enum EventLevel implements java.io.Serializable,Cloneable {
		/**
		 * A warning event that needs action.
		 */
		warning,
		/**
		 * An error event that requires immediate action.
		 */
		error
	}

	/**
	 * Possible list of event error action types.
	 */
	public static enum EventErrorAction implements java.io.Serializable,Cloneable {
		/**
		 * The client connection will fail. For example, when the client
		 * certificate expires, the TLS handshake will fail.
		 */
		connect,
		/**
		 * The client login will fail. For example, when the new password does not
		 * meet the server password complexity requirements or when the password
		 * expires, the login will fail.
		 */
		login,
		/**
		 * There is no predefined failure action. For example, when the password
		 * expires, the server will not fail the login.
		 */
		none
	}

	/**
	 * Log4j category for logging
	 */
	private static Logger cat = Logger.getLogger(EPPLoginSecPolicyEvent.class.getName(),
	      EPPCatFactory.getInstance().getFactory());

	/**
	 * XML local name for {@code EPPLoginSecPolicyEvent}.
	 */
	public static final String ELM_LOCALNAME = "event";

	/**
	 * XML root tag for {@code EPPLoginSecPolicyEvent}.
	 */
	public static final String ELM_NAME = EPPLoginSecPolicyExtFactory.NS_PREFIX + ":" + ELM_LOCALNAME;

	/**
	 * XML Element Name of {@code level} list attribute.
	 */
	private final static String ELM_LEVEL = "level";

	/**
	 * XML Element Name of {@code exDate} attribute.
	 */
	private final static String ELM_EX_DATE = "exDate";

	/**
	 * XML Element Name of {@code exPeriod} attribute.
	 */
	private final static String ELM_EX_PERIOD = "exPeriod";

	/**
	 * XML Element Name of {@code warningPeriod} attribute.
	 */
	private final static String ELM_WARNING_PERIOD = "warningPeriod";

	/**
	 * XML Element Name of {@code errorAction} attribute.
	 */
	private final static String ELM_ERROR_ACTION = "errorAction";

	/**
	 * XML Element Name of {@code threshold} attribute.
	 */
	private final static String ELM_THRESHOLD = "threshold";

	/**
	 * XML Element Name of {@code period} attribute.
	 */
	private final static String ELM_PERIOD = "period";

	/**
	 * XML Element Name of {@code type} attribute.
	 */
	private static final String ATTR_TYPE = "type";

	/**
	 * XML Element Name of {@code name} attribute.
	 */
	private static final String ATTR_NAME = "name";

	/**
	 * Event type
	 */
	private EventType type;

	/**
	 * OPTIONAL "name" attribute that can define a custom event type or define
	 * the specific statistic event.
	 */
	private String name;

	/**
	 * One or two &lt;loginSecPolicy:level&gt; elements that indicate the
	 * possible set of event levels ("warning" or "error") the server will return
	 * to the client for the event type.
	 */
	private List<EventLevel> levels = new ArrayList<EventLevel>();

	/**
	 * OPTIONAL boolean element that indicates whether the event type includes a
	 * &lt;loginSec:exDate&gt; element with the default value of "0" (or "false").
	 */
	private Boolean exDate = Boolean.FALSE;

	/**
	 * OPTIONAL duration element that the event type must be reset. The value
	 * uses the XML schema "duration" type. An example is "P30D" for 90 days.
	 */
	private String exPeriod;

	/**
	 * OPTIONAL duration element that indicates how long prior to expiry the
	 * server will include a warning event. For example, the server will include
	 * a password expiry warning event 15 days prior to expiry. The value uses
	 * the XML schema "duration" type. An example is "P15D" for 15 days.
	 */
	private String warningPeriod;

	/**
	 * OPTIONAL indication of what action will occur with an error.
	 */
	private EventErrorAction errorAction;

	/**
	 * OPTIONAL threshold value that triggers a warning event for a specific
	 * "stat" event. For example, a "failedLogins" "stat" warning event will
	 * occur if the number of failed logins exceeds 100.
	 */
	private Integer threshold;

	/**
	 * OPTIONAL period value that is associated with a warning event for a
	 * specific "stat" event. For example, a "failedLogins" "stat" warning event
	 * will occur if the number of failed logins exceeds the
	 * &lt;loginSecPolicy:threshold&gt; value over a period of 1 day. The value
	 * uses the XML schema "duration" type. An example is "P1D" for 1 day.
	 */
	private String period;

	/**
	 * {@code EPPLoginSecPolicyEvent} default constructor. At least one level
	 * must be defined period to calling {@link #encode(Document)}.
	 */
	public EPPLoginSecPolicyEvent() {
	}

	/**
	 * {@code EPPLoginSecPolicyEvent} constructor that takes the required type
	 * and an single level attributes.
	 *
	 * @param aType
	 *           Event type
	 * @param aLevel
	 *           Single event level the server will return
	 */
	public EPPLoginSecPolicyEvent(EventType aType, EventLevel aLevel) {
		this.type = aType;
		this.addLevel(aLevel);
	}

	/**
	 * {@code EPPLoginSecPolicyEvent} constructor that takes the required type
	 * and levels attributes.
	 *
	 * @param aType
	 *           Event type
	 * @param aLevels
	 *           Possible set of event levels the server will return
	 */
	public EPPLoginSecPolicyEvent(EventType aType, List<EventLevel> aLevels) {
		this.type = aType;
		this.setLevels(aLevels);
	}

	/**
	 * {@code EPPLoginSecPolicyEvent} constructor that takes all attributes.
	 *
	 * @param aType
	 *           Event type
	 * @param aLevels
	 *           Possible set of event levels the server will return
	 * @param aName
	 *           OPTIONAL custom event type or specific statistical event. Set to
	 *           {@code null} if undefined.
	 * @param aExDate
	 *           OPTIONAL boolean element that indicates whether the event type
	 *           includes a &lt;loginSec:exDate&gt; element with a default value
	 *           of {@code false}. Set to {@code null} will set the default.
	 * @param aExPeriod
	 *           OPTIONAL duration element that the event type must be reset. Set
	 *           to {@code null} if undefined.
	 * @param aWarningPeriod
	 *           OPTIONAL duration element that indicates how long prior to
	 *           expiry the server will include a warning event. Set to
	 *           {@code null} if undefined.
	 * @param aErrorAction
	 *           OPTIONAL indication of what action will occur with an error Set
	 *           to {@code null} if undefined.
	 * @param aThreshold
	 *           OPTIONAL threshold value that triggers a warning event for a
	 *           specific "stat" event. Set to {@code null} if undefined.
	 * @param aPeriod
	 *           OPTIONAL period value that is associated with a warning event
	 *           for a specific "stat" event. Set to {@code null} if undefined.
	 */
	public EPPLoginSecPolicyEvent(EventType aType, List<EventLevel> aLevels, String aName, Boolean aExDate,
	      String aExPeriod, String aWarningPeriod, EventErrorAction aErrorAction, Integer aThreshold, String aPeriod) {
		this.type = aType;
		this.setLevels(aLevels);
		this.name = aName;
		this.setExDate(aExDate);
		this.exPeriod = aExPeriod;
		this.warningPeriod = aWarningPeriod;
		this.errorAction = aErrorAction;
		this.threshold = aThreshold;
		this.period = aPeriod;
	}

	/**
	 * Clone {@code EPPLoginSecPolicyEvent} instance.
	 *
	 * @return clone of {@code EPPLoginSecPolicyEvent}
	 *
	 * @exception CloneNotSupportedException
	 *               standard Object.clone exception
	 */
	@Override
	public Object clone() throws CloneNotSupportedException {
		EPPLoginSecPolicyEvent clone = null;

		clone = (EPPLoginSecPolicyEvent) super.clone();

		// Levels
		if (this.levels != null) {
			clone.levels = (List) ((ArrayList) this.levels).clone();
		}

		return clone;
	}

	/**
	 * Validate the state of the {@code EPPLoginSecPolicyEvent} instance. A valid
	 * state means that all of the required attributes have been set. If
	 * validateState returns without an exception, the state is valid. If the
	 * state is not valid, the {@link EPPCodecException} will contain a
	 * description of the error. throws EPPCodecException State error. This will
	 * contain the name of the attribute that is not valid.
	 *
	 * @throws EPPCodecException On invalid state
	 */
	public void validateState() throws EPPCodecException {

		if (this.type == null) {
			throw new EPPCodecException("type required attribute is not set");
		}
		if (!this.hasLevels()) {
			throw new EPPCodecException("levels required attribute is not set");
		}
		if (this.levels.size() > 2) {
			throw new EPPCodecException("Maximum of levels " + this.levels.size() + " exceeds maximum of 2");
		}
	}

	/**
	 * Encode a DOM Element tree from the attributes of the
	 * {@code EPPLoginSecPolicyEvent} instance.
	 *
	 * @param aDocument
	 *           - DOM Document that is being built. Used as an Element factory.
	 *
	 * @return Element - Root DOM Element representing the
	 *         {@code EPPLoginSecPolicyEvent} instance.
	 *
	 * @exception EPPEncodeException
	 *               - Unable to encode {@code EPPLoginSecPolicyEvent} instance.
	 */
	@Override
	public Element encode(Document aDocument) throws EPPEncodeException {

		if (aDocument == null) {
			throw new EPPEncodeException("aDocument is null" + " in EPPLoginSecPolicyEvent.encode(Document)");
		}

		try {
			this.validateState();
		}
		catch (EPPCodecException e) {
			cat.error(this.getClass().getName() + ".encode(): Invalid state on encode: " + e);
			throw new EPPEncodeException("Invalid state on " + this.getClass().getName() + ".encode(): " + e);
		}

		Element root = aDocument.createElementNS(EPPLoginSecPolicyExtFactory.NS, ELM_NAME);

		// Type
		root.setAttribute(ATTR_TYPE, this.type.toString());

		// Name
		if (this.hasName()) {
			root.setAttribute(ATTR_NAME, this.name);
		}

		// Levels
		EPPUtil.encodeList(aDocument, root, this.levels, EPPLoginSecPolicyExtFactory.NS,
		      EPPLoginSecPolicyExtFactory.NS_PREFIX + ":" + ELM_LEVEL);

		// Expiry Date
		EPPUtil.encodeBoolean(aDocument, root, this.exDate, EPPLoginSecPolicyExtFactory.NS,
		      EPPLoginSecPolicyExtFactory.NS_PREFIX + ":" + ELM_EX_DATE);

		// Expiry Period
		EPPUtil.encodeString(aDocument, root, this.exPeriod, EPPLoginSecPolicyExtFactory.NS,
		      EPPLoginSecPolicyExtFactory.NS_PREFIX + ":" + ELM_EX_PERIOD);

		// Warning Period
		EPPUtil.encodeString(aDocument, root, this.warningPeriod, EPPLoginSecPolicyExtFactory.NS,
		      EPPLoginSecPolicyExtFactory.NS_PREFIX + ":" + ELM_WARNING_PERIOD);

		// Error Action
		if (this.hasErrorAction()) {
			EPPUtil.encodeString(aDocument, root, this.errorAction.toString(), EPPLoginSecPolicyExtFactory.NS,
			      EPPLoginSecPolicyExtFactory.NS_PREFIX + ":" + ELM_ERROR_ACTION);
		}

		// Threshold
		EPPUtil.encodeInteger(aDocument, root, this.threshold, EPPLoginSecPolicyExtFactory.NS,
		      EPPLoginSecPolicyExtFactory.NS_PREFIX + ":" + ELM_THRESHOLD);

		// Period
		EPPUtil.encodeString(aDocument, root, this.period, EPPLoginSecPolicyExtFactory.NS,
		      EPPLoginSecPolicyExtFactory.NS_PREFIX + ":" + ELM_PERIOD);

		return root;
	}

	/**
	 * Decode the {@code EPPLoginSecPolicyEvent} element aElement DOM Element
	 * tree.
	 *
	 * @param aElement
	 *           - Root DOM Element to decode {@code EPPLoginSecPolicyEvent}
	 *           from.
	 *
	 * @exception EPPDecodeException
	 *               Unable to decode aElement
	 */
	@Override
	public void decode(Element aElement) throws EPPDecodeException {

		// Type
		this.type = EventType.valueOf(EPPUtil.decodeStringAttr(aElement, ATTR_TYPE));

		// Name
		this.name = EPPUtil.decodeStringAttr(aElement, ATTR_NAME);

		// Levels
		this.levels = EPPUtil.decodeEnumList(aElement, EPPLoginSecPolicyExtFactory.NS, ELM_LEVEL, EventLevel.class);

		// Expiry Date
		this.setExDate(EPPUtil.decodeBoolean(aElement, EPPLoginSecPolicyExtFactory.NS, ELM_EX_DATE));

		// Expiry Period
		this.exPeriod = EPPUtil.decodeString(aElement, EPPLoginSecPolicyExtFactory.NS, ELM_EX_PERIOD);

		// Warning Period
		this.warningPeriod = EPPUtil.decodeString(aElement, EPPLoginSecPolicyExtFactory.NS, ELM_WARNING_PERIOD);

		// Error Action
		String theErrorAction = EPPUtil.decodeString(aElement, EPPLoginSecPolicyExtFactory.NS, ELM_ERROR_ACTION);
		if (theErrorAction == null) {
			this.errorAction = null;
		}
		else {
			this.errorAction = EventErrorAction.valueOf(theErrorAction);
		}

		// Threshold
		this.threshold = EPPUtil.decodeInteger(aElement, EPPLoginSecPolicyExtFactory.NS, ELM_THRESHOLD);

		// Period
		this.period = EPPUtil.decodeString(aElement, EPPLoginSecPolicyExtFactory.NS, ELM_PERIOD);
	}

	/**
	 * implements a deep {@code EPPLoginSecPolicyEvent} compare.
	 *
	 * @param aObject
	 *           {@code EPPLoginSecPolicyEvent} instance to compare with
	 *
	 * @return {@code true} if equal; {@code false} otherwise
	 */
	@Override
	public boolean equals(Object aObject) {
		if (!(aObject instanceof EPPLoginSecPolicyEvent)) {
			return false;
		}

		EPPLoginSecPolicyEvent other = (EPPLoginSecPolicyEvent) aObject;

		// Type
		if (!EqualityUtil.equals(this.type, other.type)) {
			cat.error("EPPLoginSecPolicyEvent.equals(): type not equal");
			return false;
		}

		// Name
		if (!EqualityUtil.equals(this.name, other.name)) {
			cat.error("EPPLoginSecPolicyEvent.equals(): name not equal");
			return false;
		}

		// Expiry Date
		if (!EqualityUtil.equals(this.exDate, other.exDate)) {
			cat.error("EPPLoginSecPolicyEvent.equals(): exDate not equal");
			return false;
		}

		// Expiry Period
		if (!EqualityUtil.equals(this.exPeriod, other.exPeriod)) {
			cat.error("EPPLoginSecPolicyEvent.equals(): exPeriod not equal");
			return false;
		}

		// Warning Period
		if (!EqualityUtil.equals(this.warningPeriod, other.warningPeriod)) {
			cat.error("EPPLoginSecPolicyEvent.equals(): warningPeriod not equal");
			return false;
		}

		// Error Action
		if (!EqualityUtil.equals(this.errorAction, other.errorAction)) {
			cat.error("EPPLoginSecPolicyEvent.equals(): errorAction not equal");
			return false;
		}

		// Threshold
		if (!EqualityUtil.equals(this.threshold, other.threshold)) {
			cat.error("EPPLoginSecPolicyEvent.equals(): threshold not equal");
			return false;
		}

		// Period
		if (!EqualityUtil.equals(this.period, other.period)) {
			cat.error("EPPLoginSecPolicyEvent.equals(): period not equal");
			return false;
		}

		return true;
	}

	/**
	 * Implementation of {@code Object.toString}, which will result in an
	 * indented XML {@code String} representation of the concrete
	 * {@code EPPCodecComponent}.
	 *
	 * @return Indented XML {@code String} if successful; {@code ERROR}
	 *         otherwise.
	 */
	@Override
	public String toString() {
		return EPPUtil.toString(this);
	}

	/**
	 * Returns the XML namespace associated with the {@code EPPCodecComponent}.
	 *
	 * @return XML namespace for the {@code EPPCodecComponent}.
	 */
	@Override
	public String getNamespace() {
		return EPPLoginSecPolicyExtFactory.NS;
	}

	/**
	 * Is the type defined?
	 *
	 * @return {@code true} if the type is defined; {@code false} otherwise.
	 */
	public boolean hasType() {
		return (this.type != null ? true : false);
	}

	/**
	 * Gets the event type value.
	 *
	 * @return {@link EventType} enumerated value if set; {@code null} otherwise.
	 */
	public EventType getType() {
		return this.type;
	}

	/**
	 * Sets the event type value.
	 *
	 * @param aType
	 *           Sets the event type value.
	 */
	public void setType(EventType aType) {
		this.type = aType;
	}

	/**
	 * Is the name defined?
	 *
	 * @return {@code true} if the name is defined; {@code false} otherwise.
	 */
	public boolean hasName() {
		return (this.name != null ? true : false);
	}

	/**
	 * Gets the OPTIONAL event name value.
	 *
	 * @return The event type name if defined; {@code null} otherwise.
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * Sets the OPTIONAL event name value.
	 *
	 * @param aName
	 *           Event type name. Set to {@code null} if undefined.
	 */
	public void setName(String aName) {
		this.name = aName;
	}

	/**
	 * Is the level list defined?
	 *
	 * @return {@code true} if the level list is defined; {@code false}
	 *         otherwise.
	 */
	public boolean hasLevels() {
		return (this.levels != null && !this.levels.isEmpty() ? true : false);
	}

	/**
	 * Gets the level list.
	 *
	 * @return Level list
	 */
	public List<EventLevel> getLevels() {
		return this.levels;
	}

	/**
	 * Sets the level list.
	 *
	 * @param aLevels
	 *           List of levels.
	 */
	public void setLevels(List<EventLevel> aLevels) {
		if (aLevels == null) {
			this.levels = new ArrayList<EventLevel>();
		}
		else {
			this.levels = aLevels;
		}
	}

	/**
	 * Add a level to the list of levels.
	 *
	 * @param aLevel
	 *           Level to add to the list of levels.
	 */
	public void addLevel(EventLevel aLevel) {
		if (aLevel == null) {
			this.levels = new ArrayList<EventLevel>();
		}
		this.levels.add(aLevel);
	}

	/**
	 * Gets the OPTIONAL boolean element that indicates whether the event type
	 * includes a &lt;loginSec:exDate&gt; element with the default value of
	 * {@code false}.
	 *
	 * @return {@code true} or {@code false} indicating whether the event type
	 *         includes a &lt;loginSec:exDate&gt; element.
	 */
	public Boolean getExDate() {
		return this.exDate;
	}

	/**
	 * Sets the OPTIONAL boolean element that indicates whether the event type
	 * includes a &lt;loginSec:exDate&gt; element with the default value of
	 * {@code false}.
	 *
	 * @param aExDate
	 *           {@code true} or {@code false} indicating whether the server
	 *           event type includes a &lt;loginSec:exDate&gt; element. If
	 *           {@code null} is passed, the default value of {@code false} will
	 *           be set.
	 */
	public void setExDate(Boolean aExDate) {
		if (aExDate == null) {
			this.exDate = Boolean.FALSE;
		}
		else {
			this.exDate = aExDate;
		}
	}

	/**
	 * Is the expiry period defined?
	 *
	 * @return {@code true} if the expiry period is defined; {@code false}
	 *         otherwise.
	 */
	public boolean hasExPeriod() {
		return (this.exPeriod != null ? true : false);
	}

	/**
	 * Gets the OPTIONAL expiry period value, which identifies the duration that
	 * the event type must be set using the XML schema "duration" type. An
	 * example is a value of "P90D" for define 90 days.
	 *
	 * @return expiry period if defined; {@code null} otherwise.
	 */
	public String getExPeriod() {
		return this.exPeriod;
	}

	/**
	 * Sets the OPTIONAL expiry period value, which identifies the duration that
	 * the event type must be set using the XML schema "duration" type. An
	 * example is a value of "P90D" for define 90 days.
	 *
	 * @param aExPeriod
	 *           Expiry period using the XML schema "duration" type. Set to
	 *           {@code null} if undefined.
	 */
	public void setExPeriod(String aExPeriod) {
		this.exPeriod = aExPeriod;
	}

	/**
	 * Is the warning period defined?
	 *
	 * @return {@code true} if the warning period is defined; {@code false}
	 *         otherwise.
	 */
	public boolean hasWarningPeriod() {
		return (this.warningPeriod != null ? true : false);
	}

	/**
	 * Gets the OPTIONAL warning period value, which indicates how long prior to
	 * expiry the server will include a warning event using the XML schema
	 * "duration" type. An example is a value of "P15D" for define 15 days.
	 *
	 * @return warning period if defined; {@code null} otherwise.
	 */
	public String getWarningPeriod() {
		return this.warningPeriod;
	}

	/**
	 * Sets the OPTIONAL warning period value, which indicates how long prior to
	 * expiry the server will include a warning event using the XML schema
	 * "duration" type. An example is a value of "P15D" for define 15 days.
	 *
	 * @param aWarningPeriod
	 *           Warning period using the XML schema "duration" type. Set to
	 *           {@code null} if undefined.
	 */
	public void setWarningPeriod(String aWarningPeriod) {
		this.warningPeriod = aWarningPeriod;
	}

	/**
	 * Is the error action defined?
	 *
	 * @return {@code true} if the error action is defined; {@code false}
	 *         otherwise.
	 */
	public boolean hasErrorAction() {
		return (this.errorAction != null ? true : false);
	}

	/**
	 * Gets the error action.
	 *
	 * @return The error action if defined; {@code null} otherwise.
	 */
	public EventErrorAction getErrorAction() {
		return this.errorAction;
	}

	/**
	 * Sets the error action.
	 *
	 * @param aErrorAction
	 *           Action that will occur with an error. Set to {@code null} if
	 *           undefined.
	 */
	public void setErrorAction(EventErrorAction aErrorAction) {
		this.errorAction = aErrorAction;
	}

	/**
	 * Is the threshold defined?
	 *
	 * @return {@code true} if the threshold is defined; {@code false} otherwise.
	 */
	public boolean hasThreshold() {
		return (this.threshold != null ? true : false);
	}

	/**
	 * Gets the OPTIONAL threshold value that triggers a warning event for a
	 * specific "stat" event.
	 *
	 * @return Threshold value that triggers a warning event for a specific
	 *         "stat" event if defined; {@code null} otherwise.
	 */
	public Integer getThreshold() {
		return this.threshold;
	}

	/**
	 * Sets the OPTIONAL threshold value that triggers a warning event for a
	 * specific "stat" event.
	 *
	 * @param aThreshold
	 *           Threshold value that triggers a warning event for a specific
	 *           "stat" event. Set to {@code null} if undefined.
	 */
	public void setThreshold(Integer aThreshold) {
		this.threshold = aThreshold;
	}

	/**
	 * Is the period defined?
	 *
	 * @return {@code true} if the period is defined; {@code false} otherwise.
	 */
	public boolean hasPeriod() {
		return (this.period != null ? true : false);
	}

	/**
	 * Gets the OPTIONAL period value, which indicates the period value that is
	 * associated with a warning event for a specific "stat" event. using the XML
	 * schema "duration" type. An example is a value of "P1D" for define 1 day.
	 *
	 * @return period if defined; {@code null} otherwise.
	 */
	public String getPeriod() {
		return this.period;
	}

	/**
	 * Sets the OPTIONAL period value, which indicates the period value that is
	 * associated with a warning event for a specific "stat" event. using the XML
	 * schema "duration" type. An example is a value of "P1D" for define 1 day.
	 *
	 * @param aPeriod
	 *           Period value, which indicates the period value that is
	 *           associated with a warning event for a specific "stat" event.
	 *           using the XML schema "duration" type. Set to {@code null} if
	 *           undefined.
	 */
	public void setPeriod(String aPeriod) {
		this.period = aPeriod;
	}

}
