/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is OpenEMRConnect.
*
* The Initial Developer of the Original Code is International Training &
* Education Center for Health (I-TECH) <http://www.go2itech.org/>
*
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
package ke.go.moh.oec.reception.controller;
import ke.go.moh.oec.reception.data.Server;
import java.util.logging.Level;
import java.util.logging.Logger;
import ke.go.moh.oec.reception.data.RequestResult;
import ke.go.moh.oec.RequestTypeId;
import ke.go.moh.oec.lib.Mediator;
/**
* The RequestDispatcher class provides a unified way of dispatching OEC client
* requests to OEC servers. See {@link RequestTypeId} in oeclib.
* <p>
* Depending on the {@link RequestDispatcher.DispatchType} and
* {@link Server} specified, it creates and spawns the
* necessary number of {@link RequestDispatchingThread}s to satisfy the requested
* operation.
*
* @author Gitahi Ng'ang'a
*/
public class RequestDispatcher {
public class DispatchType {
/**
* Signals the RequestDispatcher to dispatch a FIND_PERSON request to a
* Person Index or Indices. See {@link MessageTypeRegistry} in oeclib.
* <p>
* This value makes no assumptions about the index or indices to contact.
* That must be specified separately by setting the value {@link Server}
*/
public static final int FIND = 1;
/**
* Signals the RequestDispatcher to dispatch a CREATE_PERSON request to a
* Person Index or Indices. See {@link MessageTypeRegistry} in oeclib.
* <p>
* This value makes no assumptions about the index or indices to contact.
* That must be specified separately by setting the value {@link Server}
*/
public static final int CREATE = 2;
/**
* Signals the RequestDispatcher to dispatch a MODIFY_PERSON request to a
* Person Index or Indices. See {@link MessageTypeRegistry} in oeclib.
* <p>
* This value makes no assumptions about the index or indices to contact.
* That must be specified separately by setting the value {@link Server}
*/
public static final int MODIFY = 3;
/**
* Signals the RequestDispatcher to dispatch a GET_WORK request to the
* CDS. See {@link MessageTypeRegistry} in oeclib.
* <p>
* This value makes no assumptions about the index or indices to contact.
* That must be specified separately by setting the value {@link Server}
*/
public static final int GET_WORK = 4;
/**
* Signals the RequestDispatcher to dispatch a WORK_DONE request to the
* CDS. See {@link MessageTypeRegistry} in oeclib.
* <p>
* This value makes no assumptions about the index or indices to contact.
* That must be specified separately by setting the value {@link Server}
*/
public static final int WORK_DONE = 5;
/**
* Signals the RequestDispatcher to dispatch a REASSIGN request to the
* CDS. See {@link MessageTypeRegistry} in oeclib.
* <p>
* This value makes no assumptions about the index or indices to contact.
* That must be specified separately by setting the value {@link Server}
*/
public static final int REASSIGN = 6;
}
/**
* The Mediator instance used to satisfy a client request
*/
private static final Mediator mediator = new Mediator();
/**
* Dispatches a request of a specific type to a either the MPI, the LPI or both.
* <p>
* If the dispatchType specified is {@link RequestDispatcher.DispatchType#FIND},
* any {@link RequestDispatchingThread}s spawned join the current thread and
* cause this method to wait until they return. Otherwise, if the dispatchType
* specified is {@link RequestDispatcher.DispatchType#CREATE} or
* {@link RequestDispatcher.DispatchType#MODIFY} any {@link RequestDispatchingThread}s
* spawned do not join the current thread and this method returns immediately. Any other
* dispatchType values are ignored and no {@link RequestDispatchingThread}s are started.
* <p>
* Also, the number of {@link RequestDispatchingThread}s spawned depends on the
* {@link Server} specified. Specifically, two {@link RequestDispatchingThread}s
* are spawned for {@link Server#MPI_LPI} and only one otherwise.
*
* @param requestData object containing data for the request
* @param mpiRequestResult object to contain the MPI results of the request
* @param lpiRequestResult object to contain the LPI results of the request
* @param dispatchType the {@link DispatchType} of request to be dispatched
* @param {@link Server} or {@link Server}s to be contacted
*/
public static void dispatch(Object requestData, RequestResult mpiRequestResult,
RequestResult lpiRequestResult, int dispatchType, int targetServer) {
dispatch(requestData, mpiRequestResult, lpiRequestResult, null, dispatchType, targetServer);
}
/**
* Dispatches a FIND_PERSON request to the Kisumu HDSS.
* <p>
* If the dispatchType specified is {@link RequestDispatcher.DispatchType#FIND},
* the {@link RequestDispatchingThread}s spawned joins the current thread and
* causes this method to wait until it returns. Any other dispatchType values
* are ignored and no {@link RequestDispatchingThread}s are started.
*
* @param requestData object containing data for the request
* @param kisumuHdssRequestResult object to contain the Kisumu HDSS results of the request
* @param dispatchType the {@link DispatchType} of request to be dispatched
* @param {@link Server} or {@link Server}s to be contacted
*/
public static void dispatch(Object requestData,
RequestResult kisumuHdssRequestResult, int dispatchType, int targetServer) {
dispatch(requestData, null, null, kisumuHdssRequestResult,dispatchType, targetServer);
}
/**
* This method behaves the same as {@link RequestDispatcher#dispatch(ke.go.moh.oec.reception.controller.Object,
* ke.go.moh.oec.reception.data.RequestResult, ke.go.moh.oec.reception.data.RequestResult, int, int) with the exception
* that no response(s) are expected.
*
* @param requestData object containing data for the request
* @param dispatchType the {@link DispatchType} of request to be dispatched
* @param {@link Server} or {@link Server}s to be contacted
*/
public static void dispatch(Object requestData,
int dispatchType, int targetServer) {
dispatch(requestData, null, null, dispatchType, targetServer);
}
/*
* Forward requests to servers by configuring and spawning the necessary number of
* {@link RequestDispatchingThread}s.
*/
private static void dispatch(Object requestData, RequestResult mpiRequestResult,
RequestResult lpiRequestResult, RequestResult kisumuHdssRequestResult,
int dispatchType, int targetServer) {
boolean join = (dispatchType == DispatchType.FIND);
if (targetServer == Server.MPI_LPI) {
if (dispatchType == DispatchType.FIND) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.FIND_PERSON_MPI, requestData, mpiRequestResult), join);
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.FIND_PERSON_LPI, requestData, lpiRequestResult), join);
} else if (dispatchType == DispatchType.CREATE) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.CREATE_PERSON_MPI, requestData, mpiRequestResult), join);
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.CREATE_PERSON_LPI, requestData, lpiRequestResult), join);
} else if (dispatchType == DispatchType.MODIFY) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.MODIFY_PERSON_MPI, requestData, mpiRequestResult), join);
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.MODIFY_PERSON_LPI, requestData, lpiRequestResult), join);
}
} else if (targetServer == Server.MPI) {
if (dispatchType == DispatchType.FIND) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.FIND_PERSON_MPI, requestData, mpiRequestResult), join);
} else if (dispatchType == DispatchType.CREATE) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.CREATE_PERSON_MPI, requestData, mpiRequestResult), join);
} else if (dispatchType == DispatchType.MODIFY) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.MODIFY_PERSON_MPI, requestData, mpiRequestResult), join);
}
} else if (targetServer == Server.LPI) {
if (dispatchType == DispatchType.FIND) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.FIND_PERSON_LPI, requestData, lpiRequestResult), join);
} else if (dispatchType == DispatchType.CREATE) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.CREATE_PERSON_LPI, requestData, lpiRequestResult), join);
} else if (dispatchType == DispatchType.MODIFY) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.MODIFY_PERSON_LPI, requestData, lpiRequestResult), join);
}
} else if (targetServer == Server.KISUMU_HDSS) {
if (dispatchType == DispatchType.FIND) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.FIND_PERSON_HDSS, requestData, kisumuHdssRequestResult), join);
}
} else if (targetServer == Server.CDS) {
if (dispatchType == DispatchType.GET_WORK) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.GET_WORK, requestData), join);
} else if (dispatchType == DispatchType.WORK_DONE) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.WORK_DONE, requestData), join);
} else if (dispatchType == DispatchType.REASSIGN) {
spawn(new RequestDispatchingThread(
mediator, RequestTypeId.REASSIGN_WORK, requestData), join);
}
}
}
/*
* Spawn a new thread and specify whether or not it should join
* the current one.
*/
private static void spawn(RequestDispatchingThread rdt, boolean join) {
rdt.start();
if (join) {
try {
rdt.join();
} catch (Exception ex) {
Logger.getLogger(RequestDispatcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}