Click or drag to resize

Archiving

While the primary purpose of Tracking Library is to enable the ability to perform analysis and visualization as data is received, it also contains a set of classes for archiving received data for later analysis and review.

Note Note

The functionality described in this topic requires a license for the Tracking Library.

Archiving Entities

TrackingArchive<TEntity> is an abstract base class that archives entities. The following implementations are provided:

You can create your own archiver by deriving from TrackingArchive<TEntity> and implementing the required methods. Data can be retrieved from an archive in several formats: raw property data, an entity, a DateMotionCollection1<T>, a DateMotionCollection2<T, TDerivative>, a Point, or an Axes.

Entity Schema

In order for an entity to be used by an archiver, an entity schema and set of archivers must be defined. These items are registered using the EntityDescriptor<TEntity> class, which is described in more detail in the Entities topic. By implementing the IEntityArchiveDescriptor<TEntity> interface, you control exactly what data gets written to and read from an archive.

The schema defines which properties are stored in the archive, and their names. The archivers define how to store a particular type of value in an archive.

The following code sample defines an entity descriptor that implements IEntityArchiveDescriptor<TEntity>. The schema and archivers are configured in the constructor.

Java
public class ExampleEntityDescriptorWithArchive extends EntityDescriptor<ExampleEntity>
        implements IEntityPositionDescriptor, IEntityOrientationDescriptor, IEntityArchiveDescriptor<ExampleEntity> {
    public ExampleEntityDescriptorWithArchive() {
        // Schema
        m_schema = new EntitySchema<>(String.class);
        CommonEntityInterfaces.IEntityLastUpdate.addToSchema(m_schema);
        CommonEntityInterfaces.IEntityVelocity.addToSchema(m_schema);
        CommonEntityInterfaces.IEntityOrientation.addToSchema(m_schema);
        m_schema.addProperty(new TypeLiteral<String>() {}, "SymbolId", EntityTransactedPropertyGetter.of(entity -> entity.getSymbolId()));
        m_schema.addProperty(new TypeLiteral<Force>() {}, "Affiliation", EntityTransactedPropertyGetter.of(entity -> entity.getAffiliation()));

        // Archivers
        m_archivers = new TrackingTypeArchiverCollection();
        m_archivers.addEnumeration(new TypeLiteral<Force>() {});
        m_archivers.freeze();
    }

    @Override
    public final ReferenceFrame getPositionReferenceFrame() {
        return CentralBodiesFacet.getFromContext().getEarth().getFixedFrame();
    }

    @Override
    public final Axes getOrientationAxes() {
        return getPositionReferenceFrame().getAxes();
    }

    @Override
    public final EntitySchema<ExampleEntity> getSchema() {
        return m_schema;
    }

    @Override
    public final TrackingTypeArchiverCollection getArchivers() {
        return m_archivers;
    }

    @Override
    public final ExampleEntity createEntity(TransactionContext context, Object entityIdentifier) {
        return new ExampleEntity(context, (String) entityIdentifier);
    }

    private EntitySchema<ExampleEntity> m_schema;
    private TrackingTypeArchiverCollection m_archivers;
}

The schema is defined by constructing an EntitySchema<TEntity>, passing in the type of the EntityIdentifier (get) property. For each standard interface that the entity implements, addToSchema is called on the equivalent static class in CommonEntityInterfaces in order to add the properties that correspond to that particular interface to the schema. Once the standard interfaces are defined in the schema, any remaining properties are then added by calling addProperty, passing the name of the property and a delegate that will get the value of the property from an entity. After the schema is defined, the set of TrackingTypeArchivers which can read and write entity data must also be defined. By default, TrackingTypeArchiverCollection already contains archivers which can handle all primitive types as well as most of the DME Component Libraries immutable types and enums. In the above example, the Force enum is the only non-standard type. So it is added by calling the addEnumeration method. This will cause the enum to be treated as an integer. If a more complex type needs to be archived, you can implement a custom archiver by deriving from TrackingTypeArchiver.

In most cases, the default archivers simply read and write the underlying numeric properties from the data structure. For example, the Cartesian archiver produces three double values containing X (get), Y (get), and Z (get). Several archivers perform other transformations you may need to be aware of:

Writing to an Archive

After registering an EntityDescriptor<TEntity> for a given entity type, we can create an archive and start writing entities to that archive, as shown in the following code sample:

Java
MemoryArchive<ExampleEntity> archive = new MemoryArchive<>(new TypeLiteral<ExampleEntity>() {}, context);
archive.startWriting();

Any entity of the specified type that is created or modified using the specified TransactionContext will be written to the archive until stopWriting is called.

Retrieving Archived Data

Assuming an archive was created as in the above code sample, data can be retrieved in several ways. The most basic way is to retrieve RawEntityData<TEntity> objects by calling the getArchivedData method. The following code sample takes an entity identifier, start time, stop time, maximum number of records, and a list of properties to retrieve.

Java
Object entityId = "Maverick";
JulianDate startTime = new GregorianDate(2010, 5, 7, 0, 0, 0.0).toJulianDate();
JulianDate stopTime = startTime.addDays(1.0);

MemoryArchive<ExampleEntity> archive = new MemoryArchive<>(new TypeLiteral<ExampleEntity>() {}, context);

RawEntityData<ExampleEntity> rawData =
        archive.getArchivedData(entityId, startTime, stopTime, Integer.MAX_VALUE,
                                CommonEntityInterfaces.IEntityLastUpdate.LastUpdateName,
                                CommonEntityInterfaces.IEntityPosition.PositionName,
                                "SymbolId");

for (int i = 0; i < rawData.getRecordCount(); i++) {
    Object[] values = rawData.getValues(i);
    JulianDate lastUpdate = (JulianDate) values[0];
    Cartesian position = (Cartesian) values[1];
    String symbolId = (String) values[2];
}

The original entity that was archived can then be reconstructed by calling the createEntity method. Note that only the properties which were retrieved from the archive when getArchivedData was called will be set on the entity. To create a complete entity, all properties must be specified.

Java
RawEntityData<ExampleEntity> rawData =
        archive.getArchivedData(entityId, startTime, stopTime, Integer.MAX_VALUE,
                                CommonEntityInterfaces.IEntityIdentifier.EntityIdentifierName,
                                CommonEntityInterfaces.IEntityLastUpdate.LastUpdateName,
                                CommonEntityInterfaces.IEntityPosition.PositionName,
                                CommonEntityInterfaces.IEntityVelocity.VelocityName,
                                "SymbolId",
                                "Affiliation");

context.doTransactionally(Action1.of(transaction -> {
    for (int j = 0; j < rawData.getRecordCount(); j++) {
        ExampleEntity entity = rawData.createEntity(j, transaction);
    }
}));

A DateMotionCollection1<T> can also be constructed from the archive, as shown in the following code sample:

Java
DateMotionCollection1<Cartesian> motions =
        archive.getMotion1(entityId, startTime, stopTime,
                           CommonEntityInterfaces.IEntityPosition.PositionName,
                           CommonEntityInterfaces.IEntityVelocity.VelocityName);

Finally, PointFromArchive<TEntity> and AxesFromArchive<TEntity> are available, which implement Point and Axes, respectively. These classes access data directly from the archive on demand, allowing you to create Platforms and other objects that use archived data for analysis.

Java
PointFromArchive<ExampleEntity> entityPoint = new PointFromArchive<>(new TypeLiteral<ExampleEntity>() {}, archive, entityId);
AxesFromArchive<ExampleEntity> entityAxes = new AxesFromArchive<>(new TypeLiteral<ExampleEntity>() {}, archive, entityId);

Platform platform = new Platform();
platform.setLocationPoint(entityPoint);
platform.setOrientationAxes(entityAxes);