
net.sf.eBus.client.ESubscribeFeed Maven / Gradle / Ivy
//
// Copyright 2015, 2016, 2018, 2019 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.client;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.eBus.client.EClient.ClientLocation;
import static net.sf.eBus.client.EFeed.NOTIFY_METHOD;
import net.sf.eBus.messages.EMessageKey;
import net.sf.eBus.messages.ENotificationMessage;
import net.sf.eBus.util.Validator;
/**
* {@code ESubscribeFeed} is the application entry point for
* receiving {@link ENotificationMessage notification messages}.
* Follow these steps to use this feed:
*
* Step 1: Implement the {@link ESubscriber}
* interface.
*
*
* Step 2:
* Use {@link ESubscribeFeed.Builder} to create a subscribe feed
* for a given {@code ESubscriber} instance and
* {@link EMessageKey type+topic message key}. The condition is
* optional and defaults to {@code null}. If provided, then only
* notification messages satisfying the condition are forwarded
* to the subscriber.
*
* Use {@link Builder#statusCallback(FeedStatusCallback)} and
* {@link Builder#notifyCallback(NotifyCallback)} to set Java
* lambda expressions used in place of {@link ESubscriber}
* interface methods.
*
*
*
* Step 3: {@link #subscribe() Subscribe} to the
* open feed.
*
*
* Step 4: Wait for an
* {@link EFeedState#UP up}
* {@link ESubscriber#feedStatus(EFeedState, IESubscribeFeed) feed status}.
* This callback will occur before any notification messages are
* delivered. If the feed state is {@link EFeedState#DOWN down},
* then no notifications will be delivered until the feed state
* comes back up.
*
*
* Step 5: Once the feed state is up, wait for
* {@link ESubscriber#notify(ENotificationMessage, IESubscribeFeed) notification messages}
* to arrive.
*
*
* Step 6: When the subscriber is shutting down,
* {@link #unsubscribe() retract} the subscription and
* {@link #close() close} the feed.
*
* Example use of ESubscribeFeed
* import net.sf.eBus.client.EFeed.FeedScope;
import net.sf.eBus.client.EFeedState;
import net.sf.eBus.client.ESubscribeFeed;
import net.sf.eBus.client.ESubscriber;
import net.sf.eBus.messages.EMessageKey;
import net.sf.eBus.messages.ENotificationMessage;
Step 1: Implement the ESubscriber interface.
public class CatalogSubscriber implements ESubscriber
{
// Subscribe to this notification message class/subject key and feed scope.
private final EMessageKey mKey;
private final FeedScope mScope;
// Store the feed here so it can be used to unsubscribe.
private ESubscribeFeed mFeed;
public CatalogSubscriber(final String subject, final FeedScope scope) {
mKey = new EMessageKey(CatalogUpdate.class, subject);
mScope = scope;
mFeed = null;
}
@Override public void startup() {
try {
Step 2: Open the ESubscribe feed.
// This subscriber has no associated ECondition and uses ESubscriber interface method overrides.
mFeed = (ESubscribeFeed.builder()).target(this)
.messageKey(mKey)
.scope(mScope)
.build();
Step 3: Subscribe to the feed.
mFeed.subscribe();
} catch(IllegalArgumentException argex) {
// Feed open failed. Place recovery code here.
}
}
Step 4: Wait for EFeedState.UP feed status.
@Override public void feedStatus(final EFeedState feedState, final IESubscribeFeed feed) {
// What is the feed state?
if (feedState == EFeedState.DOWN) {
// Down. There are no publishers. Expect no notifications until a
// publisher is found. Put error recovery code here.
} else {
// Up. There is at least one publisher. Expect to receive notifications.
}
}
Step 5: Wait for notifications to arrive.
@Override public void notify(final ENotificationMessage msg, final IESubscribeFeed feed) {
Notification handling code here.
}
@Override public void shutdown() {
Step 6: When subscriber is shutting down, retract subscription feed.
// mFeed.unsubscribe() is not necessary since close() will unsubscribe.
if (mFeed != null) {
mFeed.close();
mFeed = null;
}
}
}
*
*
* @see ESubscriber
* @see EPublisher
* @see EPublishFeed
*
* @author Charles W. Rapp
*/
public final class ESubscribeFeed
extends ENotifyFeed
implements IESubscribeFeed
{
//---------------------------------------------------------------
// Member data.
//
//-----------------------------------------------------------
// Constants.
//
/**
* {@link ESubscriber#feedStatus(EFeedState, IESubscribeFeed)}
* method name.
*/
public static final String FEED_STATUS_METHOD =
"feedStatus";
//-----------------------------------------------------------
// Statics.
//
/**
* Logging subsystem interface.
*/
private static final Logger sLogger =
Logger.getLogger(ESubscribeFeed.class.getName());
//-----------------------------------------------------------
// Locals.
//
/**
* Use this condition to check if the notification message
* should be forwarded to subscriber.
*/
private final ECondition mCondition;
/**
* Feed status callback. If not explicitly set by client,
* then defaults to
* {@link ESubscriber#feedStatus(EFeedState, ESubscribeFeed)}.
*/
// TODO: Make final when open methods are removed.
private FeedStatusCallback mStatusCallback;
/**
* Notification message callback. If not explicity set by
* client, then defaults to
* {@link ESubscriber#notify(ENotificationMessage, ESubscribeFeed)}.
*/
// TODO: Make final when open methods are removed.
private NotifyCallback mNotifyCallback;
//---------------------------------------------------------------
// Member methods.
//
//-----------------------------------------------------------
// Constructors.
//
/**
* Creates a new subscribe feed instance for the given
* client and subject.
* @param client the client making this subscription.
* @param scope the subscription scope.
* @param condition the optional subscription condition.
* May be {@code null}.
* @param subject the subscription is for this notification
* subject.
* @deprecated Please use {@link Builder} to create eBus
* feeds.
*/
@Deprecated
private ESubscribeFeed(final EClient client,
final FeedScope scope,
final ECondition condition,
final ENotifySubject subject)
{
super (client, scope, FeedType.SUBSCRIBE_FEED, subject);
mCondition = condition;
mStatusCallback = null;
mNotifyCallback = null;
} // end of ESubscribeFeed(...)
private ESubscribeFeed(final Builder builder)
{
super (builder);
mCondition = builder.mCondition;
mStatusCallback = builder.getStatusCallback();
mNotifyCallback = builder.getNotifyCallback();
} // end of ESubscribeFeed(Builder)
//
// end of Constructors.
//-----------------------------------------------------------
//-----------------------------------------------------------
// Abstract Method Overrides.
//
@Override
/* package */ int updateActivation(final ClientLocation loc,
final EFeedState fs)
{
boolean updateFlag = false;
int retval = 0;
// Does this feed support the contra-feed's location?
if (mScope.supports(loc))
{
// Yes. Update the activation count based on the
// feed state.
// Increment or decrement?
if (fs == EFeedState.UP)
{
// Increment.
++mActivationCount;
retval = 1;
// Update?
updateFlag = (mActivationCount == 1);
}
// Decrement.
else if (mActivationCount > 0)
{
--mActivationCount;
retval = -1;
// Update?
updateFlag = (mActivationCount == 0);
}
// Did this feed transition between inactivation and
// activation?
if (updateFlag)
{
// Yes. Update the feed.
update(fs);
}
}
// No, this location is not supported. Do not modify the
// activation count.
if (sLogger.isLoggable(Level.FINEST))
{
sLogger.finest(
String.format("%s subscriber %d, feed %d: %s (%s) feed state=%s, activation count=%d (%s), update?=%b -> %d.",
mEClient.location(),
mEClient.clientId(),
mFeedId,
key(),
loc,
fs,
mActivationCount,
mScope,
updateFlag,
retval));
}
return (retval);
} // end of updateActivation(ClientLocation)
/**
* Updates the subscriber feed state. An {@code UP} feed
* state means the publisher may start posting notification
* messages to this feed as long as the publisher's feed
* state is also {@code UP}. Issues a callback to the
* client's feed state callback method.
* @param feedState latest publisher state.
*/
@Override
/* package */ void update(final EFeedState feedState)
{
if (sLogger.isLoggable(Level.FINEST))
{
sLogger.finest(
String.format("%s subscriber %d, feed %d: update feed state=%s.",
mEClient.location(),
mEClient.clientId(),
mFeedId,
feedState));
}
mFeedState = feedState;
// Note: the caller acquired the client dispatch before
// calling this method.
mEClient.dispatch(
new StatusTask<>(feedState, this, mStatusCallback));
} // end of update(EFeedState)
/**
* If the advertisement is in place, then retracts it.
*/
@Override
protected void inactivate()
{
// Retract the subscription in case it is in place.
unsubscribe();
} // end of inactivate()
//
// end of Abstract Method Overrides.
//-----------------------------------------------------------
//-----------------------------------------------------------
// IESubscribeFeed Interface Implementation.
//
/**
* Puts the feed status callback in place. If {@code cb}
* is not {@code null}, feed status updates will be passed
* to {@code cb} rather than
* {@link ESubscriber#feedStatus(EFeedState, IESubscribeFeed)}.
* The reverse is true if {@code cb} is {@code null}. That
* is, a {@code null cb} means feed status updates are
* posted to the
* {@link ESubscriber#feedStatus(EFeedState, IESubscribeFeed)}
* override.
* @param cb the feed status update callback. May be
* {@code null}.
* @throws IllegalStateException
* if this feed is either closed or subscribed.
*/
@Override
public void statusCallback(final FeedStatusCallback cb)
{
if (!mIsActive.get())
{
throw (
new IllegalStateException("feed is inactive"));
}
if (mInPlace)
{
throw (
new IllegalStateException(
"subscription in place"));
}
mStatusCallback = cb;
} // end of statusCallback(FeedStatusCallback<>)
/**
* Puts the notification message callback in place. If
* {@code cb} is not {@code null}, then notification messages
* will be passed to {@code cb} rather than
* {@link ESubscriber#notify(ENotificationMessage, IESubscribeFeed)}.
* A {@code null cb} means that notification messages will be
* passed to the
* {@link ESubscriber#notify(ENotificationMessage, IESubscribeFeed)}
* override.
* @param cb pass notification messages back to application
* via this callback.
* @throws IllegalStateException
* if this feed is either closed or subscribed.
*/
@Override
public void notifyCallback(final NotifyCallback cb)
{
if (!mIsActive.get())
{
throw (
new IllegalStateException("feed is inactive"));
}
if (mInPlace)
{
throw (
new IllegalStateException(
"subscription in place"));
}
mNotifyCallback = cb;
} // end of notifyCallback(NotifyCallback)
/**
* Activates this notification subscription. The caller will
* be asynchronously informed of the current feed state via
* the
* {@link ESubscriber#feedStatus(EFeedState, IESubscribeFeed) feed stateupdate callback method}.
*
* Nothing is done if already subscribed.
*
* @throws IllegalStateException
* if this feed is closed or if the client did not override
* {@link ESubscriber} methods nor put the required callbacks
* in place.
*
* @see #unsubscribe()
* @see EFeed#close()
*/
@Override
public void subscribe()
{
if (!mIsActive.get())
{
throw (
new IllegalStateException("feed is inactive"));
}
if (!mInPlace)
{
// If the feed state and/or notify callbacks are
// not set, then set them to their defaults.
if (mStatusCallback == null)
{
// Did the subscriber override feedStatus?
if (!isOverridden(FEED_STATUS_METHOD,
EFeedState.class,
IESubscribeFeed.class))
{
// No? Gotta do one or the other.
throw (
new IllegalStateException(
FEED_STATUS_METHOD +
" not overridden and statusCallback not set"));
}
// Yes. Use the override method.
mStatusCallback =
((ESubscriber) mEClient.target())::feedStatus;
}
if (mNotifyCallback == null)
{
// Did the subscriber override notify?
if (!isOverridden(NOTIFY_METHOD,
ENotificationMessage.class,
IESubscribeFeed.class))
{
// Nope. Not much point in putting this
// subscription is place.
throw (
new IllegalStateException(
NOTIFY_METHOD +
" not overridden and notifyCallback not set"));
}
if (sLogger.isLoggable(Level.FINER))
{
sLogger.finer(
String.format(
"%s subscriber %d, feed %d: subscribing to %s (%s).",
mEClient.location(),
mEClient.clientId(),
mFeedId,
mSubject.key(),
mScope));
}
mNotifyCallback =
((ESubscriber) mEClient.target())::notify;
}
((ENotifySubject) mSubject).subscribe(this);
// The subscription is now in place.
mInPlace = true;
}
} // end of subscribe()
/**
* De-activates this subscriber feed. Does nothing if this
* feed is not currently subscribed.
*
* Note that the client may still receive notification
* messages which were posted concurrently as this
* unsubscribe.
*
*
* @see #subscribe
* @see EFeed#close()
*/
@Override
public void unsubscribe()
{
// Is the feed subscribed?
if (mInPlace)
{
// Yes. Well, unsubscribe it.
if (sLogger.isLoggable(Level.FINER))
{
sLogger.finer(
String.format("%s subscriber %d, feed %d: unsubscribing from %s (%s).",
mEClient.location(),
mEClient.clientId(),
mFeedId,
mSubject.key(),
mScope));
}
((ENotifySubject) mSubject).unsubscribe(this);
// This feed is no longer subscribed ...
mInPlace = false;
// ... which means there are no more publishers.
mActivationCount = 0;
mFeedState = EFeedState.UNKNOWN;
}
} // end of unsubscribe()
//
// end of IESubscribeFeed Interface Implementation.
//-----------------------------------------------------------
//-----------------------------------------------------------
// Set Methods.
//
/**
* Dispatches {@code msg} to the client if the message passes
* the subscription condition.
* @param msg forward this message to the client if this
* message is acceptable.
*/
/* package */ void notify(final ENotificationMessage msg)
{
// Is the subscription still in place?
if (mInPlace)
{
// Yes. Post this message to the client task queue.
// The notify task will check the subscription
// condition prior to forwarding this message.
// Note: the caller acquired the client dispatch
// before calling this method.
mEClient.dispatch(
new NotifyTask(
msg, mCondition, this, mNotifyCallback));
}
} // end of notify(ENotificationMessage)
//
// end of Set Methods.
//-----------------------------------------------------------
/**
* Returns a new {@code ESubscribeFeed} builder instance.
* This instance should be used to build a single
* notification subscribe feed instance and not used to
* create multiple such feeds.
* @return new notification subscribe feed builder.
*/
public static Builder builder()
{
return (new Builder());
} // end of builder()
/**
* Returns a notification subscriber feed for the specified
* notification message class and subject. The client calls
* {@link #subscribe} on the returned feed in order to
* start receiving the specified notification messages.
* @param client the application object subscribing to the
* notification. May not be {@code null}.
* @param key the notification message class and subject.
* May not be {@code null} and must reference a notification
* message class.
* @param scope whether this subscription feed matches local
* publishers only, remote publishers only, or both. May not
* be {@code null}.
* @param condition accept notification messages only if the
* messages passes this condition. May be {@code null}. If
* {@code null}, then the
* {@link #NO_CONDITION default condition} which accepts all
* messages is used.
* @return the newly created, unplaced, subscribe feed. Must
* call {@link #subscribe()} in order to receive messages.
* @throws NullPointerException
* if {@code client}, {@code key}, or {@code scope} is
* {@code null}.
* @throws IllegalArgumentException
* if {@code client}, {@code key}, or {@code scope} of the
* given parameters is invalid.
* @deprecated Please use {@link Builder} to create eBus
* feeds.
*
* @see #subscribe()
* @see EFeed#close()
*/
@SuppressWarnings ("unchecked")
@Deprecated
public static ESubscribeFeed open(final ESubscriber client,
final EMessageKey key,
final FeedScope scope,
final ECondition condition)
{
validateOpenParams(client, key, scope);
return (open(client,
key,
scope,
condition,
ClientLocation.LOCAL,
false));
} // end of open(ESubscriber,EMessageKey,FeedScope,ECondition)
/**
* Returns a notification subscriber feed for the specified
* notification message class and subject. The client calls
* {@link #subscribe} on the returned feed in order to
* start receiving the specified notification messages.
*
* This method does not parameter validation since this is
* a {@code package private} method.
*
* @param client the application object subscribing to the
* notification. May not be {@code null}.
* @param key the notification message class and subject.
* May not be {@code null} and must reference a notification
* message class.
* @param scope whether this subscription feed matches local
* publishers only, remote publishers only, or both.
* @param cond accept notification messages only if the
* messages passes this condition. May be {@code null}. If
* {@code null}, then the
* {@link #NO_CONDITION default condition} which accepts all
* messages is used.
* @param l {@code client} location.
* @param isMulti {@code true} if this is part of a multiple
* key feed. If {@code true}, this feed is not added to the
* client feed list.
* @return the newly created, unplaced, subscribe feed. Must
* call {@link #subscribe()} in order to receive messages.
*/
/* package */ static ESubscribeFeed open(final ESubscriber client,
final EMessageKey key,
final FeedScope scope,
final ECondition cond,
final ClientLocation l,
final boolean isMulti)
{
// If a null condition was passed in, then use the
// default NO_CONDITION.
final ECondition subCondition =
(cond == null ? NO_CONDITION : cond);
final EClient eClient;
final ENotifySubject subject;
final ESubscribeFeed retval;
// Find or create the eBus client wrapping client.
eClient = EClient.findOrCreateClient(client, l);
// Find or create the notification subject.
subject = ENotifySubject.findOrCreate(key);
// Ready to create the subscribe feed.
retval = new ESubscribeFeed(eClient,
scope,
subCondition,
subject);
// Let the client know it is being referenced by another
// feed - but only if this is not part of a multiple
// key feed. In that case, the multiple key feed is
// added to the client.
if (!isMulti)
{
eClient.addFeed(retval);
}
if (sLogger.isLoggable(Level.FINE))
{
sLogger.fine(
String.format(
"%s subscriber %d, feed %d: opened %s (%s).",
eClient.location(),
eClient.clientId(),
retval.feedId(),
key,
scope));
}
return (retval);
} // end of open(...)
/**
* Verifies that given parameters are not set to {@code null}
* and that {@code key} references a notification message and
* that the message scope and feed scope are in agreement.
* This method is called for effect only.
* @param client subscriber client.
* @param key notification message code.
* @param scope feed scope.
*/
protected static void validateOpenParams(final ESubscriber client,
final EMessageKey key,
final FeedScope scope)
{
// Are the parameters non-null references?
Objects.requireNonNull(client, "client is null");
Objects.requireNonNull(key, "key is null");
Objects.requireNonNull(scope, "scope is null");
// Is the message key for a notification?
if (!key.isNotification())
{
throw (
new IllegalArgumentException(
String.format(
"%s is not a notification message",
key)));
}
// Are the feed scope and message scope in agreement?
checkScopes(key, scope);
} // end of validateOpenParams(...)
//---------------------------------------------------------------
// Inner classes.
//
/**
* {@code ESubscribeFeed.Builder} is now the preferred
* mechanism for creating a {@code ESubscribeFeed} instance.
* A {@code Builder} instance is acquired from
* {@link ESubscribeFeed#builder()}. The following example
* shows how to create a {@code ESubscribeFeed} instance
* using a {@code Builder}. The code assumes that the class
* implements {@code ESubscriber} interface
* {@code feedStatus} method but uses a separate method for
* notification message callback.
* @Override public void startup() {
final EMessageKey key = new EMessageKey(CatalogUpdate.class, subject);
final ESubscribeFeed feed = (ESubscribeFeed.builder()).target(this)
.messageKey(key)
.scope(EFeed.FeedScope.REMOTE_ONLY)
.condition(m -> ((CatalogUpdate) m).category == Category.APPLIANCES)
// Call .statusCallback(lambda expression) to replace feedStatus method
.notifyCallback(this::catalogUpdate)
.build();
...
}
*
* @see #builder()
* @see #open(ESubscriber, EMessageKey, EFeed.FeedScope, ECondition)
*/
public static final class Builder
extends ENotifyFeed.Builder
{
//-----------------------------------------------------------
// Member data.
//
//-------------------------------------------------------
// Locals.
//
/**
* Use this condition to check if the notification message
* should be forwarded to subscriber. Default settings is
* {@link #NO_CONDITION}.
*/
private ECondition mCondition;
/**
* Feed status callback. If not explicitly set by client,
* then defaults to
* {@link ESubscriber#feedStatus(EFeedState, ESubscribeFeed)}.
*/
private FeedStatusCallback mStatusCallback;
/**
* Notification message callback. If not explicity set by
* client, then defaults to
* {@link ESubscriber#notify(ENotificationMessage, ESubscribeFeed)}.
*/
private NotifyCallback mNotifyCallback;
//-----------------------------------------------------------
// Member methods.
//
//-------------------------------------------------------
// Constructors.
//
/**
* Creates a new subscribe feed builder.
*/
private Builder()
{
super (FeedType.SUBSCRIBE_FEED,
ESubscribeFeed.class);
mCondition = NO_CONDITION;
} // end of Builder()
//
// end of Constructors.
//-------------------------------------------------------
//-------------------------------------------------------
// Abstract Method Overrides.
//
/**
* Checks if feed status and notify callbacks are either
* set explicitly or the {@code ESubscriber} methods are
* overridden.
* @param problems place invalid configuration settings
* in this problems list.
* @return {@code problems} to allow for method chaining.
*/
@Override
protected Validator validate(Validator problems)
{
// If the status and notify callbacks are not
// set, then use the interface methods if defined.
// Did the subscriber override feedStatus?
if (mStatusCallback == null &&
mTarget != null &&
isOverridden(FEED_STATUS_METHOD,
EFeedState.class,
IESubscribeFeed.class))
{
// Yes. Use the override method.
mStatusCallback =
((ESubscriber) mTarget)::feedStatus;
}
// Did the subscriber override notify?
if (mNotifyCallback == null &&
mTarget != null &&
isOverridden(NOTIFY_METHOD,
ENotificationMessage.class,
IESubscribeFeed.class))
{
// Yes. Use the override method.
mNotifyCallback =
((ESubscriber) mTarget)::notify;
}
return (super.validate(problems)
.requireTrue((mStatusCallback != null ||
isOverridden(FEED_STATUS_METHOD,
EFeedState.class,
IESubscribeFeed.class)),
"statusCallback",
FEED_STATUS_METHOD +
" not overridden and statusCalback not set")
.requireTrue((mNotifyCallback != null ||
isOverridden(NOTIFY_METHOD,
ENotificationMessage.class,
IESubscribeFeed.class)),
"notifyCallback",
NOTIFY_METHOD +
" not overridden and notifyCallback not set"));
} // end of validate(Validator)
/**
* Returns a new {@code ESubscribeFeed} instance based on
* {@code this Builder}'s configuration.
* @return new notification subscribe feed.
*/
@Override
protected ESubscribeFeed buildImpl()
{
final ESubscribeFeed retval =
new ESubscribeFeed(this);
// Let the client know it is being referenced by another
// feed - but only if this is not part of a multiple
// key feed. In that case, the multiple key feed is
// added to the client.
if (!mIsMultiFlag)
{
mEClient.addFeed(retval);
}
if (sLogger.isLoggable(Level.FINE))
{
sLogger.fine(
String.format(
"%s subscriber %d, feed %d: opened %s (%s).",
mLocation,
mEClient.clientId(),
retval.feedId(),
mKey,
mScope));
}
return (retval);
} // end of buildImpl()
/**
* Returns {@code this} reference.
* @return {@code this} reference.
*/
@Override
protected Builder self()
{
return (this);
} // end of self()
//
// end of Abstract Method Overrides.
//-------------------------------------------------------
//-------------------------------------------------------
// Get Methods.
//
/**
* Returns subscriber feed status callback method.
* @return subscriber feed status callback method.
*/
private FeedStatusCallback getStatusCallback()
{
// Was status callback explicitly defined?
if (mStatusCallback == null)
{
// No. Create a callback to
// ESubscriber.feedStatus() method.
mStatusCallback =
((ESubscriber) mTarget)::feedStatus;
}
return (mStatusCallback);
} // end of getStatusCallback()
/**
* Returns notification callback method.
* @return notification callback method.
*/
private NotifyCallback getNotifyCallback()
{
// Was the notify callback explicitly defined?
if (mNotifyCallback == null)
{
// No. Create a callback to the
// ESubscriber.notify() method.
mNotifyCallback =
((ESubscriber) mTarget)::notify;
}
return (mNotifyCallback);
} // end of getNotifyCallback()
//
// end of Get Methods.
//-------------------------------------------------------
//-------------------------------------------------------
// Set Methods.
//
/**
* Sets subscription condition to the given value. May
* be {@code null} which results in a
* {@link #NO_CONDITION} condition.
*
* An example using this method is:
*
* {@code condition(m -> ((CatalogUpdate) m).category == Category.APPLIANCES)}
* @param condition subscription condition.
* @return {@code this Builder} instance.
*/
public Builder condition(final ECondition condition)
{
if (condition == null)
{
mCondition = NO_CONDITION;
}
else
{
mCondition = condition;
}
return (this);
} // end of condition(ECondition)
/**
* Puts the subscribe feed status callback in place. If
* {@code cb} is not {@code null}, subscribe status
* updates will be passed to {@code cb} rather than
* {@link ESubscriber#feedStatus(EFeedState, IESubscribeFeed)}.
* The reverse is true, if {@code cb} is {@code null},
* then updates are posted to the
* {@link ESubscriber#feedStatus(EFeedState, IESubscribeFeed)}
* override.
*
* An example using this method is:
*
* statusCallback(
(fs, f) ->
{
if (fs == EFeedState.DOWN) {
// Clean up in-progress work.
}
}
* @param cb subscribe status update callback. May be
* {@code null}.
* @return {@code this Builder} instance.
*/
public Builder statusCallback(FeedStatusCallback cb)
{
mStatusCallback = cb;
return (this);
} // end of statusCallback(FeedStatusCallback<>)
/**
* Puts the notification message callback in place. If
* {@code cb} is not {@code null}, then notification
* messages will be passed to {@code cb} rather than
* {@link ESubscriber#notify(ENotificationMessage, IESubscribeFeed)}.
* A {@code null cb} means that notification messages will be
* passed to the
* {@link ESubscriber#notify(ENotificationMessage, IESubscribeFeed)}
* override.
*
* An example showing how to use this method is:
* {@code notifyCallback(this::locationUpdate)}
*
* @param cb pass notification messages back to target
* via this callback.
* @return {@code this Builder} instance.
*/
public Builder notifyCallback(final NotifyCallback cb)
{
mNotifyCallback = cb;
return (this);
} // end of notifyCallback()
//
// end of Set Methods.
//-------------------------------------------------------
} // end of class Builder
} // end of class ESubscribeFeed