+package org.wamblee.xmlrouter.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.transform.dom.DOMSource;
+
+import org.wamblee.xml.XMLDocument;
+import org.wamblee.xmlrouter.common.Id;
+import org.wamblee.xmlrouter.subscribe.Destination;
+
+/**
+ * Provides robustness for the use of externally provided destinations by
+ * catching null return values and exceptions and providing usable default
+ * return values.
+ *
+ * @author Erik Brakkee
+ *
+ */
+public class RobustDestination implements Destination {
+
+ private static final Logger LOGGER = Logger
+ .getLogger(RobustDestination.class.getName());
+
+ private Id<Destination> id;
+ private Destination destination;
+
+ public RobustDestination(Id<Destination> aId, Destination aDestination) {
+ id = aId;
+ destination = aDestination;
+ }
+
+ @Override
+ public String getName() {
+ try {
+ String res = destination.getName();
+ if (res == null) {
+ logNameReturnedNull();
+ return Constants.UNKNOWN_DESTINATION_NAME.toString();
+ }
+ return res;
+ } catch (Exception e) {
+ logNameThrewException(e);
+ return Constants.UNKNOWN_DESTINATION_NAME.toString();
+ }
+ }
+
+ @Override
+ public Collection<String> chooseFromTargetTypes(
+ Collection<String> aPossibleTargetTypes) {
+ try {
+ Collection<String> res = destination
+ .chooseFromTargetTypes(aPossibleTargetTypes);
+ if (res == null) {
+ logChooseFromTargetTypesReturnedNull(aPossibleTargetTypes);
+ return Collections.EMPTY_LIST;
+ }
+ Collection<String> finalRes = new ArrayList<String>();
+ for (String type : res) {
+ if (!aPossibleTargetTypes.contains(type)) {
+ logChooseFromTargetTypesReturnedInvalidType(
+ aPossibleTargetTypes, type);
+ } else {
+ finalRes.add(type);
+ }
+ }
+ return finalRes;
+ } catch (Exception e) {
+ logChooseFromTargetTypesThrewException(aPossibleTargetTypes, e);
+ return Collections.EMPTY_LIST;
+ }
+ }
+
+ @Override
+ public boolean receive(DOMSource aEvent) {
+ try {
+ return destination.receive(aEvent);
+ } catch (Exception e) {
+ logReceiveThrewException(aEvent, e);
+ return false;
+ }
+ }
+
+ private void logNameThrewException(Exception aE) {
+ LOGGER.log(Level.WARNING,
+ "getName() threw exception for destination id " + id +
+ " returning name " + Constants.UNKNOWN_DESTINATION_NAME +
+ " instead", aE);
+ }
+
+ private void logNameReturnedNull() {
+ LOGGER.log(Level.WARNING,
+ "getName() returned null for destination id " + id +
+ " returning name " + Constants.UNKNOWN_DESTINATION_NAME +
+ " instead");
+ }
+
+ private void logChooseFromTargetTypesReturnedInvalidType(
+ Collection<String> aPossibleTargetTypes, String aType) {
+ LOGGER
+ .log(
+ Level.WARNING,
+ "chooseFromTargetTypes() for destination {0} returned invalid type ''{1}'' which is not in the offered set of types {2}",
+ new Object[] { id, aType, aPossibleTargetTypes.toString() });
+ }
+
+ private void logChooseFromTargetTypesReturnedNull(
+ Collection<String> aPossibleTargetTypes) {
+ LOGGER.log(Level.WARNING,
+ "chooseFromTargetTypes() returned null for destination " + id);
+ }
+
+ private void logChooseFromTargetTypesThrewException(
+ Collection<String> aPossibleTargetTypes, Exception aE) {
+ LOGGER
+ .log(
+ Level.WARNING,
+ "chooseFromTargetTypes() threw exception for destination " + id,
+ aE);
+ }
+
+ private void logReceiveThrewException(DOMSource aEvent, Exception aE) {
+ LOGGER.log(Level.WARNING, "Receive threw exception for destination " +
+ id + " for event " + new XMLDocument(aEvent).print(true), aE);
+ }
+
+}