org.axonframework.eventstore.mongo.EventEntry.java Source code

Java tutorial

Introduction

Here is the source code for org.axonframework.eventstore.mongo.EventEntry.java

Source

/*
 * Copyright (c) 2010-2011. Axon Framework
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.axonframework.eventstore.mongo;

import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;
import org.axonframework.domain.DomainEventMessage;
import org.axonframework.serializer.SerializedDomainEventData;
import org.axonframework.serializer.SerializedDomainEventMessage;
import org.axonframework.serializer.SerializedMetaData;
import org.axonframework.serializer.SerializedObject;
import org.axonframework.serializer.Serializer;
import org.axonframework.serializer.SimpleSerializedObject;
import org.axonframework.upcasting.UpcastSerializedDomainEventData;
import org.axonframework.upcasting.UpcasterChain;
import org.joda.time.DateTime;

import java.util.ArrayList;
import java.util.List;

/**
 * Data needed by different types of event logs.
 *
 * @author Allard Buijze
 * @author Jettro Coenradie
 * @since 2.0 (in incubator since 0.7)
 */
public class EventEntry implements SerializedDomainEventData {

    /**
     * Property name in mongo for the Aggregate Identifier.
     */
    public static final String AGGREGATE_IDENTIFIER_PROPERTY = "aggregateIdentifier";

    /**
     * Property name in mongo for the Sequence Number.
     */
    public static final String SEQUENCE_NUMBER_PROPERTY = "sequenceNumber";

    /**
     * Property name in mongo for the Aggregate's Type Identifier.
     */
    public static final String AGGREGATE_TYPE_PROPERTY = "type";

    /**
     * Property name in mongo for the Time Stamp.
     */
    public static final String TIME_STAMP_PROPERTY = "timeStamp";

    private static final String SERIALIZED_PAYLOAD_PROPERTY = "serializedPayload";
    private static final String PAYLOAD_TYPE_PROPERTY = "payloadType";
    private static final String PAYLOAD_REVISION_PROPERTY = "payloadRevision";
    private static final String META_DATA_PROPERTY = "serializedMetaData";
    private static final String EVENT_IDENTIFIER_PROPERTY = "eventIdentifier";
    /**
     * Mongo object representing the index Events in Mongo.
     */
    public static final BasicDBObject UNIQUE_INDEX = new BasicDBObject(AGGREGATE_IDENTIFIER_PROPERTY, 1)
            .append(AGGREGATE_TYPE_PROPERTY, 1).append(SEQUENCE_NUMBER_PROPERTY, 1);
    /**
     * Charset used for the serialization is usually UTF-8, which is presented by this constant.
     */
    private final String aggregateIdentifier;
    private final long sequenceNumber;
    private final String timeStamp;
    private final String aggregateType;
    private final Object serializedPayload;
    private final String payloadType;
    private final String payloadRevision;
    private final Object serializedMetaData;
    private final String eventIdentifier;

    /**
     * Constructor used to create a new event entry to store in Mongo.
     *
     * @param aggregateType   String containing the aggregate type of the event
     * @param event           The actual DomainEvent to store
     * @param eventSerializer Serializer to use for the event to store
     */
    EventEntry(String aggregateType, DomainEventMessage event, Serializer eventSerializer) {
        this.aggregateType = aggregateType;
        this.aggregateIdentifier = event.getAggregateIdentifier().toString();
        this.sequenceNumber = event.getSequenceNumber();
        this.eventIdentifier = event.getIdentifier();
        Class<?> serializationTarget = String.class;
        if (eventSerializer.canSerializeTo(DBObject.class)) {
            serializationTarget = DBObject.class;
        }
        SerializedObject serializedPayloadObject = eventSerializer.serialize(event.getPayload(),
                serializationTarget);
        SerializedObject serializedMetaDataObject = eventSerializer.serialize(event.getMetaData(),
                serializationTarget);

        this.serializedPayload = serializedPayloadObject.getData();
        this.payloadType = serializedPayloadObject.getType().getName();
        this.payloadRevision = serializedPayloadObject.getType().getRevision();
        this.serializedMetaData = serializedMetaDataObject.getData();
        this.timeStamp = event.getTimestamp().toString();
    }

    /**
     * Creates a new EventEntry based onm data provided by Mongo.
     *
     * @param dbObject Mongo object that contains data to represent an EventEntry
     */
    EventEntry(DBObject dbObject) {
        this.aggregateIdentifier = (String) dbObject.get(AGGREGATE_IDENTIFIER_PROPERTY);
        this.sequenceNumber = (Long) dbObject.get(SEQUENCE_NUMBER_PROPERTY);
        this.serializedPayload = dbObject.get(SERIALIZED_PAYLOAD_PROPERTY);
        this.timeStamp = (String) dbObject.get(TIME_STAMP_PROPERTY);
        this.aggregateType = (String) dbObject.get(AGGREGATE_TYPE_PROPERTY);
        this.payloadType = (String) dbObject.get(PAYLOAD_TYPE_PROPERTY);
        this.payloadRevision = (String) dbObject.get(PAYLOAD_REVISION_PROPERTY);
        this.serializedMetaData = dbObject.get(META_DATA_PROPERTY);
        this.eventIdentifier = (String) dbObject.get(EVENT_IDENTIFIER_PROPERTY);
    }

    /**
     * Returns the actual DomainEvent from the EventEntry using the provided Serializer.
     *
     * @param actualAggregateIdentifier The actual aggregate identifier instance used to perform the lookup, or
     *                                  <code>null</code> if unknown
     * @param eventSerializer           Serializer used to de-serialize the stored DomainEvent
     * @param upcasterChain             Set of upcasters to use when an event needs upcasting before de-serialization
     * @return The actual DomainEventMessage instances stored in this entry
     */
    @SuppressWarnings("unchecked")
    public List<DomainEventMessage> getDomainEvents(Object actualAggregateIdentifier, Serializer eventSerializer,
            UpcasterChain upcasterChain) {
        Class<?> representationType = getRepresentationType();
        List<SerializedObject> upcastObjects = upcasterChain.upcast(
                new SimpleSerializedObject(serializedPayload, representationType, payloadType, payloadRevision));
        List<DomainEventMessage> messages = new ArrayList<DomainEventMessage>(upcastObjects.size());
        for (SerializedObject upcastObject : upcastObjects) {
            messages.add(new SerializedDomainEventMessage(new UpcastSerializedDomainEventData(this,
                    actualAggregateIdentifier == null ? aggregateIdentifier : actualAggregateIdentifier,
                    upcastObject), eventSerializer));
        }
        return messages;
    }

    private Class<?> getRepresentationType() {
        Class<?> representationType = String.class;
        if (serializedPayload instanceof DBObject) {
            representationType = DBObject.class;
        }
        return representationType;
    }

    @Override
    public String getEventIdentifier() {
        return eventIdentifier;
    }

    @Override
    public Object getAggregateIdentifier() {
        return aggregateIdentifier;
    }

    /**
     * getter for the sequence number of the event.
     *
     * @return long representing the sequence number of the event
     */
    public long getSequenceNumber() {
        return sequenceNumber;
    }

    @Override
    public DateTime getTimestamp() {
        return new DateTime(timeStamp);
    }

    @SuppressWarnings("unchecked")
    @Override
    public SerializedObject getMetaData() {
        return new SerializedMetaData(serializedMetaData, getRepresentationType());
    }

    @SuppressWarnings("unchecked")
    @Override
    public SerializedObject getPayload() {
        return new SimpleSerializedObject(serializedPayload, getRepresentationType(), payloadType, payloadRevision);
    }

    /**
     * Returns the current EventEntry as a mongo DBObject.
     *
     * @return DBObject representing the EventEntry
     */
    public DBObject asDBObject() {
        return BasicDBObjectBuilder.start().add(AGGREGATE_IDENTIFIER_PROPERTY, aggregateIdentifier)
                .add(SEQUENCE_NUMBER_PROPERTY, sequenceNumber).add(SERIALIZED_PAYLOAD_PROPERTY, serializedPayload)
                .add(TIME_STAMP_PROPERTY, timeStamp).add(AGGREGATE_TYPE_PROPERTY, aggregateType)
                .add(PAYLOAD_TYPE_PROPERTY, payloadType).add(PAYLOAD_REVISION_PROPERTY, payloadRevision)
                .add(META_DATA_PROPERTY, serializedMetaData).get();
    }

    /**
     * Returns the mongo DBObject used to query mongo for events for specified aggregate identifier and type.
     *
     * @param type                The type of the aggregate to create the mongo DBObject for
     * @param aggregateIdentifier Identifier of the aggregate to obtain the mongo DBObject for
     * @param firstSequenceNumber number representing the first event to obtain
     * @return Created DBObject based on the provided parameters to be used for a query
     */
    public static DBObject forAggregate(String type, String aggregateIdentifier, long firstSequenceNumber) {
        return BasicDBObjectBuilder.start().add(EventEntry.AGGREGATE_IDENTIFIER_PROPERTY, aggregateIdentifier)
                .add(EventEntry.SEQUENCE_NUMBER_PROPERTY, new BasicDBObject("$gte", firstSequenceNumber))
                .add(EventEntry.AGGREGATE_TYPE_PROPERTY, type).get();
    }
}