Package org.axonframework.unitofwork

Source Code of org.axonframework.unitofwork.MetaDataMutatingUnitOfWorkListenerAdapter$MutableDomainEventMessage

/*
* Copyright (c) 2010-2014. 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.unitofwork;

import org.axonframework.domain.AggregateRoot;
import org.axonframework.domain.DomainEventMessage;
import org.axonframework.domain.EventMessage;
import org.axonframework.domain.MetaData;
import org.joda.time.DateTime;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Specialist UnitOfWorkListenerAdapter that allows modification of Meta Data of Events during the "beforeCommit" phase
* of a Unit of Work. This is the phase where all events to publish are known, but haven't been persisted or published
* yet.
*
* @author Allard Buijze
* @since 2.1
*/
public abstract class MetaDataMutatingUnitOfWorkListenerAdapter extends UnitOfWorkListenerAdapter {

    @Override
    public final <T> EventMessage<T> onEventRegistered(UnitOfWork unitOfWork, EventMessage<T> event) {
        return wrapped(event);
    }

    @Override
    public void onPrepareCommit(UnitOfWork unitOfWork, Set<AggregateRoot> aggregateRoots, List<EventMessage> events) {
        int i = 0;
        for (EventMessage<?> event : events) {
            final Map<String, ?> additionalMetaData = assignMetaData(event, events, i++);
            if (additionalMetaData != null) {
                EventMessage<?> changedEvent = event.andMetaData(additionalMetaData);
                if (changedEvent instanceof MutableEventMessage) {
                    ((MutableEventMessage) changedEvent).makeImmutable();
                }
            }
        }
    }

    /**
     * Defines the additional meta data to assign to the given <code>event</code>. For reference, the entire list of
     * <code>events</code> is provided, where the given <code>event</code> can be found at given <code>index</code>.
     * <p/>
     * Any entries returned that already exist are overwritten by the entry in the Map returned. Other entries are
     * added.
     * <p/>
     * This method is invoked for each of the <code>events</code>.
     *
     * @param event  The event for which to assign additional meta data
     * @param events The entire list of events part of this unit of work
     * @param index  The index at which the event can be found in the list of events
     * @return a Map with entries to add to the Meta Data of the given event
     */
    protected abstract Map<String, ?> assignMetaData(EventMessage event, List<EventMessage> events, int index);

    private <T> EventMessage<T> wrapped(EventMessage<T> event) {
        if (event instanceof DomainEventMessage) {
            return new MutableDomainEventMessage<T>((DomainEventMessage<T>) event);
        } else {
            return new MutableEventMessage<T>(event);
        }
    }

    private static class MutableEventMessage<T> implements EventMessage<T> {

        private static final long serialVersionUID = -5697283646053267959L;
        private final EventMessage<T> event;
        private volatile MetaData metaData;
        private volatile boolean fixed;

        public MutableEventMessage(EventMessage<T> event) {
            this.event = event;
            this.metaData = event.getMetaData();
        }

        @Override
        public String getIdentifier() {
            return event.getIdentifier();
        }

        @Override
        public MetaData getMetaData() {
            return metaData;
        }

        @Override
        public T getPayload() {
            return event.getPayload();
        }

        @Override
        public Class getPayloadType() {
            return event.getPayloadType();
        }

        @Override
        public DateTime getTimestamp() {
            return event.getTimestamp();
        }

        @Override
        public EventMessage<T> withMetaData(Map<String, ?> metaData) {
            if (fixed) {
                return event.withMetaData(metaData);
            } else {
                this.metaData = new MetaData(metaData);
                return this;
            }
        }

        @Override
        public EventMessage<T> andMetaData(Map<String, ?> additionalMetaData) {
            if (fixed) {
                return event.withMetaData(this.metaData).andMetaData(additionalMetaData);
            } else {
                Map<String, Object> newMetaData = new HashMap<String, Object>(additionalMetaData);
                newMetaData.putAll(this.metaData);
                this.metaData = new MetaData(newMetaData);
                return this;
            }
        }

        protected EventMessage<T> getWrappedEvent() {
            return event;
        }

        /**
         * Returns the wrapped event, with the meta data currently configured on this instance. This makes sure that
         * an immutable version of the event is actually serialized.
         *
         * @return an immutable representation of the current state of this object
         */
        protected Object writeReplace() {
            return event.withMetaData(metaData);
        }

        public void makeImmutable() {
            this.fixed = true;
        }
    }

    private static class MutableDomainEventMessage<T> extends MutableEventMessage<T> implements DomainEventMessage<T> {

        private static final long serialVersionUID = -1814502500382189837L;

        public MutableDomainEventMessage(DomainEventMessage<T> event) {
            super(event);
        }

        @Override
        public long getSequenceNumber() {
            return getWrappedEvent().getSequenceNumber();
        }

        @Override
        public Object getAggregateIdentifier() {
            return getWrappedEvent().getAggregateIdentifier();
        }

        @Override
        protected DomainEventMessage<T> getWrappedEvent() {
            return (DomainEventMessage<T>) super.getWrappedEvent();
        }

        @Override
        public DomainEventMessage<T> withMetaData(Map<String, ?> metaData) {
            return (DomainEventMessage<T>) super.withMetaData(metaData);
        }

        @Override
        public DomainEventMessage<T> andMetaData(Map<String, ?> additionalMetaData) {
            return (DomainEventMessage<T>) super.andMetaData(additionalMetaData);
        }
    }
}
TOP

Related Classes of org.axonframework.unitofwork.MetaDataMutatingUnitOfWorkListenerAdapter$MutableDomainEventMessage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.