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

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

There is a newer version: 7.6.0
Show newest version
//
// Copyright 2013, 2016 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;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.sf.eBus.util.Validator;

/**
 * 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 */ public class EReplyMessage extends EMessage implements Serializable { //--------------------------------------------------------------- // Enums. // /** * An eBus reply is limited to either {@code OK} (success), * {@code OK_CONTINUING} (in-progress reply with more to * come), {@code CANCELED} (terminated before completion), * {@code CANCEL_REJECT} (cancel request rejected), and * {@code ERROR} (failure to process request and request is * terminated). */ 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 is terminated either due to a * cancel request or the replier unilaterally canceling * the request. */ CANCELED (true), /** * An optional cancel request is rejected and the replier * is still working the request. Repliers are not * required to respond to a cancel request with this * status but it is considered good programming to do so. */ CANCEL_REJECT (false), /** * The request handling failed. There will be no further * replies. */ ERROR (true); //----------------------------------------------------------- // Member data. // //------------------------------------------------------- // Locals. // /** * If {@code true}, then this is the final reply and no * more replies are expected for this request. */ private final boolean mFinalReply; //----------------------------------------------------------- // 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) { mFinalReply = 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 (mFinalReply); } // end of isFinal() // // end of Get Methods. //------------------------------------------------------- } // end of enum ReplyStatus //--------------------------------------------------------------- // Member data. // //----------------------------------------------------------- // Constants. // /** * Serialization version identifier. */ private static final long serialVersionUID = 0x060000L; //----------------------------------------------------------- // Locals. // /** * The current request handling status. If * {@link ReplyStatus#ERROR}, then {@link #replyReason} will * contain text explaining why the request was rejected. *

* This field is displayed first. *

*/ @FieldDisplayIndex (index = 0) public final ReplyStatus replyStatus; /** * The reason for a {@link ReplyStatus#ERROR} reply status. * May be {@code null} or empty. *

* This field is displayed second. *

*/ @FieldDisplayIndex (index = 1) @Nullable public final String replyReason; //--------------------------------------------------------------- // Member methods. // //----------------------------------------------------------- // Constructors. // /** * Creates a new eBus reply message based on the given reply * message builder. {@code builder} is guaranteed to contain * a valid message configuration at this point. * @param builder contains the reply message configuration. */ protected EReplyMessage(final Builder builder) { super (builder); this.replyStatus = builder.mReplyStatus; this.replyReason = builder.mReplyReason; } // end of EReplyMessage(EReplyMessageBuilder) // // 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. */ @SuppressWarnings({"java:S2159"}) @Override public boolean equals(final Object o) { boolean retcode = super.equals(o); if (!retcode) { // 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))); } return (retcode); } // end of equals(Object) /** * Returns the reply message hash code. * @return the reply message hash code. */ @Override public int hashCode() { return (Objects.hash(super.hashCode(), replyStatus, replyReason)); } // 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. //----------------------------------------------------------- /** * Returns the {@code EReplyMessage} builder. * @return {@link EReplyMessage.Builder} instance. */ @SuppressWarnings({"java:S1452"}) public static EReplyMessage.Builder builder() { return (new ConcreteBuilder()); } // end of builder() //--------------------------------------------------------------- // Inner classes. // /** * Base class for all {@link EReplyMessage} 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. // /** * Reply is either OK but continuing, OK and final, and * error (which is always final). Must be set. */ @Nonnull protected ReplyStatus mReplyStatus; /** * Generally text explaining a error status. May be * {@code null} or an empty string. */ @Nullable protected String mReplyReason; //----------------------------------------------------------- // Member methods. // //------------------------------------------------------- // Constructors. // protected Builder(final Class targetClass) { super (targetClass, MessageType.REPLY); } // end of Builder(Class) // // end of Constructors. //------------------------------------------------------- //------------------------------------------------------- // Abstract Method Overrides. // /** * Checks if reply status is set. Note that the reply * reason is not required to be set; it may be * {@code null} or an empty string. * @param problems used to check field validity and * collect discovered invalid fields. * @return {@code problems} to allow for method chaining. */ @Override protected Validator validate(final Validator problems) { return (super.validate(problems) .requireNotNull(mReplyStatus, "reply status")); } // end of validate(Validator) // // end of Abstract Method Overrides. //------------------------------------------------------- //------------------------------------------------------- // Set Methods. // /** * Sets the replier status for the matching request. * @param status replier status. * @return {@code this} builder instance. * @throws NullPointerException * if {@code status} is {@code null}. */ public final B replyStatus(final ReplyStatus status) { mReplyStatus = Objects.requireNonNull(status, "status is null"); return ((B) this); } // end of replyStatus(ReplyStatus) /** * Sets the reply status reason. Generally used to * explain a {@link ReplyStatus#ERROR error} status. * {@code reason} may be {@code null} or an empty string. * @param reason reply status reason. * @return {@code this} builder instance. */ public final B replyReason(final String reason) { mReplyReason = reason; return ((B) this); } // end of replyReason(String) // // end of Set Methods. //------------------------------------------------------- } // end of class EReplyMessageBuilder /** * Since {@code EReplyMessage} is not abstract and may be * instantiated as a concrete message, this builder is used * to create an {@code EReplyMessage} instance. */ public static final class ConcreteBuilder extends EReplyMessage.Builder { //----------------------------------------------------------- // Member data. // //----------------------------------------------------------- // Member methods. // //------------------------------------------------------- // Constructors. // private ConcreteBuilder() { super (EReplyMessage.class); } // end of ConcreteBuilder() // // end of Constructors. //------------------------------------------------------- //------------------------------------------------------- // Abstract Method Overrides. // @Override protected EReplyMessage buildImpl() { return (new EReplyMessage(this)); } // end of buildImpl() // // end of Abstract Method Overrides. //------------------------------------------------------- } // end of class ConcreteBuilder } // end of class EReplyMessage




© 2015 - 2025 Weber Informatics LLC | Privacy Policy