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

net.sf.eBus.messages.ENotificationMessage Maven / Gradle / Ivy

The newest version!
//
// Copyright 2013, 2016, 2019, 2021 Charles W. Rapp
//
// 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 net.sf.eBus.messages;

import java.io.Serializable;
import java.util.Objects;

/**
 * Required base class for all application publish/subscribe
 * notification messages. As of eBus release 5.6.0 this class
 * has two optional fields: {@link #publisherId} and
 * {@link #position}. {@code publisherId} can be used to uniquely
 * define a publisher when there are multiple publishers for
 * the same message key within a system. It is the application's
 * responsibility to define the meaning and uniqueness of
 * publisher identifiers.
 * 

* Position is used to define message ordering when notification * messages are published at a rate faster than wallclock time * granularity. In other words, there are multiple notification * messages per timestamp. If these messages are persisted then * message ordering may be lost on retrieval. The * {@code position} field may be used as an index within a * given time limit to guarantee correct ordering when retrieved * from persistent store. *

*

* Combining {@code subject}, {@code timestamp}, * {@code publisherId}, and {@code position} guarantees a unique * index for any notification message placed into persistent * store if publisher identifier and message position * are correctly used. *

* * @see ERequestMessage * @see EReplyMessage * * @author Charles Rapp */ public abstract class ENotificationMessage extends EMessage implements Serializable { //--------------------------------------------------------------- // Member data. // //----------------------------------------------------------- // Constants. // /** * {@link #publisherId} defaults to {@value} when not set. */ public static final long NO_PUB_ID = 0; /** * Serialization version identifier. */ private static final long serialVersionUID = 0x060000L; //----------------------------------------------------------- // Locals. // /** * Optional field used to define the publisher which * produced this notification. This identifier is set by the * application. eBus has no responsibility in assigning this * value or guaranteeing identifier uniqueness. *

* Therefore the meaning of this identifier is * within the application. If this identifier needs to be * unique between application instances and across networks, * then it is up to developers to guarantee identifier * uniqueness. *

*

* If the publisher identifier is not defined then it * defaults to {@link #NO_PUB_ID}. *

*/ public final long publisherId; /** * This optional field is meant to be used to maintain * notification order when placed in persistent store. The * problem is that system timestamps have a set granularity * (whether millisecond, microsecond, or nanosecond). If more * than one notification message is published within that * timestamp granularity, then message ordering may * be lost when retrieved from persistent store when ordering * by {@link #timestamp} alone. *

* The solution is to combine {@code timestamp} with * {@code position} which is incremented after each * publish. There is one position index per unique * {@link EMessageKey message key} and {@link #publisherId}. * Depending on message publishing rate this position index * should be reset at a fixed rate to prevent the index * from going past {@link Integer#MAX_VALUE} * (2,147,483,647). *

*

* This value defaults to zero when not defined. *

*/ public final int position; //--------------------------------------------------------------- // Member methods. // //----------------------------------------------------------- // Constructors. // /** * Creates a new eBus notification message based on the given * message builder. {@code builder} is guaranteed to contain * a valid message configuration at this point. * @param builder contains the eBus notification message * configuration. */ protected ENotificationMessage(final Builder builder) { super (builder); publisherId = builder.mPubId; position = builder.mPosition; } // end of ENotificationMessage(EMessageBuilder) // // end of Constructors. //----------------------------------------------------------- //----------------------------------------------------------- // Object Method Overrides. // /** * Returns {@code true} if {@code o} is a * non-{@code null ENotificationMessage} instance with a * publisher identifier and position equal to * {@code this ENotificationMessage} instance and * {@code false} otherwise. * @param o comparison object. * @return {@code true} if the message fields are equal * and {@code false} otherwise. */ @SuppressWarnings({"java:S2159"}) @Override public boolean equals(final Object o) { boolean retcode = (this == o); if (!retcode && o instanceof ENotificationMessage) { final ENotificationMessage msg = (ENotificationMessage) o; retcode = (super.equals(msg) && publisherId == msg.publisherId && position == msg.position); } return (retcode); } // end of equals(Object) /** * Returns notification message hash code. * @return notification message hash code. */ @Override public int hashCode() { return (Objects.hash(super.hashCode(), publisherId, position)); } // end of hashCode() /** * Returns notification message publisher ID and position as * a string. * @return notification message publisher ID and position as * a string. */ @Override public String toString() { return ( String.format( "%s%n publisherId: %d%n position: %,d", super.toString(), publisherId, position)); } // end of toString() // // end of Object Method Overrides. //----------------------------------------------------------- //--------------------------------------------------------------- // Inner classes. // /** * Base class for all {@link ENotificationMessage} builders. * Used by eBus when de-serializing an encoded message back * into the target message object. * * @param builds this target message class. * @param message builder subclass. Needed to return the * correct builder type when setting fields. If this were not * the case, field chaining would not work. */ @SuppressWarnings ("unchecked") public abstract static class Builder> extends EMessage.Builder { //----------------------------------------------------------- // Member data. // //------------------------------------------------------- // Locals. // /** * Optional publisher identifier. */ protected long mPubId; /** * Notification message position in feed stream. */ protected int mPosition; //----------------------------------------------------------- // Member methods. // //------------------------------------------------------- // Constructors. // /** * Creates a new notification message builder for the * given message class. * @param targetClass notification message sub-class. */ protected Builder(final Class targetClass) { super (targetClass, MessageType.NOTIFICATION); mPubId = NO_PUB_ID; mPosition = 0; } // end of Builder(Class) /** * Creates a new notification message builder for the * given message class and subject. * @param targetClass notification message sub-class. * @param subject message subject. */ protected Builder(final Class targetClass, final String subject) { super (targetClass, subject, MessageType.NOTIFICATION); mPubId = NO_PUB_ID; mPosition = 0; } // end of Builder(Class, String) // // end of Constructors. //------------------------------------------------------- //------------------------------------------------------- // Set Methods. // /** * Sets publisher identifier to given value. There is no * limitations on {@code id} value. Returns {@code this} * builder configuration so that field configuration may * be chained. * @param id publisher identifier. * @return {@code this} builder instance. */ public final B publisherId(final long id) { mPubId = id; return ((B) this); } // end of publisherId(long) /** * Sets notification position to given value which must * be ≥ zero. Returns {@code this} builder * configuration so that field configuration may be * chained. * @param pos notification message position in feed * publish order. * @return {@code this} builder instance. * @throws IllegalArgumentException * if {@code pos} is < zero. */ public final B position(final int pos) { if (pos < 0) { throw ( new IllegalArgumentException( "position < zero")); } mPosition = pos; return ((B) this); } // end of position(int) // // end of Set Methods. //------------------------------------------------------- } // end of class Builder } // end of class ENotificationMessage




© 2015 - 2024 Weber Informatics LLC | Privacy Policy