All Downloads are FREE. Search and download functionalities are using the official Maven repository.

timeBench.data.TemporalElement Maven / Gradle / Ivy

Go to download

TimeBench, a flexible, easy-to-use, and reusable software library written in Java that provides foundational data structures and algorithms for time- oriented data in Visual Analytics.

The newest version!
package timeBench.data;

import org.timebench.util.lang.CustomIterable;

import ieg.prefuse.data.ParentChildNode;
import prefuse.data.Table;
import prefuse.data.Tuple;
import prefuse.data.tuple.TableNode;
import timeBench.calendar.Granule;

/**
 * Relational view of the temporal element. Following the proxy tuple
 * pattern [Heer & Agrawala, 2006] it provides an object oriented proxy for
 * accessing a row of the temporal elements table.
 * 
 * 

* Note that this class provides only a thin layer over {@link TableNode} and * {@link TableTuple} for increased convenience. Methods such as * {@link #set(int, Object)} can still be called, which might put this object or * the whole temporal dataset in an inconsistent state. * * @author Rind */ public abstract class TemporalElement extends ParentChildNode implements Comparable { protected static TemporalElementStore temporalDataHeap = new TemporalElementStore(); // predefined column names for temporal elements (similar to VisualItem) /** * the identifier data field for temporal elements. Primary key of the * temporal element table. */ public static final String ID = "id"; /** * the "inf" data field for temporal elements. */ public static final String INF = "inf"; /** * the "sup" data field for temporal elements. */ public static final String SUP = "sup"; /** * the "granularity id" data field for temporal elements. */ public static final String GRANULARITY_ID = "granularityID"; /** * the "granularity context id" data field for temporal elements. */ public static final String GRANULARITY_CONTEXT_ID = "granularityContextID"; /** * the "kind" data field for temporal elements. */ public static final String KIND = "kind"; /** * creates an invalid TemporalElement. Use {@link TemporalDataset} as a * factory! */ protected TemporalElement() { } /** * Initialize a new temporal element backed by a node table. This method is * used by the appropriate TupleManager instance, and should not be called * directly by client code, unless by a client-supplied custom TupleManager. * * @param table * the backing table * @param graph * the backing graph * @param row * the row in the node table to which this temporal element * corresponds */ protected void init(Table table, TemporalElementStore graph, int row) { super.init(table, graph, row); } /** * Creates a TemporalElement on the temporal data heap. Note that * currently, these TemporalElements have to be cleared manually * from there as there is no full support for weak references * in Java. * * @param inf * the lower end of the temporal element * @param sup * the upper end of the temporal element * @param granularityId * the granularityID of the temporal element * @param granularityContextId * the granularityContextID of the temporal element * @param kind * the kind of the temporal element * @return the created temporal element */ public static TemporalElement createOnHeap(long inf, long sup, int granularityId, int granularityContextId, int kind) { return temporalDataHeap.addTemporalElement(inf, sup, granularityId, granularityContextId, kind); } /** * Destroys an instance of a (this) TemporalElement on the heap. * If it is not on the heap, nothing is done to prevent this, so prefuse will * throw an IllegalArgumentException. External references to * this TemporalElement should be cleared by the calling code. */ public void destroyFromHeap() { temporalDataHeap.removeTemporalElement(this); } /** * Indicates if the temporal element is anchored in time. * *

* Anchored temporal elements represent one or more granules on an * underlying granularity. They have an infimum and an supremum in the * discrete time domain. * * @return true if the element is anchored */ public abstract boolean isAnchored(); /** * Gets the length of the temporal element. * *

* This can be either *

  • the number of chronons in the bottom granularity for anchored * temporal elements or *
  • the number of granules in the current granularity for unanchored * temporal elements. * * @return the length of the temporal element */ // TODO does it make sense to have a common method for all temporal elements? public abstract long getLength(); /** * Sets the length of the temporal element. * *

    * This can be either *

  • the number of chronons in the bottom granularity for anchored * temporal elements or *
  • the number of granules in the current granularity for unanchored * temporal elements. * * @value the length of the temporal element */ // TODO does it make sense to have a common method for all temporal elements? public abstract void setLength(long value); /** * Get the temporal dataset of which this element is a member. * * @return the backing temporal dataset */ public TemporalElementStore getTemporalElementStore() { return (TemporalElementStore) this.m_graph; } /** * Get the temporal element id. * * @return the id */ public long getId() { return super.getLong(TemporalElement.ID); } /** * Get the granularity id. * * @return the granularity id */ public int getGranularityId() { return super.getInt(TemporalElement.GRANULARITY_ID); } /** * Get the granularity context id. * * @return the granularity context id */ public int getGranularityContextId() { return super.getInt(TemporalElement.GRANULARITY_CONTEXT_ID); } public static final int SPAN = 0x00; public static final int SET = 0x01; public static final int INSTANT = 0x02; public static final int INTERVAL = 0x03; public static final int RECURRING_INSTANT = 0x12; public static final int RECURRING_INTERVAL = 0x13; // Byte 1 Byte 2 Byte 3 Byte 4 // 0x00 normal // 0x01 template // subkind // data primitive template primitive // // checks agains non-template -> false // instant template granularities must be smaller or equal to instant data granularities // d chronons before -> recalculate, check for starts public static final int TEMPLATE_BEFORE_INSTANT_INSTANT = 0x01000202; public static final int TEMPLATE_AFTER_INSTANT_INSTANT = 0x01010202; public static final int TEMPLATE_STARTS_INSTANT_INSTANT = 0x01020202; public static final int TEMPLATE_FINISHES_INSTANT_INSTANT = 0x01030202; public static final int TEMPLATE_DURING_INSTANT_INSTANT = 0x01040202; public static final int TEMPLATE_OUTSIDE_INSTANT_INSTANT = 0x01050202; public static final int TEMPLATE_OVERLAP_START_INSTANT_INSTANT = 0x01060202; public static final int TEMPLATE_OVERLAP_FINISH_INSTANT_INSTANT = 0x01070202; public static final int TEMPLATE_BEFORE_INTERVAL_INSTANT = 0x01000302; public static final int TEMPLATE_AFTER_INTERVAL_INSTANT = 0x01010302; public static final int TEMPLATE_STARTS_INTERVAL_INSTANT = 0x01020302; public static final int TEMPLATE_FINISHES_INTERVAL_INSTANT = 0x01030302; public static final int TEMPLATE_OUTSIDE_INTERVAL_INSTANT = 0x01050302; public static final int TEMPLATE_OVERLAP_START_INTERVAL_INSTANT = 0x01060302; public static final int TEMPLATE_OVERLAP_FINISH_INTERVAL_INSTANT = 0x01070302; public static final int TEMPLATE_BEFORE_INTERVAL_INTERVAL = 0x01000303; public static final int TEMPLATE_AFTER_INTERVAL_INTERVAL = 0x01010303; public static final int TEMPLATE_STARTS_INTERVAL_INTERVAL = 0x01020303; public static final int TEMPLATE_FINISHES_INTERVAL_INTERVAL = 0x01030303; public static final int TEMPLATE_DURING_INTERVAL_INTERVAL = 0x01040303; public static final int TEMPLATE_OUTSIDE_INTERVAL_INTERVAL = 0x01050303; public static final int TEMPLATE_OVERLAP_START_INTERVAL_INTERVAL = 0x01060303; public static final int TEMPLATE_OVERLAP_FINISH_INTERVAL_INTERVAL = 0x01070203; public static final int TEMPLATE_ASLONGAS_SPAN_SPAN = 0x01100000; public static final int TEMPLATE_ASLONGAS_INTERVAL_SPAN = 0x01100300; public static final int TEMPLATE_STARTS_RECURRING_INSTANT_RECURRING_INSTANT = 0x01021212; public static final int TEMPLATE_FINISHES_RECURRING_INSTANT_RECURRING_INSTANT = 0x01031212; public static final int TEMPLATE_OUTSIDE_RECURRING_INSTANT_RECURRING_INSTANT = 0x01041212; public static final int TEMPLATE_OVERLAP_START_RECURRING_INSTANT_RECURRING_INSTANT = 0x01061212; public static final int TEMPLATE_OVERLAP_FINISH_RECURRING_INSTANT_RECURRING_INSTANT = 0x01071212; public static final int TEMPLATE_STARTS_RECURRING_INTERVAL_RECURRING_INSTANT = 0x01021312; public static final int TEMPLATE_FINISHES_RECURRING_INTERVAL_RECURRING_INSTANT = 0x01031312; public static final int TEMPLATE_DURING_RECURRING_INTERVAL_RECURRING_INTERVAL = 0x01041313; public static final int TEMPLATE_OUTSIDE_RECURRING_INTERVAL_RECURRING_INSTANT = 0x01041312; public static final int TEMPLATE_OVERLAP_START_RECURRING_INTERVAL_RECURRING_INSTANT = 0x01061312; public static final int TEMPLATE_OVERLAP_FINISH_RECURRING_INTERVAL_RECURRING_INSTANT = 0x01071312; public static final int TEMPLATE_ASLONGAS_RECURRING_INTERVAL_SPAN = 0x01101300; /** * Get the kind of temporal element (0 = span, 1 = set/temporal element, 2 = * instant, 3 = interval) * * @return the kind of temporal element */ public int getKind() { return super.getInt(TemporalElement.KIND); } /** * converts to a generic temporal element. * * @return a generic temporal element of the same underlying data row. */ public GenericTemporalElement asGeneric() { return ((TemporalElementStore) this.m_graph).getTemporalElementByRow(this.m_row); } /** * converts to a temporal primitive. * * @return a temporal primitive of the same underlying data row. */ public TemporalElement asPrimitive() { return ((TemporalElementStore) this.m_graph).getTemporalPrimitiveByRow(this.m_row); } /** * returns the first instant of temporal element. * for instants, return this. * for intervals, return begin. * for others, does not interpret the semantics, just goes down to first child and tries again * * @return the first instant * @throws TemporalDataException */ public Instant getFirstInstant() throws TemporalDataException { TemporalElement thisElement = this.asPrimitive(); if (thisElement instanceof Instant) { return (Instant)thisElement; } else if (thisElement instanceof Interval) { return ((Interval)thisElement).getBegin(); // TODO check if this is implemented yet } else if (thisElement.getFirstChild() != null) { return ((TemporalElement)thisElement.getFirstChild()).getFirstInstant(); } return null; } /** * returns the last instant of temporal element. * for instants, return this. * for intervals, return end. * for others, does not interpret the semantics, just goes down to first child and tries again * * @return the first instant * @throws TemporalDataException */ public Instant getLastInstant() throws TemporalDataException { TemporalElement thisElement = this.asPrimitive(); if (thisElement instanceof Instant) { return (Instant)thisElement; } else if (thisElement instanceof Interval) { return ((Interval)thisElement).getEnd(); // TODO check if this is implemented yet } else if (thisElement.getLastChild() != null) { return ((TemporalElement)thisElement.getLastChild()).getLastInstant(); } return null; } /** * Get an iterator over all temporal objects occurring with this temporal * element. * * @return temporal objects occurring with the temporal element */ public Iterable temporalObjects() { return ((TemporalElementStore) this.m_graph).getTemporalObjectsByElementId(getId()); } public Iterable temporalObjects(TemporalDataset tmpds) { return tmpds.getTemporalObjectsByElementId(getId()); } /** * Get an iterator over all temporal elements that are parents of this * temporal element. * * @return an iterator over parents */ @SuppressWarnings("unchecked") public Iterable parentElements() { return new CustomIterable(super.parents()); } /** * Get an iterator over all temporal elements that are children of this * temporal element. * * @return an iterator over children */ @SuppressWarnings("unchecked") public Iterable childElements() { return new CustomIterable(super.children()); } /** * Get the first or only child temporal element as a primitive. * * @return a temporal element that is child of this temporal element or * null. */ public TemporalElement getFirstChildPrimitive() { int child = getGraph().getChildRow(m_row, 0); if (child > -1) { return ((TemporalElementStore) this.m_graph).getTemporalPrimitiveByRow(child); } else { return null; } } /** * Get the last or only child temporal element as a primitive. * * @return a temporal element that is child of this temporal element or * null. */ public TemporalElement getLastChildPrimitive() { int child = getGraph().getChildRow(m_row, getChildCount() - 1); if (child > -1) { return ((TemporalElementStore) this.m_graph).getTemporalPrimitiveByRow(child); } else { return null; } } /** * Gets the first granule of an anchored temporal element. For an * {@link Instant}, the granule represents the time of the instant. If it is * unanchored, null is returned. Granules are cached. * * @return the first granule * @throws TemporalDataException * @see timeBench.data.util.GranuleCache */ public Granule getGranule() throws TemporalDataException { return getGranules()[0]; } /** * Gets a list of granules of an anchored temporal element. If it is * unanchored, null is returned. Granules are cached. * * @return the first granule * @throws TemporalDataException * @see timeBench.data.util.GranuleCache */ public Granule[] getGranules() throws TemporalDataException { return ((TemporalElementStore) this.m_graph).getGranulesByRow(m_row); } /** * creates a human-readable string from a {@link TemporalElement}. *

    * Example: GenericTemporalElement[id=2, inf=3, sup=14, granularityId=1, granularityContextId=1, kind=1] * * @return a string representation */ @Override public String toString() { /*return getClass().getSimpleName() + "[id=" + getId() + ", inf=" + super.getLong(TemporalElement.INF) + ", sup=" + super.getLong(TemporalElement.SUP) + ", granularityId=" + getGranularityId() + ", granularityContextId=" + getGranularityContextId() + ", kind=" + getKind() + "]";*/ return ""+getId(); } @Override public int compareTo(TemporalElement aThat) { final int BEFORE = -1; final int EQUAL = 0; final int AFTER = 1; // this optimization is usually worthwhile, and can always be added if (this == aThat) return EQUAL; // primitive numbers follow this form if (this.getLong(INF) < aThat.getLong(INF)) return BEFORE; if (this.getLong(INF) > aThat.getLong(INF)) return AFTER; if (this.getLong(SUP) < aThat.getLong(SUP)) return BEFORE; if (this.getLong(SUP) > aThat.getLong(SUP)) return AFTER; // ID and Graph absolutely identify a TemporalElement tuple if (this.getLong(ID) < aThat.getLong(ID)) return BEFORE; if (this.getLong(ID) > aThat.getLong(ID)) return AFTER; if (this.getGraph() == aThat.getGraph()) return EQUAL; if (this.getGraph().hashCode() < aThat.getGraph().hashCode()) return BEFORE; else return AFTER; } @Override public boolean equals(Object obj) { if (obj instanceof TemporalElement) { TemporalElement el = (TemporalElement) obj; return this.getId() == el.getId() && this.getGraph() == el.getGraph(); } else { return false; } } }





  • © 2015 - 2025 Weber Informatics LLC | Privacy Policy