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

ar.com.zauber.commons.async.AbstractJoiner Maven / Gradle / Ivy

There is a newer version: 3.55
Show newest version
/**
 * Copyright (c) 2005-2015 Zauber S.A. 
 *
 * 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 ar.com.zauber.commons.async;

import java.util.ArrayList;
import java.util.Collection;

import ar.com.zauber.commons.validate.Validate;

/**
 * An abstract skeleton implementation of {@link Joiner} that defines templates method
 * that will be called every time the joiner is notified.
 * 
 * 

* This class is thread safe *

* * @param The type of object to be joined. * @param The type of failed flows. * @author Guido Marucci Blas * @since Apr 20, 2011 */ public abstract class AbstractJoiner implements Joiner { private final Collection succededObjects; private final Collection> failedTasks; private final int expectedNotifications; private int failureNotifications = 0; /** * Creates the AbstractJoiner. * * @param expectedNotifications The amount of expected notifications. Must be a positive number. * @param succededObjects A collection were the succeeded objects will be added. May be null. * @param failedTasks A collection were the failed tasks will be added. May be null. * @throws IllegalArgumentException if expectedNotifications is not a positive number. */ public AbstractJoiner( final int expectedNotifications, final Collection succededObjects, final Collection> failedTasks) { if (expectedNotifications < 1) { throw new IllegalArgumentException(String.format( "The amount of expected notifications must be a positive number. %d was given", expectedNotifications)); } this.expectedNotifications = expectedNotifications; this.succededObjects = (succededObjects == null) ? new ArrayList(expectedNotifications) : succededObjects; this.failedTasks = (failedTasks == null) ? new ArrayList>(expectedNotifications) : failedTasks; } /** * Creates the AbstractJoiner. * * @param expectedNotifications The amount of expected notifications. Must be a positive number. * @param succededObjects A collection were the succeeded objects will be added. May be null. * @throws IllegalArgumentException if expectedNotifications is not a positive number. */ public AbstractJoiner(final int expectedNotifications, final Collection succededObjects) { this(expectedNotifications, succededObjects, null); } /** * Creates the AbstractJoiner. * * @param expectedNotifications The amount of expected notifications. Must be a positive number. * @throws IllegalArgumentException if expectedNotifications is not a positive number. */ public AbstractJoiner(final int expectedNotifications) { this(expectedNotifications, null, null); } @Override public final synchronized void notifySuccess(final T object) { Validate.notNull(object, "The object to be joined cannot be null"); if (getRemainingNotificationsCount() == 0) { throw new IllegalStateException("All the expected notification have been received."); } succededObjects.add(object); onSuccessNotification(object); notificationHandler(); } @Override public final synchronized void notifyFailure() { if (getRemainingNotificationsCount() == 0) { throw new IllegalStateException("All the expected notification have been received."); } ++failureNotifications; onFailureNotification(null, null); notificationHandler(); } @Override public final synchronized void notifyFailure(final Throwable t) { notifyFailure(null, t); } @Override public final synchronized void notifyFailure(final F failedTask, final Throwable t) { Validate.notNull(t, "The failed task cannot be null"); if (getRemainingNotificationsCount() == 0) { throw new IllegalStateException("All the expected notification have been received."); } failedTasks.add(new DefaultFailedTask(failedTask, t)); ++failureNotifications; onFailureNotification(failedTask, t); notificationHandler(); } @Override public final synchronized int getSuccessfulNotificationsCount() { return succededObjects.size(); } @Override public final synchronized int getFailureNotificationsCount() { return failureNotifications; } @Override public final synchronized int getExpectedNotificationsCount() { return expectedNotifications; } @Override public final synchronized int getRemainingNotificationsCount() { return expectedNotifications - getSuccessfulNotificationsCount() - getFailureNotificationsCount(); } @Override public final synchronized boolean hasFailureNotifications() { return getFailureNotificationsCount() != 0; } @Override public final synchronized boolean isWaitingForNotifications() { return getRemainingNotificationsCount() != 0; } @Override public final synchronized Collection joinedObjects() { return new ArrayList(succededObjects); } @Override public final synchronized Collection> failedTasks() { return new ArrayList>(failedTasks); } /** * Template method that will be called when a success notification is received. * * @param object The joined object. Cannot be null. */ protected abstract void onSuccessNotification(final T object); /** * Template method that will be called when a failure notification is received. * * @param failedTask The failed task. May be null. * @param t The cause of failure. May be null in which case failedTask is null. */ protected abstract void onFailureNotification(final F failedTask, final Throwable t); /** * Template method that will be called when all the notification have been received. */ protected abstract void onAllNotificationsReceived(); /** * Commons actions that need to be done when a notification has been received are * handled by this method. */ private void notificationHandler() { if (!isWaitingForNotifications()) { onAllNotificationsReceived(); } } /** * Default immutable implementation of {@link FailedTask} * * @author Guido Marucci Blas * @since Apr 20, 2011 */ protected static final class DefaultFailedTask implements FailedTask { private final F failedTask; private final Throwable t; /** * Creates the DefaultFailedTask. * * @param failedTask The failed task. May be null. * @param t The cause of the failed task. Cannot be null. * @throws IllegalArgumentException if t is null. */ public DefaultFailedTask(final F failedTask, final Throwable t) { Validate.notNull(t, "The cause cannot be null"); this.failedTask = failedTask; this.t = t; } @Override public F getFailedTask() { return failedTask; } @Override public Throwable getCause() { return t; } @Override public boolean hasFailedTasks() { return failedTask != null; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy