/* Tag.java created 2007-09-28 * */ package org.signalml.plugin.export.signal; import static org.signalml.app.util.i18n.SvarogI18n._; import java.beans.IntrospectionException; import java.util.LinkedList; import java.util.List; import org.signalml.app.model.components.ChannelPropertyEditor; import org.signalml.app.model.components.LabelledPropertyDescriptor; import org.signalml.app.model.components.PropertyProvider; import org.signalml.plugin.export.signal.tagStyle.TagAttributeValue; import org.signalml.plugin.export.signal.tagStyle.TagAttributes; import org.signalml.plugin.export.signal.tagStyle.TagStyleAttributeDefinition; import org.springframework.context.MessageSourceResolvable; /** * This class represents a tagged {@link SignalSelection selection} of a signal. * Contains the {@link TagStyle style} and annotation of this selection. * Allows to compare tagged selections using its left end, length and the * number of channel (in this order). * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class Tag extends SignalSelection implements Comparable<ExportedTag>, Cloneable, MessageSourceResolvable, PropertyProvider, ExportedTag { //TODO (can't extend SignalSelection due to strange xstream behaviour) private static final long serialVersionUID = 1L; /** * {@link TagStyle style} of this tagged selection */ private TagStyle style; /** * The annotation of the tag. */ private String annotation; /** * The attributes which are assigned to this tag (annotation is not included). */ private TagAttributes tagAttributes = new TagAttributes(); /** * Constructor. Creates a tagged selection from a given * {@link SignalSelection selection} with a given {@link TagStyle style} * and annotation. * @param style the style of the tagged selection * @param signalSelection a signal selection to be copied/used * @param annotation an annotation of a tagged selection */ public Tag(TagStyle style, SignalSelection signalSelection, String annotation) { super(style.getType(), signalSelection.getPosition(), signalSelection.getLength(), signalSelection.getChannel()); this.style = style; this.annotation = annotation; } /** * Constructor. Creates a tagged selection with a given * {@link TagStyle style}, starting position, length, annotation and * the number of the channel. * @param style the style of the tagged selection * @param d the position from which the selection starts * @param e the length of the selection * @param channel a number of a channel which this selection should * concern. CHANNEL_NULL if selection should concern all channels * @param annotation an annotation of a tagged selection */ public Tag(TagStyle style, double d, double e, int channel, String annotation) { super(style.getType(), d, e, channel); this.style = style; this.annotation = annotation; } /** * Constructor. Creates a tagged selection with a given * {@link TagStyle style}, starting position and length, but without * any annotation. Selection will concern all channels. * @param style the style of the tagged selection. * @param position the position from which the selection starts * @param length the length of the selection */ public Tag(TagStyle style, double position, double length) { super((style != null ? style.getType() : SignalSelectionType.CHANNEL), position, length); this.style = style; } /** * Constructor. Creates a tagged selection with a given * {@link TagStyle style}, starting position, length and the number of * channel, but without any annotation. * @param style the style of the tagged selection * @param position the position from which the selection starts * @param length the length of the selection * @param channel a number of a channel which this selection should */ public Tag(TagStyle style, double position, double length, int channel) { super(style.getType(), position, length, channel); this.style = style; } /** * Copy constructor. * @param tag the tagged selection to be copied */ public Tag(Tag tag) { this(tag.style, tag.position, tag.length, tag.channel, tag.getAnnotation()); } /** * Copy constructor. * Creates a tag using the parameters provided by given interface. * @param tag the object which parameters are to be copied */ public Tag(ExportedTag tag) { this(new TagStyle(tag.getStyle()), tag.getPosition(), tag.getLength(), tag.getChannel(), tag.getAnnotation()); } /** * Returns the style of this tagged selection. * @return the style of this tagged selection */ @Override public TagStyle getStyle() { return style; } /** * Sets the style of this tag. * @param style the style to be used by this tag */ public void setStyle(TagStyle style) { this.style = style; } /** * Returns the annotation of this tagged selection. * @return the annotation of this tagged selection */ @Override public String getAnnotation() { return annotation; } /** * Sets the annotation of this tagged selection. * @param annotation the annotation to be set */ @Override public void setAnnotation(String annotation) { this.annotation = annotation; } /** * Adds an attribute to this tag. * @param attributeValue the object describing the attribute */ public void setAttribute(TagAttributeValue attributeValue) { tagAttributes.addAttribute(attributeValue); } /** * Returns whether this tagged selection is a marker. * @return true if this tagged selection is a marker, false otherwise */ @Override public boolean isMarker() { return (style != null ? style.isMarker() : false); } /** * Compares the current object to given. * The comparison uses the following characteristics in turn: * starting position, length, the channel number, * and the TagStyle of this tag. The first characteristic that * doesn't match determines the outcome of the comparison. * @param t a tagged selection to be compared with the current object * @return > 0 if the current object is greater than given; * < 0 if current is smaller than given; * 0 if the selections are equal. */ public int compareTo(Tag t) { double test = this.getTimestamp() - t.getTimestamp(); if (test == 0) { test = length - t.length; if (test == 0) { test = channel - t.channel; if (((int) test) == 0) { if (style != null && t.style != null) { return style.compareTo(t.style); } else { return 0; } } } } return (int) Math.signum(test); } /** * Checks if this tagged selection is equal to given. * Uses {@link #compareTo(Tag)}. * @param obj an object to be compared with this tagged selection * @return true if a given object is equal to this tagged selection, * false otherwise */ @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof Tag)) { return false; } return (this.compareTo((Tag) obj) == 0); } /** * Creates a copy of this tagged selection. * @return a copy of this tagged selection */ @Override public Tag clone() { Tag tag = new Tag(style, position, length, channel, this.getAnnotation()); tag.tagAttributes = tagAttributes.clone(); return tag; } @Override public String toString() { return style.getName() + ": " + position + " -> " + (position + length); } @Override public Object[] getArguments() { return new Object[] { style.getDescriptionOrName(), position, length, position + length, channel }; } @Override public String[] getCodes() { return new String[] { (channel == CHANNEL_NULL ? "tagWithoutChannel" : "tagWithChannel") }; } @Override public String getDefaultMessage() { return toString(); } @Override public List<LabelledPropertyDescriptor> getPropertyList() throws IntrospectionException { List<LabelledPropertyDescriptor> list = new LinkedList<LabelledPropertyDescriptor>(); list.add(new LabelledPropertyDescriptor(_("style"), "style", Tag.class, "getStyle", null)); list.add(new LabelledPropertyDescriptor(_("position"), "position", Tag.class)); list.add(new LabelledPropertyDescriptor(_("length"), "length", Tag.class)); if (channel != CHANNEL_NULL) { LabelledPropertyDescriptor channel = new LabelledPropertyDescriptor(_("channel"), "channel", Tag.class); channel.setPropertyEditorClass(ChannelPropertyEditor.class); list.add(channel); } list.add(new LabelledPropertyDescriptor(_("annotation"), "annotation", Tag.class)); return list; } /* (non-Javadoc) * @see org.signalml.plugin.export.signal.ExportedTag#compareTo(org.signalml.plugin.export.signal.ExportedTag) */ @Override public int compareTo(ExportedTag t) { double test = this.getTimestamp() - t.getTimestamp(); if (test == 0) { test = length - t.getLength(); if (test == 0) { test = channel - t.getChannel(); if (((int) test) == 0) { if (style != null && t.getStyle() != null) { TagStyle newStyle = new TagStyle(t.getStyle()); return style.compareTo(newStyle); } else { return 0; } } } } return (int) Math.signum(test); } /** * Returns the attributes set for this tag. * @return attributes set for this tag */ public TagAttributes getAttributes() { return tagAttributes; } /** * Adds an attribute to the tag. If a tag attribute definition for the * attribute doesn't exist, it is created. * @param attributeCode tag attribute code (name) * @param value the value of the attribute */ public void addAttributeToTag(String attributeCode, String value) { TagStyleAttributeDefinition attributeDefinition = style.getAttributesDefinitions().getAttributeDefinition(attributeCode); if (attributeDefinition == null) { attributeDefinition = new TagStyleAttributeDefinition(attributeCode, attributeCode, true); style.getAttributesDefinitions().addAttributeDefinition(attributeDefinition); } TagAttributeValue attributeValue = new TagAttributeValue(attributeDefinition, value); setAttribute(attributeValue); } }