Interface BarbelHisto<T>

  • Type Parameters:
    T - the type to manage
    All Known Implementing Classes:
    BarbelHistoCore

    public interface BarbelHisto<T>
    The main abstraction of BarbelHisto that provides the client API. Clients should perform all operations with this interface.

    Create an instance as follows:

    BarbelHisto histo = BarbelHistoBuilder.barbel().build();

    Explore BarbelHistoBuilder documentation to learn about the different settings clients can choose.

    BarbelHisto tracks two time dimensions:
    - effective time is when a change to a domain object is supposed to become effective
    - record time is when that change was recorded in the system, when records were created and inactivated

    To manage data with BarbelHisto clients must annotate their classes with DocumentId on the primary key. An example:
     public class SomeBusinessPojo {
        @DocumentId
        private String documentId;
        ... any custom fields and methods
        public String getDocumentId() {
           return documentId;
        }
        public void setDocumentId(String id) {
           this.documentId = id;
        }
     }
     
    The primary key should be business oriented, i.e. personnel number, contract number.

    Two BarbelModes can be used to manage different types of objects: BarbelMode.POJO is the default mode. Of course, using POJO mode is the easiest way forward. However, behind the scenes BarbelHisto uses proxying when managing POJOs to store the version data with the objects that clients save. Proxying can become complicated in some situations. For that reason there is another mode called BarbelMode.BITEMPORAL. One can change the mode to BarbelMode.BITEMPORAL with the BarbelHistoBuilder.withMode(BarbelMode) method like so:
     BarbelHisto barbel = BarbelHistoBuilder.barbel().withMode(BarbelMode.BITEMPORAL).build();
     
    If BarbelMode.BITEMPORAL is used clients have to implement the interface Bitemporal on the type they wish to manage with BarbelHisto. In this mode, there won't be any proxying magic applied to objects. When clients implement the interface Bitemporal they need to declare a field of type BitemporalStamp in the business object type. There is nothing else required than declaring the field. Anything else is managed by BarbelHisto. See DefaultDocument as an example of a fully equipped business class in BarbelMode.BITEMPORAL.

    In any mode clients never have to care about the bitemporal version stamp. This is completely managed by BarbelHisto. Clients only need to take care that their primary key is properly set.

    Use the save(Object, ZonedDateTime, ZonedDateTime) method to save objects to BarbelHisto. The from/until period entered describes when the object data should become effective, and until it should be effective. Clients use EffectivePeriod.INFINITE to express that the object stored is valid until infinite.

    To retrieve data stored into BarbelHisto clients can use retrieveOne(Query) or retrieve(Query). Use the BarbelQueries for convenience like so:
     List result = core.retrieve(BarbelQueries.allActive(someBusinessPojo.getDocumentId()),
                    BarbelQueryOptions.sortAscendingByEffectiveFrom());
     
    Users should become familiar with all the queries in BarbelQueries.

    Clients that use custom data stores like MongoDB or any other of the kind should call unload(Object...) after processing data with BarbelHisto. To restore the journal later to continue bitemporal data processing use load(Collection).

    Use timeshift(Object, ZonedDateTime) to turn back time and see how document journals looked like in the past. Time shift is one of the core functionalities of BarbelHisto. Clients can turn back time to see how the document journals for a document Id looked like at that given time. This knowledge is mission critical for many businesses. Notice that this method returns complete journals of a given document Id. It is often the case that objects effective periods change over time as updates are posted to BarbelHisto with different effective periods. Today a document may have two active effective periods, one period A starting two years ago, and another one period B effective beginning in two weeks, e.g. an adress change to an initial client record that the client communicated two weeks ago.
     Today: 2019-02-01
     Effective from   Effective Until     Created at      Adress
     2017-01-01       2019-02-14          2016-12-15      Barbel-Street 1    Period A
     2019-02-14       Infinite            2019-01-15      Carp-Street 10     Period B
     
    In this example three weeks ago on January 9, 2019 that adress change in question was not recorded to the system. If you turn back time to January 9, 2019 that journal returned by time shift would only contain the effective period A. These cases can get more complex obviously the more updates are posted for a given document Id. Use prettyPrintJournal(Object) to get more familiar with effective periods and record time.


    Author:
    Niklas Schlimm
    • Method Detail

      • save

        BitemporalUpdate<T> save​(T newVersion,
                                 ZonedDateTime from,
                                 ZonedDateTime until)
        Save objects to BarbelHisto. Creates snapshots of state. Clients can safely continue to work on passed instances. Thread safe, applies lock to journals of document IDs (not the complete backbone). This allows concurrent work on different document IDs. If clients try to update the same document Id, this method throws ConcurrentModificationException. The method returns a copy of the object saved including the version data. In in BarbelMode.POJO cast the returned object to Bitemporal to read the version data.
        Parameters:
        newVersion - the object state to save
        from - effective time of object state
        until - effective until of the state
        Returns:
        the BitemporalUpdate performed by this save operation
      • save

        default BitemporalUpdate<T> save​(T newVersion,
                                         EffectivePeriod period)
        Save objects to BarbelHisto. Creates snapshots of state. Clients can safely continue to work on passed instances. Thread safe, applies lock to journals of document IDs (not the complete backbone). This allows concurrent work on different document IDs. If clients try to update the same document Id, this method throws ConcurrentModificationException. The method returns a copy of the object saved including the version data. In in BarbelMode.POJO cast the returned object to Bitemporal to read the version data.
        Parameters:
        newVersion - the object state to save
        period - effective time period of object state
        Returns:
        the BitemporalUpdate performed by this save operation
      • save

        default BitemporalUpdate<T> save​(T newVersion,
                                         ZonedDateTime from)
        Save objects to BarbelHisto. Creates snapshots of state. Clients can safely continue to work on passed instances. Thread safe, applies lock to journals of document IDs (not the complete backbone). This allows concurrent work on different document IDs. If clients try to update the same document Id, this method throws ConcurrentModificationException. The method returns a copy of the object saved including the version data. In in BarbelMode.POJO cast the returned object to Bitemporal to read the version data. This method assumes that the object is effective infinitely, starting from the provided from-Date.
        Parameters:
        newVersion - the object state to save
        from - effective time of object state
        Returns:
        the BitemporalUpdate performed by this save operation
      • save

        default BitemporalUpdate<T> save​(T newVersion)
        Save objects to BarbelHisto. Creates snapshots of state. Clients can safely continue to work on passed instances. Thread safe, applies lock to journals of document IDs (not the complete backbone). This allows concurrent work on different document IDs. If clients try to update the same document Id, this method throws ConcurrentModificationException. The method returns a copy of the object saved including the version data. In in BarbelMode.POJO cast the returned object to Bitemporal to read the version data. This method assumes that the object is effective from now to infinity.
        Parameters:
        newVersion - the object state to save
        Returns:
        the BitemporalUpdate performed by this save operation
      • retrieve

        List<T> retrieve​(com.googlecode.cqengine.query.Query<T> query)
        Retrieve data from BarbelHisto using cqengine like queries. Clients want to use BarbelQueries for there convenience here. BarbelQueries can be combined with additional queries from QueryFactory.
        Parameters:
        query - the client query from BarbelQueries and/or QueryFactory
        Returns:
        the copies returned, maybe empty, never null
      • retrieve

        List<T> retrieve​(com.googlecode.cqengine.query.Query<T> query,
                         com.googlecode.cqengine.query.option.QueryOptions options)
        Retrieve data from BarbelHisto using cqengine like queries. Clients want to use BarbelQueries and BarbelQueryOptions for there convenience here. BarbelQueries can be combined with additional queries from QueryFactory.
        Parameters:
        query - the client query from BarbelQueries and/or QueryFactory
        options - the options from BarbelQueryOptions or QueryFactory
        Returns:
        the copies returned, maybe empty, never null
      • retrieveOne

        T retrieveOne​(com.googlecode.cqengine.query.Query<T> query)
        Retrieve data from BarbelHisto using cqengine like queries. Clients want to use BarbelQueries for there convenience here. BarbelQueries can be combined with additional queries from QueryFactory. Throws IllegalStateException when query returns more then one result, NoSuchElementException if nothing was found.
        Parameters:
        query - the client query from BarbelQueries and/or QueryFactory
        Returns:
        the returned copy
      • timeshift

        DocumentJournal timeshift​(Object id,
                                  ZonedDateTime time)
        Turn back time to see how document journals looked like in the past. If clients pass LocalDateTime.now() the actual journal is returned. Time shift does not change the backbone collection of the BarbelHisto instance, instead it returns an instance of DocumentJournal with copies of managed Bitemporal objects.
        Parameters:
        id - the document Id
        time - the time, must be in the past
        Returns:
        the document journal at that given time
      • prettyPrintJournal

        String prettyPrintJournal​(Object id)
        Pretty print the journal for the given document ID.
        Parameters:
        id - the document ID
        Returns:
        the journal as pretty print out
      • unload

        Collection<Bitemporal> unload​(Object... documentIDs)
        Unloads the journal data of the given document IDs into a collection and return that to the client. The journal data of the given document IDs will be deleted from the backbone. This method is used when client uses custom data store. Clients may store the returned collection to the data store of their choice. Used in conjunction with load(Collection) to re-load that stored journals back into BarbelHisto to continue bitemporal processing.

        In BarbelMode.POJO (default) clients receive a collection of BitemporalVersion objects. In BarbelMode.BITEMPORAL clients receive objects that implement Bitemporal.

        Parameters:
        documentIDs - the document IDs to unload
        Returns:
        the collection of Bitemporal objects to store into an arbitrary data store
        See Also:
        https://github.com/npgall/cqengine
      • contains

        boolean contains​(Object documentId)
        Check if BarbelHisto contains data for the given document ID.
        Parameters:
        documentId - the document id to check
        Returns:
        true if BarbelHisto contains data otherwise false