/** * Dispatcher.java * * Copyright 2012 Niolex, Inc. * * Niolex licenses this file to you 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 org.apache.niolex.commons.seda; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * The dispatcher used to dispatch messages into the next stage. * Every dispatcher is independent from each other, construct the stages * before start to use the dispatcher. Once it's running, do not add any * stage into the dispatcher. * * @author <a href="mailto:xiejiyun@gmail.com">Xie, Jiyun</a> * @version 1.0.0, $Date: 2012-11-16$ */ public class Dispatcher { /** * the global instance. */ private static final Dispatcher INSTANCE = new Dispatcher(); /** * The internal stage map. */ private final Map<String, Stage<?>> stageMap = new HashMap<String, Stage<?>>(); /** * The adjuster used to adjust all the stages in this dispatcher. */ private Adjuster adjuster; /** * Get the global instance. * * @return the global instance */ public static final Dispatcher getInstance() { return INSTANCE; } /** * Register a stage with it's stage name. * <br><b> * Call this method before dispatch messages. * </b> * * @param stage the stage to register. * @return the previous value associated with this stage name, or null if there was no mapping * for this stage name. */ public Stage<?> register(Stage<?> stage) { return stageMap.put(stage.getStageName(), stage); } /** * Get the stage with this stage name. * * @param <K> the stage type * @param stageName the stage name of the stage you want to get. * @return the stage instance, null if stage not found. * @throws ClassCastException If the type of the corresponding stage is not the same * as your parameter class. */ @SuppressWarnings("unchecked") public <K extends Stage<?>> K getStage(String stageName) { return (K) stageMap.get(stageName); } /** * When all the stages are set, user need to call this method to construct * the stage network. * <br><b> * Call this method before dispatch messages. * </b> */ public void construction() { for (Stage<?> s : this.getAllStages()) { s.construct(); } } /** * Start to adjust all the stages in this dispatcher. * * @param adjustInterval the adjust interval. */ public synchronized void startAdjust(int adjustInterval) { if (adjuster == null) { adjuster = new Adjuster(); for (Stage<?> s : this.getAllStages()) { adjuster.addStage(s); } } adjuster.setAdjustInterval(adjustInterval); adjuster.startAdjust(); } /** * Shutdown all the stages in this dispatcher. We will stop the * adjuster if there is one. */ public synchronized void shutdown() { for (Stage<?> s : this.getAllStages()) { s.shutdown(); } if (adjuster != null) { adjuster.stopAdjust(); adjuster = null; } } /** * Clear all the stages in this dispatcher. */ public void clear() { stageMap.clear(); } /** * Dispatch the specified message to the stage with this specified stage name. * * @param <T> the message type * @param stageName the name of the stage you want to dispatch this message to * @param msg the message to be dispatched * @return true if dispatch success, false if stage not found * @throws ClassCastException if this message can not be processed by the corresponding stage */ public <T extends Message> boolean dispatch(String stageName, T msg) { @SuppressWarnings("unchecked") Stage<T> stage = (Stage<T>) stageMap.get(stageName); if (stage != null) { stage.addInput(msg); return true; } else { return false; } } /** * Dispatch the specified message to the stage with the class name of this message * as the stage name. * * @param <T> the message type * @param msg the message to be dispatched * @return true if dispatch success, false if stage not found * @throws ClassCastException If this message can not be processed by the corresponding stage */ public <T extends Message> boolean dispatch(T msg) { return dispatch(msg.getClass().getName(), msg); } /** * Get all the stages in this dispatcher. * * @return the stages collection */ public Collection<Stage<?>> getAllStages() { return stageMap.values(); } }