X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fxmlrouter%2Fimpl%2FXMLRouter.java;h=9c0f2d4937e8ad5ff068da5d97aec56c09efabf5;hb=3b2c669b25bfcb5a3c3f06ff9180d85143bebb2a;hp=652a2ff8a037376bf53e1a026a968120850e8416;hpb=7ace7a8cf3173112717904aa825a7481dd0804e8;p=xmlrouter diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouter.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouter.java index 652a2ff..9c0f2d4 100644 --- a/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouter.java +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouter.java @@ -12,120 +12,92 @@ * 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.wamblee.xmlrouter.impl; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.transform.dom.DOMSource; +import org.wamblee.general.Clock; +import org.wamblee.general.Pair; import org.wamblee.xml.XMLDocument; import org.wamblee.xmlrouter.common.Id; -import org.wamblee.xmlrouter.config.Config; import org.wamblee.xmlrouter.config.DocumentType; import org.wamblee.xmlrouter.config.Filter; import org.wamblee.xmlrouter.config.Transformation; +import org.wamblee.xmlrouter.listener.EventInfo; +import org.wamblee.xmlrouter.listener.EventListener; import org.wamblee.xmlrouter.publish.Gateway; import org.wamblee.xmlrouter.subscribe.Destination; import org.wamblee.xmlrouter.subscribe.DestinationRegistry; -// TODO concurrency. - -public class XMLRouter implements Config, Gateway, DestinationRegistry { +/** + * The XML Router. + * + * @author Erik Brakkee + * + */ +public class XMLRouter implements Gateway, DestinationRegistry { private static final Logger LOGGER = Logger.getLogger(XMLRouter.class .getName()); - private AtomicInteger sequenceNumbers; - private Map documentTypes; - private Transformations transformations; - private Map filters; - private Map destinations; - - public XMLRouter() { - sequenceNumbers = new AtomicInteger(1); - documentTypes = new LinkedHashMap(); - transformations = new Transformations(); - filters = new LinkedHashMap(); - destinations = new LinkedHashMap(); - } - - @Override - public Id addDocumentType(DocumentType aType) { - int seqno = sequenceNumbers.getAndIncrement(); - documentTypes.put(seqno, aType); - return new Id(seqno); - } - - @Override - public void removeDocumentType(Id aId) { - documentTypes.remove(aId); - } - - @Override - public Collection getDocumentTypes() { - return Collections.unmodifiableCollection(documentTypes.values()); - } - - @Override - public Id addTransformation(Transformation aTransformation) { - return transformations.addTransformation(aTransformation); - } + private AtomicLong sequenceNumbers; + private EventListener listener; + private Clock clock; + private AtomicLong nextEventId; - @Override - public void removeTransformation(Id aId) { - transformations.removeTransformation(aId); - } + private XMLRouterConfiguration config; - @Override - public Collection getTransformations() { - return transformations.getTransformations(); - } + private Map, Destination> destinations; - @Override - public Id addFilter(Filter aFilter) { - int seqno = sequenceNumbers.getAndIncrement(); - filters.put(seqno, aFilter); - return new Id(seqno); + public XMLRouter(Clock aClock, XMLRouterConfiguration aConfig, + EventListener aListener) { + sequenceNumbers = new AtomicLong(1); + listener = aListener; + clock = aClock; + nextEventId = new AtomicLong(clock.currentTimeMillis()); + config = aConfig; + destinations = new LinkedHashMap, Destination>(); } @Override - public void removeFilter(Id aId) { - filters.remove(aId); - } + public void publish(String aSource, DOMSource aEvent) { + long time = clock.currentTimeMillis(); - @Override - public Collection getFilters() { - return Collections.unmodifiableCollection(filters.values()); - } + Pair snapshotconfig = config + .getConfig(); - @Override - public boolean publish(String aSource, DOMSource aEvent) { + Id id = new Id(nextEventId.getAndIncrement() + ""); + List types = determineDocumentTypes(snapshotconfig.getFirst() + .documentTypeConfig().values(), aEvent); + EventInfo info = new EventInfo(time, aSource, id, types, aEvent); boolean delivered = false; try { - List filteredInputTypes = determineFilteredInputTypes(aEvent); + List filteredInputTypes = determineFilteredInputTypes( + snapshotconfig.getFirst().filterConfig().values(), types, + aEvent); if (filteredInputTypes.isEmpty()) { if (LOGGER.isLoggable(Level.FINE)) { String doc = new XMLDocument(aEvent).print(true); LOGGER .log( Level.FINE, - "Event ''0}'' from source {1} removed because of filters.", + "Event ''{0}'' from source ''{1}'' removed because of filters.", new Object[] { doc, aSource }); } - return delivered; } // get the reachable target types through transformations. @@ -135,48 +107,54 @@ public class XMLRouter implements Config, Gateway, DestinationRegistry { // This is however certainly not the main case. for (String inputType : filteredInputTypes) { - boolean result = deliverEvent(aSource, aEvent, inputType); + boolean result = deliverEvent(snapshotconfig.getFirst() + .filterConfig().values(), snapshotconfig.getSecond(), info, + inputType); delivered = delivered || result; } } finally { if (!delivered) { destinationNotFound(aSource, aEvent); + listener.notDelivered(info); } - return delivered; } } - private boolean deliverEvent(String aSource, DOMSource aEvent, - String aInputType) { + private boolean deliverEvent(Collection aFilters, + TransformationPaths aTransformations, EventInfo aInfo, String aInputType) { boolean delivered = false; Set possibleTargetTypes = new HashSet(); - possibleTargetTypes.addAll(transformations + possibleTargetTypes.addAll(aTransformations .getPossibleTargetTypes(aInputType)); // ask each destination what target types, if any they want to have. - for (Destination destination : destinations.values()) { + for (Map.Entry, Destination> entry : destinations + .entrySet()) { + Id destinationId = entry.getKey(); + Destination destination = entry.getValue(); Collection requested = destination .chooseFromTargetTypes(possibleTargetTypes); if (!requested.isEmpty()) { // Deliver to the destination. for (String targetType : requested) { - TransformationPath path = transformations.getPath( + TransformationPath path = aTransformations.getPath( aInputType, targetType); List ts = path.getTransformations(); int i = 0; boolean allowed = true; - DOMSource transformed = aEvent; + DOMSource transformed = aInfo.getEvent(); while (i < ts.size() && allowed && transformed != null) { Transformation t = ts.get(i); DOMSource orig = transformed; transformed = t.transform(transformed); if (transformed == null) { - transformationReturnedNull(aSource, aEvent, - aInputType, t, orig); + transformationReturnedNull(aInfo.getSource(), + aInfo.getEvent(), aInputType, t, orig); } - if (!isAllowedByFilters(t.getToType(), transformed)) { + if (!isAllowedByFilters(aFilters, t.getToType(), + transformed)) { allowed = false; } i++; @@ -185,6 +163,8 @@ public class XMLRouter implements Config, Gateway, DestinationRegistry { // all transformations done and all filters still // allow the event. boolean result = destination.receive(transformed); + listener.delivered(aInfo, ts, destinationId.getId(), + result); delivered = delivered || result; } @@ -194,12 +174,13 @@ public class XMLRouter implements Config, Gateway, DestinationRegistry { return delivered; } - private List determineFilteredInputTypes(DOMSource aEvent) { - List types = determineDocumentTypes(aEvent); + private List determineFilteredInputTypes( + Collection aFilters, List aTypes, DOMSource aEvent) { + // apply filters to the input List filteredTypes = new ArrayList(); - for (String type : types) { - boolean allowed = isAllowedByFilters(type, aEvent); + for (String type : aTypes) { + boolean allowed = isAllowedByFilters(aFilters, type, aEvent); if (allowed) { filteredTypes.add(type); } @@ -207,9 +188,10 @@ public class XMLRouter implements Config, Gateway, DestinationRegistry { return filteredTypes; } - private boolean isAllowedByFilters(String aType, DOMSource aEvent) { + private boolean isAllowedByFilters(Collection aFilters, + String aType, DOMSource aEvent) { boolean allowed = true; - for (Filter filter : filters.values()) { + for (Filter filter : aFilters) { if (!filter.isAllowed(aType, aEvent)) { allowed = false; } @@ -217,9 +199,10 @@ public class XMLRouter implements Config, Gateway, DestinationRegistry { return allowed; } - private List determineDocumentTypes(DOMSource aEvent) { + private List determineDocumentTypes( + Collection aTypes, DOMSource aEvent) { List res = new ArrayList(); - for (DocumentType type : documentTypes.values()) { + for (DocumentType type : aTypes) { if (type.isInstance(aEvent)) { res.add(type.getName()); } @@ -227,18 +210,6 @@ public class XMLRouter implements Config, Gateway, DestinationRegistry { return res; } - private void logEvent(String aMessage, String aSource, DOMSource aEvent, - Exception aException) { - LOGGER.log(Level.WARNING, aMessage + ": source '" + aSource + - "': Event: '" + new XMLDocument(aEvent).print(true) + "'", - aException); - } - - private void logEvent(String aMessage, String aSource, DOMSource aEvent) { - LOGGER.log(Level.WARNING, - aMessage + ": " + eventToString(aSource, aEvent)); - } - private String eventToString(String aSource, DOMSource aEvent) { return "source '" + aSource + "': Event: '" + new XMLDocument(aEvent).print(true) + "'"; @@ -260,15 +231,15 @@ public class XMLRouter implements Config, Gateway, DestinationRegistry { @Override public Id registerDestination(Destination aDestination) { notNull("destination", aDestination); - int seqno = sequenceNumbers.getAndIncrement(); - Id id = new Id(seqno); - destinations.put(seqno, new RobustDestination(id, aDestination)); + long seqno = sequenceNumbers.getAndIncrement(); + Id id = new Id(seqno + ""); + destinations.put(id, new RobustDestination(id, aDestination)); return id; } @Override public void unregisterDestination(Id aId) { - destinations.remove(aId.getId()); + destinations.remove(aId); } private void notNull(String aName, Object aValue) {