
net.sf.eBus.messages.EReplyMessage Maven / Gradle / Ivy
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this library; if not, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA
// 02111-1307 USA
//
// The Initial Developer of the Original Code is Charles W. Rapp.
// Portions created by Charles W. Rapp are
// Copyright 2013, 2016. Charles W. Rapp
// All Rights Reserved.
//
package net.sf.eBus.messages;
import java.io.Serializable;
/**
* Required base class for all application request messages. Adds
* the message fields reply status, reply reason, and final reply
* flag.
*
* This message is not abstract because it is a complete
* message in its own right and may be used to send a generic
* reply to any request.
*
* Note: messages are limited to 31 fields. This
* is due to eBus binary serialization format. This number is
* decreased to 27 fields for sub-classes because
* {@link EMessage} has two fields: {@code subject} and
* {@code timestamp} and {@code EReplyMessage} has two fields:
* {@link #replyStatus} and {@link #replyReason}.
*
* @see ENotificationMessage
* @see ERequestMessage
*
* @author Charles Rapp
*/
@EFieldInfo (fields = {"replyStatus", "replyReason"})
public class EReplyMessage
extends EMessage
implements Serializable
{
//---------------------------------------------------------------
// Enums.
//
/**
* An eBus reply is limited to either OK (success) or
* ERROR (failure).
*/
public enum ReplyStatus
{
/**
* The request handling is successfully completed.
*/
OK_FINAL (true),
/**
* The request handling is successful, so far. This
* status may change in the future.
*/
OK_CONTINUING (false),
/**
* The request handling failed. There will be no further
* replies.
*/
ERROR (true);
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
/**
* Creates a reply status instance with the given final
* reply flag.
* @param finalReply {@code true} if this status means
* this is a final reply.
*/
private ReplyStatus(final boolean finalReply)
{
_finalReply = finalReply;
} // end of ReplyStatus(boolean)
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// Get Methods.
//
/**
* Returns {@code true} if this is a final reply and
* {@code false} if more replies are expected.
* @return {@code true} if this is a final reply.
*/
public boolean isFinal()
{
return (_finalReply);
} // end of isFinal()
//
// end of Get Methods.
//-------------------------------------------------------
//-----------------------------------------------------------
// Member data.
//
/**
* If {@code true}, then this is the final reply and no
* more replies are expected for this request.
*/
private final boolean _finalReply;
} // end of enum ReplyStatus
//---------------------------------------------------------------
// Member data.
//
//-----------------------------------------------------------
// Constants.
//
/**
* Serialization version identifier.
*/
private static final long serialVersionUID = 0x060100L;
//-----------------------------------------------------------
// Locals.
//
/**
* The current request handling status. If
*/
public final ReplyStatus replyStatus;
/**
* The reason for a {@link ReplyStatus#ERROR} reply status.
* May be {@code null} or empty.
*/
@Optional
public final String replyReason;
//---------------------------------------------------------------
// Member methods.
//
//-----------------------------------------------------------
// Constructors.
//
/**
* Creates a new reply message instance for the given
* subject, status, reason, and final reply flag. The
* timestamp is set to the current system time.
*
* This constructor is public so that this class may be used
* as a generic reply to any request.
* @param subject the message subject.
* @param replyStatus the reply status.
* @param replyReason the reason explaining an error reply
* status. May be {@code null} or empty.
* @throws IllegalArgumentException
* if:
*
* -
* {@code subject} is either of {@code null} or empty;
*
* -
* {@code replyStatus} is {@code null};
*
*
*/
public EReplyMessage(final String subject,
final ReplyStatus replyStatus,
final String replyReason)
throws IllegalArgumentException
{
this (subject,
System.currentTimeMillis(),
replyStatus,
replyReason);
} // end of EReplyMessage(String, ReplyStatus, String)
/**
* Creates a new reply message instance for the given
* subject, timestamp, status, reason, and final reply flag.
* This constructor is used for message de-serialization.
* @param subject the message subject.
* @param timestamp the message timestamp (Java millisecond
* epoch time).
* @param replyStatus the OK or error reply status.
* @param replyReason the reason explaining an error reply
* status. May be {@code null} or empty.
* @throws IllegalArgumentException
* if:
*
* -
* {@code subject} is either of {@code null} or empty;
*
* -
* {@code replyStatus} is {@code null};
*
*
*/
public EReplyMessage(final String subject,
final long timestamp,
final ReplyStatus replyStatus,
final String replyReason)
throws IllegalArgumentException
{
super (subject,
timestamp,
MessageType.REPLY);
if (replyStatus == null)
{
throw (
new IllegalArgumentException(
"null replyStatus"));
}
this.replyStatus = replyStatus;
this.replyReason = replyReason;
} // end of EReplyMessage(...)
//
// end of Constructors.
//-----------------------------------------------------------
//-----------------------------------------------------------
// Object Method Overrides.
//
/**
* Returns {@code true} if {@code o} is a
* non-{@code null EReplyMessage} instance with a reply
* status and reply reason equal to
* {@code this EReplyMessage} instance and {@code false}
* otherwise.
* @param o comparison object.
* @return {@code true} if the message fields are equal
* and {@code false} otherwise.
*/
@Override
public boolean equals(final Object o)
{
boolean retcode = super.equals(o);
if (retcode == false)
{
// no-op.
}
else if (!(o instanceof EReplyMessage))
{
retcode = false;
}
else
{
final EReplyMessage msg = (EReplyMessage) o;
retcode =
(replyStatus == msg.replyStatus &&
(replyReason == null ?
msg.replyReason == null :
replyReason.equals(
msg.replyReason) == true));
}
return (retcode);
} // end of equals(Object)
/**
* Returns the reply message hash code.
* @return the reply message hash code.
*/
@Override
public int hashCode()
{
final int reasonHash =
(replyReason == null ? 0 : replyReason.hashCode());
return (
((((super.hashCode() * 37) +
replyStatus.ordinal()) * 37) +
reasonHash));
} // end of hashCode()
/**
* Returns the message subject, timestamp, and sequence
* number as a string.
* @return the message as text.
*/
@Override
public String toString()
{
return (
String.format(
"%s%n reply status: %s%n reply reason: %s",
super.toString(),
replyStatus,
(replyReason == null ?
"(no reason)" :
replyReason)));
} // end of toString()
//
// end of Object Method Overrides.
//-----------------------------------------------------------
//-----------------------------------------------------------
// Get Methods.
//
/**
* Returns {@code true} if this is the final reply and
* {@code false} if another reply is to be expected.
* @return {@code true} if this is the final reply.
*/
public boolean isFinal()
{
return (replyStatus.isFinal());
} // end of isFinal()
//
// end of Get Methods.
//-----------------------------------------------------------
} // end of class EReplyMessage