package rocks.inspectit.server.diagnosis.engine.tag; import java.util.Objects; import org.apache.commons.lang.builder.ToStringBuilder; import rocks.inspectit.server.diagnosis.engine.rule.ActionMethod; import rocks.inspectit.server.diagnosis.engine.rule.RuleOutput; import rocks.inspectit.server.diagnosis.engine.rule.store.IRuleOutputStorage; /** * A <code>Tag</code> represents the actual result of a rule execution. Everything what is created * by a {@link ActionMethod} is wrapped in a <code>Tag</code>. A <code>Tag</code> can thus be * considered as a qualified attachment to the currently analyzed object. Depending on the * {@link ActionMethod} configuration/implementation, one rule can produce multiple <code>Tag</code> * s. <b>Be aware that all produced Tags are of the same type. It is invalid/impossible to create * different Tag types</b>. All <code>Tag</code>s are gathered to one {@link RuleOutput} and stored * in the {@link IRuleOutputStorage}. * * @author Claudio Waldvogel, Alexander Wert * @see IRuleOutputStorage * @see RuleOutput */ public class Tag { /** * The type of this <code>Tag</code>. This is a simple, but unique, identifier. */ private final String type; /** * The value of this Tag. No assumptions are made what the value is. Everything is a valid * value. */ private final Object value; /** * The parent Tag. */ private final Tag parent; /** * The state of this Tag. * * <pre> * <ul> * <li><b>TagState.LEAF</b>, if the value is was not processed any further.</li> * <li><b>TagState.PARENT</b>, if the value was processed to create further <code>Tag</code>s</li> * </ul> * </pre> */ private TagState state = TagState.LEAF; // ------------------------------------------------------------- // Constructors // ------------------------------------------------------------- /** * Default Constructor. * * @param type * The type of this <code>Tag</code>. The is an equivalent to a Tag's name. */ public Tag(String type) { this(type, null, null); } /** * Constructor to create a Tag with an associated value. * * @param type * The type of the <code>Tag</code> * @param value * The value of this <code>Tag</code> */ public Tag(String type, Object value) { this(type, value, null); } /** * Creates a Tag with a value and a parent. * * @param type * The type of this <code>Tag</code>. * @param value * The value of this <code>Tag</code> * @param parent * The <code>Tag</code> which is considered as the predecessor of this * <code>Tag</code>. */ public Tag(String type, Object value, Tag parent) { this.value = value; this.type = type; this.parent = parent; if (this.parent != null) { this.parent.markParent(); } } // ------------------------------------------------------------- // Methods: Accessors // ------------------------------------------------------------- /** * Gets {@link #type}. * * @return {@link #type} */ public String getType() { return type; } /** * Gets {@link #value}. * * @return {@link #value} */ public Object getValue() { return value; } /** * Gets {@link #parent}. * * @return {@link #parent} */ public Tag getParent() { return parent; } /** * Gets {@link #state}. * * @return {@link #state} */ public TagState getState() { return state; } // ------------------------------------------------------------- // Methods: Internals // ------------------------------------------------------------- /** * Utility method to mark a <code>Tag</code> as parent by setting the state to * {@link TagState#PARENT}. */ private void markParent() { if (state.equals(TagState.LEAF)) { state = TagState.PARENT; } } // ------------------------------------------------------------- // Methods: Generated // ------------------------------------------------------------- /** * {@inheritDoc} */ @Override public String toString() { return new ToStringBuilder(this).append("type", type).append("value", value).append("parent", parent).append("state", state).toString(); } /** * {@inheritDoc} */ @Override public int hashCode() { final int prime = 31; int result = 1; result = (prime * result) + ((this.parent == null) ? 0 : this.parent.hashCode()); result = (prime * result) + ((this.state == null) ? 0 : this.state.hashCode()); result = (prime * result) + ((this.type == null) ? 0 : this.type.hashCode()); result = (prime * result) + ((this.value == null) ? 0 : this.value.hashCode()); return result; } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Tag other = (Tag) obj; if (this.parent == null) { if (other.parent != null) { return false; } } else if (!this.parent.equals(other.parent)) { return false; } if (this.state != other.state) { return false; } if (this.type == null) { if (other.type != null) { return false; } } else if (!this.type.equals(other.type)) { return false; } if (this.value == null) { if (other.value != null) { return false; } } else if (!Objects.deepEquals(this.value, other.value)) { return false; } return true; } }