ComparisonPlace.java
package emissary.place;
import emissary.core.DiffCheckConfiguration;
import emissary.core.IBaseDataObject;
import emissary.core.IBaseDataObjectHelper;
import emissary.core.ResourceException;
import emissary.util.PlaceComparisonHelper;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.Collections;
import java.util.List;
/**
* This place takes two other places, gives each place a copy of the received IBDO and compares the output of the two
* places.
* <p>
* NOTE: The configurations for the two places to be compared are used to construct the places internally; however, the
* two places are never registered with the Emissary framework. Therefore, it is only the configuration for this class
* that is registered with the Emissary framework. This means that PLACE_NAME, SERVICE_NAME, SERVICE_PROXY, etc. must
* all be set correctly (and is most likely based on the two places being compared's configurations) in this place's
* configuration in order to execute the two places to be compared correctly.
* <p>
* NOTE: the ibdo and attachments returned by Place A are the ones returned from this class.
* <p>
* The configuration file for this class must contain the five properties defined by the five constants in this class.
*/
public class ComparisonPlace extends ServiceProviderPlace {
/**
* The full pathname for the first class.
*/
public static final String PLACE_A_CLASSNAME = "PLACE_A_CLASSNAME";
/**
* The full pathname for the configuration for the first class.
*/
public static final String PLACE_A_CONFIGNAME = "PLACE_A_CONFIGNAME";
/**
* The full pathname for the second class.
*/
public static final String PLACE_B_CLASSNAME = "PLACE_B_CLASSNAME";
/**
* The full pathname for the configuration for the second class.
*/
public static final String PLACE_B_CONFIGNAME = "PLACE_B_CONFIGNAME";
/**
* An identifier to be added to the log message.
*/
public static final String LOGGING_IDENTIFIER = "LOGGING_IDENTIFIER";
private static final String CONFIG_ERROR_MSG = " must be defined in the configuration file!";
private static final String PROCESS_PROCESSHD_MSG = "Mixed process/processHeavyDuty not allowed!";
private final ServiceProviderPlace placeA;
private final ServiceProviderPlace placeB;
private final String loggingIdentifier;
public ComparisonPlace(final String configFile, final String theDir, final String thePlaceLocation) throws IOException {
super(configFile, theDir, thePlaceLocation);
final String placeAClassName = configG.findStringEntry(PLACE_A_CLASSNAME);
final String placeAConfigName = configG.findStringEntry(PLACE_A_CONFIGNAME);
final String placeBClassName = configG.findStringEntry(PLACE_B_CLASSNAME);
final String placeBConfigName = configG.findStringEntry(PLACE_B_CONFIGNAME);
loggingIdentifier = configG.findStringEntry(LOGGING_IDENTIFIER);
Validate.notNull(placeAClassName, PLACE_A_CLASSNAME + CONFIG_ERROR_MSG);
Validate.notNull(placeAConfigName, PLACE_A_CONFIGNAME + CONFIG_ERROR_MSG);
Validate.notNull(placeBClassName, PLACE_B_CLASSNAME + CONFIG_ERROR_MSG);
Validate.notNull(placeBConfigName, PLACE_B_CONFIGNAME + CONFIG_ERROR_MSG);
Validate.notNull(loggingIdentifier, LOGGING_IDENTIFIER + CONFIG_ERROR_MSG);
placeA = createPlace(placeAClassName, placeAConfigName);
placeB = createPlace(placeBClassName, placeBConfigName);
placeA.shutDown();
placeB.shutDown();
Validate.isTrue(placeA.processMethodImplemented == placeB.processMethodImplemented, PROCESS_PROCESSHD_MSG);
}
@Override
public List<IBaseDataObject> processHeavyDuty(final IBaseDataObject ibdoA) throws ResourceException {
final IBaseDataObject ibdoB = IBaseDataObjectHelper.clone(ibdoA, true);
final List<IBaseDataObject> attachmentsA;
final List<IBaseDataObject> attachmentsB;
if (placeA.processMethodImplemented) {
placeA.process(ibdoA);
placeB.process(ibdoB);
attachmentsA = Collections.emptyList();
attachmentsB = Collections.emptyList();
} else {
attachmentsA = placeA.processHeavyDuty(ibdoA);
attachmentsB = placeB.processHeavyDuty(ibdoB);
}
final String differences = checkDifferences(ibdoA, ibdoB, attachmentsA, attachmentsB, loggingIdentifier);
if (differences != null) {
logDifferences(differences);
}
return attachmentsA;
}
/**
* This method checks for the differences in the output between the two places and can be overridden for custom
* behaviour.
*
* @param ibdoA the IBDO from the first place.
* @param ibdoB the IBDO from the second place.
* @param attachmentsA the list of attachments from the first place.
* @param attachmentsB the list of attachments from the second place.
* @param loggingIdentifier the identifier to be added to the message to be logged.
* @return the differences to be logger or null if there are no differences.
*/
protected String checkDifferences(final IBaseDataObject ibdoA, final IBaseDataObject ibdoB, final List<IBaseDataObject> attachmentsA,
final List<IBaseDataObject> attachmentsB, final String loggingIdentifier) {
return PlaceComparisonHelper.checkDifferences(ibdoB, ibdoA, attachmentsB, attachmentsA, loggingIdentifier,
DiffCheckConfiguration.onlyCheckData());
}
/**
* This method logs the differences in the output between the two places and can be overriden for custom behaviour.
*
* @param differences to be logged.
*/
protected void logDifferences(final String differences) {
logger.info(differences);
}
/**
* This method creates a place given a class name and configuration file.
*
* @param className of the place.
* @param configName of the place.
* @return the place
* @throws IOException if anything goes wrong.
*/
public static final ServiceProviderPlace createPlace(final String className, final String configName) throws IOException {
try {
final Class<?> placeAClass = Class.forName(className);
final Constructor<?> placeAConstructor = placeAClass.getConstructor(String.class, String.class, String.class);
return (ServiceProviderPlace) placeAConstructor.newInstance(null, null, configName);
} catch (Exception e) {
throw new IOException("Unable to create " + className, e);
}
}
}