/*******************************************************************************
* Copyright (c) 2009 MATERNA Information & Communications. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html. For further
* project-related information visit http://www.ws4d.org. The most recent
* version of the JMEDS framework can be obtained from
* http://sourceforge.net/projects/ws4d-javame.
******************************************************************************/
package org.ws4d.java.dispatch;
import org.ws4d.java.message.Message;
import org.ws4d.java.structures.ArrayList;
import org.ws4d.java.structures.HashMap;
import org.ws4d.java.structures.HashMap.Entry;
import org.ws4d.java.structures.Iterator;
import org.ws4d.java.structures.List;
import org.ws4d.java.types.EndpointReference;
import org.ws4d.java.types.URI;
/**
* This class allows matching messages according to their
* {@link Message#getType() message type} or the {@link Message#getTo() address
* of the endpoint} they are addressed to.
* <p>
* Selection criteria can be specified in a generic way by means of the
* {@link #setSelectionProperty(int, List)} method. This method allows
* declaration of expected values for each property in question. A message will
* match those criteria only if it has matching values for all the given
* properties.
* </p>
*/
public class DefaultMessageSelector implements MessageSelector {
/**
* Property denoting a selection based on the message type.
*/
public static final int MESSAGE_TYPE = 1;
/**
* Property denoting a selection based on the target
* {@link EndpointReference endpoint reference} of the message (i.e. its
* WS-Addressing [destination] property). The [destination] property is
* actually an IRI consisting of the [address] property of the target's
* endpoint reference. Nevertheless, when specifying a selection rule by
* means of {@link #setSelectionProperty(int, List)} method, the provided
* {@link List} <code>values</code> is expected to contain
* {@link EndpointReference} instances rather than {@link URI}s.
*/
public static final int ENDPOINT_REFERENCE = 2;
// key = Integer (property type), value = list of acceptable property values
private final HashMap selectionRules = new HashMap();
private static boolean isKnownPropertyType(int propertyType) {
return MESSAGE_TYPE == propertyType || ENDPOINT_REFERENCE == propertyType;
}
/**
* Create a new default message selector.
*/
public DefaultMessageSelector() {
super();
}
/*
* (non-Javadoc)
* @see org.ws4d.java.communication.MessageSelector#matches(org.ws4d.
* java.communication.message.DPWSMessage)
*/
public synchronized boolean matches(Message msg) {
boolean result = true;
for (Iterator it = selectionRules.entrySet().iterator(); it.hasNext();) {
Entry ent = (Entry) it.next();
int propertyType = ((Integer) ent.getKey()).intValue();
List values = (List) ent.getValue();
if (values == null || values.size() == 0) {
continue;
}
// realize intersection semantics
switch (propertyType) {
case (MESSAGE_TYPE): {
int msgType = msg.getType();
boolean typeMatches = false;
for (Iterator it2 = values.iterator(); it2.hasNext();) {
Integer requestedMsgType = (Integer) it2.next();
if (msgType == requestedMsgType.intValue()) {
typeMatches = true;
break;
}
}
result &= typeMatches;
break;
}
case (ENDPOINT_REFERENCE): {
// FIXME get the appropriate ER!!!
EndpointReference endpointReference = new EndpointReference(msg.getTo());
boolean refMatches = false;
for (Iterator it2 = values.iterator(); it2.hasNext();) {
EndpointReference requestedEndpointReference = (EndpointReference) it2.next();
if (endpointReference.equals(requestedEndpointReference)) {
refMatches = true;
break;
}
}
result &= refMatches;
break;
}
}
}
return result;
}
/**
* Adds a <em>"selection rule"</em> by specifying a message
* <code>property</code> and declaring a list of allowed <code>values</code>
* for this property. Each message, which has a value for this property that
* is contained within <code>values</code>, will be considered for a match.
* In case the provided list of <code>values</code> is <code>null</code> or
* empty, a message will always match regardless of its actual value for the
* property.
* <p>
* Calling this method more than once with the same <code>property</code>
* but different <code>values</code> overwrites (i.e. replaces) previously
* specified <code>values</code> for that property.
* </p>
*
* @param property the property to set expected values for; allowed values
* are {@link #MESSAGE_TYPE} and {@link #ENDPOINT_REFERENCE}
* @param values a list of values the <code>property</code> may take in
* order to get matched by this selector; if empty, then any
* value of the property would match
* @throws IllegalArgumentException if <code>propertyType</code> is neither
* {@link #MESSAGE_TYPE} nor {@link #ENDPOINT_REFERENCE}
*/
public synchronized void setSelectionProperty(int property, List values) {
if (!isKnownPropertyType(property)) {
throw new IllegalArgumentException("invalid property: " + property);
}
selectionRules.put(new Integer(property), values == null ? null : new ArrayList(values));
}
}