Index: pom.xml =================================================================== --- pom.xml (revision 1216) +++ pom.xml (working copy) @@ -90,6 +90,21 @@ mysql-connector-java 3.1.14 + + org.apache.ws.commons.axiom + axiom-api + SNAPSHOT + + + org.apache.ws.commons.axiom + axiom-impl + SNAPSHOT + + + org.apache.ws.commons.axiom + axiom-dom + SNAPSHOT + @@ -125,6 +140,7 @@ src/site/site.vm + Index: src/main/java/com/espertech/esper/client/Configuration.java =================================================================== --- src/main/java/com/espertech/esper/client/Configuration.java (revision 1216) +++ src/main/java/com/espertech/esper/client/Configuration.java (working copy) @@ -171,7 +171,13 @@ { eventClasses.put(eventTypeAlias, eventClassName); } + + public void addEventTypeAlias(String eventTypeAlias, ConfigurationEventTypeXMLAXIOM xmlAXIOMEventTypeDesc) + { + eventTypesXMLDOM.put(eventTypeAlias, xmlAXIOMEventTypeDesc); + } + /** * Add an alias for an event type represented by Java-bean plain-old Java object events. * @param eventTypeAlias is the alias for the event type @@ -247,6 +253,8 @@ { eventTypesXMLDOM.put(eventTypeAlias, xmlDOMEventTypeDesc); } + + /** * Add a database reference with a given database name. Index: src/main/java/com/espertech/esper/client/ConfigurationEventTypeXMLAXIOM.java =================================================================== --- src/main/java/com/espertech/esper/client/ConfigurationEventTypeXMLAXIOM.java (revision 0) +++ src/main/java/com/espertech/esper/client/ConfigurationEventTypeXMLAXIOM.java (revision 0) @@ -0,0 +1,11 @@ +package com.espertech.esper.client; + +public class ConfigurationEventTypeXMLAXIOM extends + ConfigurationEventTypeXMLDOM { + + /** + * + */ + private static final long serialVersionUID = 1L; + +} Index: src/main/java/com/espertech/esper/client/ConfigurationParser.java =================================================================== --- src/main/java/com/espertech/esper/client/ConfigurationParser.java (revision 1216) +++ src/main/java/com/espertech/esper/client/ConfigurationParser.java (working copy) @@ -180,6 +180,10 @@ { handleXMLDOM(aliasName, configuration, eventTypeElement); } + else if (nodeName.equals("xml-axiom")) + { + handleXMLAXIOM(aliasName, configuration, eventTypeElement); + } else if(nodeName.equals("java-util-map")) { handleMap(aliasName, configuration, eventTypeElement); @@ -260,7 +264,66 @@ } } } + + private static void handleXMLAXIOM(String aliasName, Configuration configuration, Element xmldomElement) + { + String rootElementName = xmldomElement.getAttributes().getNamedItem("root-element-name").getTextContent(); + String rootElementNamespace = getOptionalAttribute(xmldomElement, "root-element-namespace"); + String schemaResource = getOptionalAttribute(xmldomElement, "schema-resource"); + String defaultNamespace = getOptionalAttribute(xmldomElement, "default-namespace"); + String resolvePropertiesAbsoluteStr = getOptionalAttribute(xmldomElement, "resolve-properties-absolute"); + + ConfigurationEventTypeXMLAXIOM xmlAXIOMEventTypeDesc = new ConfigurationEventTypeXMLAXIOM(); + + xmlAXIOMEventTypeDesc.setRootElementName(rootElementName); + xmlAXIOMEventTypeDesc.setSchemaResource(schemaResource); + xmlAXIOMEventTypeDesc.setRootElementNamespace(rootElementNamespace); + xmlAXIOMEventTypeDesc.setDefaultNamespace(defaultNamespace); + if (resolvePropertiesAbsoluteStr != null) + { + xmlAXIOMEventTypeDesc.setResolvePropertiesAbsolute(Boolean.parseBoolean(resolvePropertiesAbsoluteStr)); + } + configuration.addEventTypeAlias(aliasName, xmlAXIOMEventTypeDesc); + DOMElementIterator propertyNodeIterator = new DOMElementIterator(xmldomElement.getChildNodes()); + while (propertyNodeIterator.hasNext()) + { + Element propertyElement = propertyNodeIterator.next(); + if (propertyElement.getNodeName().equals("namespace-prefix")) + { + String prefix = propertyElement.getAttributes().getNamedItem("prefix").getTextContent(); + String namespace = propertyElement.getAttributes().getNamedItem("namespace").getTextContent(); + xmlAXIOMEventTypeDesc.addNamespacePrefix(prefix, namespace); + } + if (propertyElement.getNodeName().equals("xpath-property")) + { + String propertyName = propertyElement.getAttributes().getNamedItem("property-name").getTextContent(); + String xPath = propertyElement.getAttributes().getNamedItem("xpath").getTextContent(); + String propertyType = propertyElement.getAttributes().getNamedItem("type").getTextContent(); + QName xpathConstantType; + if (propertyType.toUpperCase().equals("NUMBER")) + { + xpathConstantType = XPathConstants.NUMBER; + } + else if (propertyType.toUpperCase().equals("STRING")) + { + xpathConstantType = XPathConstants.STRING; + } + else if (propertyType.toUpperCase().equals("BOOLEAN")) + { + xpathConstantType = XPathConstants.BOOLEAN; + } + else + { + throw new IllegalArgumentException("Invalid xpath property type for property '" + + propertyName + "' and type '" + propertyType + '\''); + } + xmlAXIOMEventTypeDesc.addXPathProperty(propertyName, xPath, xpathConstantType); + } + } + } + + private static void handleLegacy(String aliasName, String className, Configuration configuration, Element xmldomElement) { // Class name is required for legacy classes Index: src/main/java/com/espertech/esper/client/EPRuntime.java =================================================================== --- src/main/java/com/espertech/esper/client/EPRuntime.java (revision 1216) +++ src/main/java/com/espertech/esper/client/EPRuntime.java (working copy) @@ -10,6 +10,8 @@ import java.util.Map; import java.util.Set; +import org.apache.axiom.om.OMNode; + /** * Interface to event stream processing runtime services. */ @@ -46,6 +48,16 @@ * @throws EPException is thrown when the processing of the event lead to an error */ public void sendEvent(org.w3c.dom.Node node) throws EPException; + + /** + * Send an event represented by a AXIOM node to the event stream processing runtime. + *

+ * Use the route method for sending events into the runtime from within UpdateListener code. + * + * @param node is the OMNode as an event + * @throws EPException is thrown when the processing of the event lead to an error + */ + public void sendEvent(OMNode node) throws EPException; /** * Number of events received over the lifetime of the event stream processing runtime. Index: src/main/java/com/espertech/esper/core/ConfigurationOperationsImpl.java =================================================================== --- src/main/java/com/espertech/esper/core/ConfigurationOperationsImpl.java (revision 1216) +++ src/main/java/com/espertech/esper/core/ConfigurationOperationsImpl.java (working copy) @@ -7,6 +7,7 @@ **************************************************************************************/ package com.espertech.esper.core; +import com.espertech.esper.client.ConfigurationEventTypeXMLAXIOM; import com.espertech.esper.client.ConfigurationEventTypeXMLDOM; import com.espertech.esper.client.ConfigurationException; import com.espertech.esper.client.ConfigurationOperations; @@ -160,6 +161,18 @@ throw new ConfigurationException(t.getMessage(), t); } } + + public void addEventTypeAlias(String eventTypeAlias, ConfigurationEventTypeXMLAXIOM xmlAXIOMEventTypeDesc) + { + try + { + eventAdapterService.addXMLAXIOMType(eventTypeAlias, xmlAXIOMEventTypeDesc); + } + catch (EventAdapterException t) + { + throw new ConfigurationException(t.getMessage(), t); + } + } private static Map createPropertyTypes(Properties properties) { Index: src/main/java/com/espertech/esper/core/EPRuntimeImpl.java =================================================================== --- src/main/java/com/espertech/esper/core/EPRuntimeImpl.java (revision 1216) +++ src/main/java/com/espertech/esper/core/EPRuntimeImpl.java (working copy) @@ -23,6 +23,8 @@ import com.espertech.esper.util.ManagedLock; import com.espertech.esper.util.ThreadLogUtil; import com.espertech.esper.epl.variable.VariableReader; + +import org.apache.axiom.om.OMNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -128,7 +130,25 @@ EventBean eventBean = services.getEventAdapterService().adapterForDOM(document); processEvent(eventBean); } + + public void sendEvent(OMNode document) throws EPException + { + if (document == null) + { + log.fatal(".sendEvent Null object supplied"); + return; + } + if ((ExecutionPathDebugLog.isDebugEnabled) && (log.isDebugEnabled())) + { + log.debug(".sendEvent Processing DOM node event " + document); + } + + // Get it wrapped up, process event + EventBean eventBean = services.getEventAdapterService().adapterForAXIOM(document); + processEvent(eventBean); + } + public void sendEvent(Map map, String eventTypeAlias) throws EPException { if (map == null) @@ -626,6 +646,7 @@ } catch (RuntimeException ex) { + ex.printStackTrace(); throw ex; } finally Index: src/main/java/com/espertech/esper/core/EPServicesContextFactoryDefault.java =================================================================== --- src/main/java/com/espertech/esper/core/EPServicesContextFactoryDefault.java (revision 1216) +++ src/main/java/com/espertech/esper/core/EPServicesContextFactoryDefault.java (working copy) @@ -173,7 +173,13 @@ // Add Java class alias try { - eventAdapterService.addXMLDOMType(entry.getKey(), entry.getValue()); + ConfigurationEventTypeXMLDOM value = entry.getValue(); + if (value instanceof ConfigurationEventTypeXMLAXIOM) { + eventAdapterService.addXMLDOMType(entry.getKey(), (ConfigurationEventTypeXMLAXIOM) value); + + } else { + eventAdapterService.addXMLDOMType(entry.getKey(), value); + } } catch (EventAdapterException ex) { Index: src/main/java/com/espertech/esper/core/StatementLifecycleSvcImpl.java =================================================================== --- src/main/java/com/espertech/esper/core/StatementLifecycleSvcImpl.java (revision 1216) +++ src/main/java/com/espertech/esper/core/StatementLifecycleSvcImpl.java (working copy) @@ -712,6 +712,7 @@ } catch (ExprValidationException ex) { + ex.printStackTrace(); throw new EPStatementException(ex.getMessage(), eplStatement); } catch (RuntimeException ex) Property changes on: src\main\java\com\espertech\esper\event ___________________________________________________________________ Name: svn:ignore + axiom Index: src/main/java/com/espertech/esper/event/EventAdapterServiceImpl.java =================================================================== --- src/main/java/com/espertech/esper/event/EventAdapterServiceImpl.java (revision 1216) +++ src/main/java/com/espertech/esper/event/EventAdapterServiceImpl.java (working copy) @@ -2,13 +2,20 @@ import com.espertech.esper.client.Configuration; import com.espertech.esper.client.ConfigurationEventTypeLegacy; +import com.espertech.esper.client.ConfigurationEventTypeXMLAXIOM; import com.espertech.esper.client.ConfigurationEventTypeXMLDOM; import com.espertech.esper.event.xml.BaseXMLEventType; import com.espertech.esper.client.EPException; import com.espertech.esper.event.xml.SchemaXMLEventType; import com.espertech.esper.event.xml.SimpleXMLEventType; import com.espertech.esper.event.xml.XMLEventBean; +import com.espertech.esper.event.xml.axiom.AxiomEventBean; +import com.espertech.esper.event.xml.axiom.AxiomXMLEventType; import com.espertech.esper.util.UuidGenerator; + +import org.apache.axiom.om.OMDocument; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; @@ -300,7 +307,35 @@ return new XMLEventBean(node, eventType); } + + public EventBean adapterForAXIOM(OMNode node) { + String rootElementName; + OMElement namedNode = null; + if (node instanceof OMDocument) + { + namedNode = ((OMDocument) node).getOMDocumentElement(); + } + else if (node instanceof OMElement) + { + namedNode = (OMElement)node; + } + else + { + throw new EPException("Unexpected AXIOM node of type '" + node.getClass() + "' encountered, please supply a Document or Element node"); + } + rootElementName = namedNode.getLocalName(); + + EventType eventType = xmldomRootElementNames.get(rootElementName); + if (eventType == null) + { + throw new EventAdapterException("AXIOM event root element name '" + rootElementName + + "' has not been configured"); + } + + return new AxiomEventBean(namedNode, eventType); + } + /** * Add a configured XML DOM event type. * @param eventTypeAlias is the alias name of the event type @@ -334,7 +369,11 @@ EventType type; if (configurationEventTypeXMLDOM.getSchemaResource() == null) { - type = new SimpleXMLEventType(configurationEventTypeXMLDOM); + if (configurationEventTypeXMLDOM instanceof ConfigurationEventTypeXMLAXIOM) { + type = new AxiomXMLEventType((ConfigurationEventTypeXMLAXIOM) configurationEventTypeXMLDOM); + } else { + type = new SimpleXMLEventType(configurationEventTypeXMLDOM); + } } else { @@ -346,7 +385,47 @@ return type; } + + /** + * Add a configured XML DOM event type. + * @param eventTypeAlias is the alias name of the event type + * @param configurationEventTypeXMLDOM configures the event type schema and namespace and XPath + * property information. + */ + public synchronized EventType addXMLAXIOMType(String eventTypeAlias, ConfigurationEventTypeXMLAXIOM configurationEventTypeXMLAXIOM) + { + if (configurationEventTypeXMLAXIOM.getRootElementName() == null) + { + throw new EventAdapterException("Required root element name has not been supplied"); + } + EventType existingType = aliasToTypeMap.get(eventTypeAlias); + if (existingType != null) + { + String message = "Event type named '" + eventTypeAlias + "' has already been declared with differing column name or type information"; + if (!(existingType instanceof BaseXMLEventType)) + { + throw new EventAdapterException(message); + } + ConfigurationEventTypeXMLAXIOM config = ((BaseXMLEventType) existingType).getConfigurationEventTypeXMLAXIOM(); + if (!config.equals(configurationEventTypeXMLAXIOM)) + { + throw new EventAdapterException(message); + } + + return existingType; + } + + EventType type; + type = new AxiomXMLEventType(configurationEventTypeXMLAXIOM); + + aliasToTypeMap.put(eventTypeAlias, type); + xmldomRootElementNames.put(configurationEventTypeXMLAXIOM.getRootElementName(), type); + + return type; + } + + public final EventBean createMapFromValues(Map properties, EventType eventType) { return new MapEventBean(properties, eventType); Index: src/main/java/com/espertech/esper/event/EventAdapterService.java =================================================================== --- src/main/java/com/espertech/esper/event/EventAdapterService.java (revision 1216) +++ src/main/java/com/espertech/esper/event/EventAdapterService.java (working copy) @@ -2,7 +2,10 @@ import java.util.Map; +import org.apache.axiom.om.OMNode; import org.w3c.dom.Node; + +import com.espertech.esper.client.ConfigurationEventTypeXMLAXIOM; import com.espertech.esper.client.ConfigurationEventTypeXMLDOM; import com.espertech.esper.client.ConfigurationEventTypeLegacy; import com.espertech.esper.client.Configuration; @@ -160,6 +163,15 @@ * @return event wrapper for document */ public EventBean adapterForDOM(Node node); + + /** + * Returns an adapter for the XML AXIOM document that exposes it's data as event properties for use in statements. + * @param node is the node to wrap + * @return event wrapper for document + */ + public EventBean adapterForAXIOM(OMNode node); + + /** * Creates an unnamed composite event type with event properties that are name-value pairs @@ -195,6 +207,15 @@ * @return event type */ public EventType addXMLDOMType(String eventTypeAlias, ConfigurationEventTypeXMLDOM configurationEventTypeXMLDOM); + + /** + * Adds an XML AXIOM event type. + * @param eventTypeAlias is the alias to add the type for + * @param configurationEventTypeXMLAXIOM is the XML AXIOM config info + * @return event type + */ + public EventType addXMLAXIOMType(String eventTypeAlias, ConfigurationEventTypeXMLAXIOM configurationEventTypeXMLAXIOM); + /** * Sets the configured legacy Java class information. Index: src/main/java/com/espertech/esper/event/EventAdapterService.java =================================================================== --- src/main/java/com/espertech/esper/event/EventAdapterService.java (revision 1216) +++ src/main/java/com/espertech/esper/event/EventAdapterService.java (working copy) @@ -2,7 +2,10 @@ import java.util.Map; +import org.apache.axiom.om.OMNode; import org.w3c.dom.Node; + +import com.espertech.esper.client.ConfigurationEventTypeXMLAXIOM; import com.espertech.esper.client.ConfigurationEventTypeXMLDOM; import com.espertech.esper.client.ConfigurationEventTypeLegacy; import com.espertech.esper.client.Configuration; @@ -160,6 +163,15 @@ * @return event wrapper for document */ public EventBean adapterForDOM(Node node); + + /** + * Returns an adapter for the XML AXIOM document that exposes it's data as event properties for use in statements. + * @param node is the node to wrap + * @return event wrapper for document + */ + public EventBean adapterForAXIOM(OMNode node); + + /** * Creates an unnamed composite event type with event properties that are name-value pairs @@ -195,6 +207,15 @@ * @return event type */ public EventType addXMLDOMType(String eventTypeAlias, ConfigurationEventTypeXMLDOM configurationEventTypeXMLDOM); + + /** + * Adds an XML AXIOM event type. + * @param eventTypeAlias is the alias to add the type for + * @param configurationEventTypeXMLAXIOM is the XML AXIOM config info + * @return event type + */ + public EventType addXMLAXIOMType(String eventTypeAlias, ConfigurationEventTypeXMLAXIOM configurationEventTypeXMLAXIOM); + /** * Sets the configured legacy Java class information. Index: src/main/java/com/espertech/esper/event/EventAdapterServiceImpl.java =================================================================== --- src/main/java/com/espertech/esper/event/EventAdapterServiceImpl.java (revision 1216) +++ src/main/java/com/espertech/esper/event/EventAdapterServiceImpl.java (working copy) @@ -2,13 +2,20 @@ import com.espertech.esper.client.Configuration; import com.espertech.esper.client.ConfigurationEventTypeLegacy; +import com.espertech.esper.client.ConfigurationEventTypeXMLAXIOM; import com.espertech.esper.client.ConfigurationEventTypeXMLDOM; import com.espertech.esper.event.xml.BaseXMLEventType; import com.espertech.esper.client.EPException; import com.espertech.esper.event.xml.SchemaXMLEventType; import com.espertech.esper.event.xml.SimpleXMLEventType; import com.espertech.esper.event.xml.XMLEventBean; +import com.espertech.esper.event.xml.axiom.AxiomEventBean; +import com.espertech.esper.event.xml.axiom.AxiomXMLEventType; import com.espertech.esper.util.UuidGenerator; + +import org.apache.axiom.om.OMDocument; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; @@ -300,7 +307,35 @@ return new XMLEventBean(node, eventType); } + + public EventBean adapterForAXIOM(OMNode node) { + String rootElementName; + OMElement namedNode = null; + if (node instanceof OMDocument) + { + namedNode = ((OMDocument) node).getOMDocumentElement(); + } + else if (node instanceof OMElement) + { + namedNode = (OMElement)node; + } + else + { + throw new EPException("Unexpected AXIOM node of type '" + node.getClass() + "' encountered, please supply a Document or Element node"); + } + rootElementName = namedNode.getLocalName(); + + EventType eventType = xmldomRootElementNames.get(rootElementName); + if (eventType == null) + { + throw new EventAdapterException("AXIOM event root element name '" + rootElementName + + "' has not been configured"); + } + + return new AxiomEventBean(namedNode, eventType); + } + /** * Add a configured XML DOM event type. * @param eventTypeAlias is the alias name of the event type @@ -334,7 +369,11 @@ EventType type; if (configurationEventTypeXMLDOM.getSchemaResource() == null) { - type = new SimpleXMLEventType(configurationEventTypeXMLDOM); + if (configurationEventTypeXMLDOM instanceof ConfigurationEventTypeXMLAXIOM) { + type = new AxiomXMLEventType((ConfigurationEventTypeXMLAXIOM) configurationEventTypeXMLDOM); + } else { + type = new SimpleXMLEventType(configurationEventTypeXMLDOM); + } } else { @@ -346,7 +385,47 @@ return type; } + + /** + * Add a configured XML DOM event type. + * @param eventTypeAlias is the alias name of the event type + * @param configurationEventTypeXMLDOM configures the event type schema and namespace and XPath + * property information. + */ + public synchronized EventType addXMLAXIOMType(String eventTypeAlias, ConfigurationEventTypeXMLAXIOM configurationEventTypeXMLAXIOM) + { + if (configurationEventTypeXMLAXIOM.getRootElementName() == null) + { + throw new EventAdapterException("Required root element name has not been supplied"); + } + EventType existingType = aliasToTypeMap.get(eventTypeAlias); + if (existingType != null) + { + String message = "Event type named '" + eventTypeAlias + "' has already been declared with differing column name or type information"; + if (!(existingType instanceof BaseXMLEventType)) + { + throw new EventAdapterException(message); + } + ConfigurationEventTypeXMLAXIOM config = ((BaseXMLEventType) existingType).getConfigurationEventTypeXMLAXIOM(); + if (!config.equals(configurationEventTypeXMLAXIOM)) + { + throw new EventAdapterException(message); + } + + return existingType; + } + + EventType type; + type = new AxiomXMLEventType(configurationEventTypeXMLAXIOM); + + aliasToTypeMap.put(eventTypeAlias, type); + xmldomRootElementNames.put(configurationEventTypeXMLAXIOM.getRootElementName(), type); + + return type; + } + + public final EventBean createMapFromValues(Map properties, EventType eventType) { return new MapEventBean(properties, eventType); Index: src/main/java/com/espertech/esper/event/xml/axiom/AxiomXMLEventType.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/axiom/AxiomXMLEventType.java (revision 0) +++ src/main/java/com/espertech/esper/event/xml/axiom/AxiomXMLEventType.java (revision 0) @@ -0,0 +1,115 @@ +package com.espertech.esper.event.xml.axiom; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.axiom.om.xpath.AXIOMXPath; +import org.jaxen.JaxenException; + +import com.espertech.esper.client.ConfigurationEventTypeXMLAXIOM; +import com.espertech.esper.client.EPException; +import com.espertech.esper.client.ConfigurationEventTypeXMLDOM.XPathPropertyDesc; +import com.espertech.esper.event.EventPropertyGetter; +import com.espertech.esper.event.TypedEventPropertyGetter; +import com.espertech.esper.event.xml.BaseXMLEventType; + +/** + * Optimistic try to resolve the property string into an appropiate xPath, and + * use it as getter. Mapped and Indexed properties supported. Because no type + * information is given, all property are resolved to String. No namespace + * support. Cannot access to xml attributes, only elements content. + * + * + * + * + */ +public class AxiomXMLEventType extends BaseXMLEventType { + + private final Map propertyGetterCache; + private String defaultNamespacePrefix; + private final boolean isResolvePropertiesAbsolute; + private Map xPathProperties = null; + + /** + * Ctor. + * + * @param configurationEventTypeXMLAXIOM + * configures the event type + */ + public AxiomXMLEventType( + ConfigurationEventTypeXMLAXIOM configurationEventTypeXMLAXIOM) { + super(configurationEventTypeXMLAXIOM); + + isResolvePropertiesAbsolute = configurationEventTypeXMLAXIOM + .isResolvePropertiesAbsolute(); + + // Set of namespace context for XPath expressions + AxiomXPathNamespaceContext xPathNamespaceContext = new AxiomXPathNamespaceContext(); + for (Map.Entry entry : configurationEventTypeXMLAXIOM + .getNamespacePrefixes().entrySet()) { + xPathNamespaceContext.addPrefix(entry.getKey(), entry.getValue()); + } + + if (configurationEventTypeXMLAXIOM.getDefaultNamespace() != null) { + String defaultNamespace = configurationEventTypeXMLAXIOM + .getDefaultNamespace(); + xPathNamespaceContext.setDefaultNamespace(defaultNamespace); + + // determine a default namespace prefix to use to construct XPath + // expressions from pure property names + defaultNamespacePrefix = null; + for (Map.Entry entry : configurationEventTypeXMLAXIOM + .getNamespacePrefixes().entrySet()) { + if (entry.getValue().equals(defaultNamespace)) { + defaultNamespacePrefix = entry.getKey(); + break; + } + } + } + + super.setNamespaceContext(xPathNamespaceContext); + super.setExplicitProperties(configurationEventTypeXMLAXIOM + .getXPathProperties().values()); + this.xPathProperties = configurationEventTypeXMLAXIOM + .getXPathProperties(); + propertyGetterCache = new HashMap(); + } + + protected Class doResolvePropertyType(String property) { + return String.class; + } + +// public EventPropertyGetter getGetter(String property) { +// return doResolvePropertyGetter(property); +// } + + protected EventPropertyGetter doResolvePropertyGetter(String property) { + TypedEventPropertyGetter getter = propertyGetterCache.get(property); + if (getter != null) { + return getter; + } + + AXIOMXPath axXPath = null; + // String xPathExpr + // =SimpleXMLPropertyParser.parse(property,getRootElementName(), + // defaultNamespacePrefix, isResolvePropertiesAbsolute); + XPathPropertyDesc xpd = xPathProperties.get(property); + String xPathExpr = xpd.getXpath(); + + try { + axXPath = new AXIOMXPath(xPathExpr); + } catch (JaxenException e) { + throw new EPException( + "Error constructing XPath expression from property name '" + + property + '\'', e); + } + axXPath + .setNamespaceContext((org.jaxen.NamespaceContext) namespaceContext); + getter = new AXIOMXPathPropertyGetter(property, axXPath, + XPathConstants.STRING); + propertyGetterCache.put(property, getter); + return getter; + } +} Index: src/main/java/com/espertech/esper/event/xml/axiom/AXIOMXPathPropertyGetter.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/axiom/AXIOMXPathPropertyGetter.java (revision 0) +++ src/main/java/com/espertech/esper/event/xml/axiom/AXIOMXPathPropertyGetter.java (revision 0) @@ -0,0 +1,86 @@ +package com.espertech.esper.event.xml.axiom; + +import javax.xml.namespace.QName; +import javax.xml.xpath.XPathConstants; + +import org.apache.axiom.om.OMNode; +import org.apache.axiom.om.xpath.AXIOMXPath; +import org.jaxen.JaxenException; + +import com.espertech.esper.event.EventBean; +import com.espertech.esper.event.PropertyAccessException; +import com.espertech.esper.event.TypedEventPropertyGetter; + +/** + * Getter for properties of AXIOM xml events. + * + * @author paul + */ +public class AXIOMXPathPropertyGetter implements TypedEventPropertyGetter { + AXIOMXPath expression; + String property; + QName resultType; + + /** + * Ctor. + * + * @param propertyName + * is the name of the event property for which this getter gets + * values + * @param xPathExpression + * is a compile XPath expression + * @param resultType + * is the resulting type + */ + public AXIOMXPathPropertyGetter(String propertyName, AXIOMXPath xPath, + QName resultType) { + this.expression = xPath; + this.property = propertyName; + this.resultType = resultType; + } + + public Object get(EventBean eventBean) throws PropertyAccessException { + Object und = eventBean.getUnderlying(); + if (und == null) { + throw new PropertyAccessException( + "Unexpected null underlying event encountered, expecting org.w3c.dom.Node instance as underlying"); + } + if (!(und instanceof OMNode)) { + throw new PropertyAccessException( + "Unexpected underlying event of type '" + + und.getClass() + + "' encountered, expecting org.w3c.dom.Node as underlying"); + } + try { + if (resultType.equals(XPathConstants.BOOLEAN)) { + return expression.booleanValueOf(und); + } else if (resultType.equals(XPathConstants.NUMBER)) { + Number n = expression.numberValueOf(und); + return n.doubleValue(); + } else { + String result = expression.stringValueOf(und); + return result; + } + + } catch (JaxenException e) { + throw new PropertyAccessException("Error getting property " + + property, e); + } + } + + public Class getResultClass() { + if (resultType.equals(XPathConstants.BOOLEAN)) + return Boolean.class; + if (resultType.equals(XPathConstants.NUMBER)) + return Double.class; + if (resultType.equals(XPathConstants.STRING)) + return String.class; + + return String.class; + } + + public boolean isExistsProperty(EventBean eventBean) { + return true; // Property exists as the property is not dynamic + // (unchecked) + } +} Index: src/main/java/com/espertech/esper/event/xml/axiom/AxiomXPathNamespaceContext.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/axiom/AxiomXPathNamespaceContext.java (revision 0) +++ src/main/java/com/espertech/esper/event/xml/axiom/AxiomXPathNamespaceContext.java (revision 0) @@ -0,0 +1,13 @@ +package com.espertech.esper.event.xml.axiom; + + +import org.jaxen.NamespaceContext; + +import com.espertech.esper.event.xml.XPathNamespaceContext; + +public class AxiomXPathNamespaceContext extends XPathNamespaceContext implements NamespaceContext { + + public String translateNamespacePrefixToUri(String prefix) { + return this.getNamespaceURI(prefix); + } +} Index: src/main/java/com/espertech/esper/event/xml/axiom/AxiomEventBean.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/axiom/AxiomEventBean.java (revision 0) +++ src/main/java/com/espertech/esper/event/xml/axiom/AxiomEventBean.java (revision 0) @@ -0,0 +1,52 @@ +package com.espertech.esper.event.xml.axiom; + +import org.apache.axiom.om.OMNode; + +import com.espertech.esper.event.EventBean; +import com.espertech.esper.event.EventPropertyGetter; +import com.espertech.esper.event.EventType; +import com.espertech.esper.event.PropertyAccessException; + +/** + * EventBean wrapper for XML documents. Currently only instances of OMNode can + * be used + * + * @author Paul Fremantle + * + */ +public class AxiomEventBean implements EventBean { + + private EventType eventType; + private OMNode event; + + /** + * Ctor. + * + * @param event + * is the node with event property information + * @param type + * is the event type for this event wrapper + */ + public AxiomEventBean(OMNode event, EventType type) { + this.event = event; + eventType = type; + } + + public EventType getEventType() { + return eventType; + } + + public Object get(String property) throws PropertyAccessException { + EventPropertyGetter getter = eventType.getGetter(property); + if (getter == null) { + throw new PropertyAccessException("Property named '" + property + + "' is not a valid property name for this type"); + } + return getter.get(this); + } + + public Object getUnderlying() { + return event; + } + +} Index: src/main/java/com/espertech/esper/event/xml/axiom/AxiomEventBean.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/axiom/AxiomEventBean.java (revision 0) +++ src/main/java/com/espertech/esper/event/xml/axiom/AxiomEventBean.java (revision 0) @@ -0,0 +1,52 @@ +package com.espertech.esper.event.xml.axiom; + +import org.apache.axiom.om.OMNode; + +import com.espertech.esper.event.EventBean; +import com.espertech.esper.event.EventPropertyGetter; +import com.espertech.esper.event.EventType; +import com.espertech.esper.event.PropertyAccessException; + +/** + * EventBean wrapper for XML documents. Currently only instances of OMNode can + * be used + * + * @author Paul Fremantle + * + */ +public class AxiomEventBean implements EventBean { + + private EventType eventType; + private OMNode event; + + /** + * Ctor. + * + * @param event + * is the node with event property information + * @param type + * is the event type for this event wrapper + */ + public AxiomEventBean(OMNode event, EventType type) { + this.event = event; + eventType = type; + } + + public EventType getEventType() { + return eventType; + } + + public Object get(String property) throws PropertyAccessException { + EventPropertyGetter getter = eventType.getGetter(property); + if (getter == null) { + throw new PropertyAccessException("Property named '" + property + + "' is not a valid property name for this type"); + } + return getter.get(this); + } + + public Object getUnderlying() { + return event; + } + +} Index: src/main/java/com/espertech/esper/event/xml/axiom/AxiomXMLEventType.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/axiom/AxiomXMLEventType.java (revision 0) +++ src/main/java/com/espertech/esper/event/xml/axiom/AxiomXMLEventType.java (revision 0) @@ -0,0 +1,115 @@ +package com.espertech.esper.event.xml.axiom; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.xpath.XPathConstants; + +import org.apache.axiom.om.xpath.AXIOMXPath; +import org.jaxen.JaxenException; + +import com.espertech.esper.client.ConfigurationEventTypeXMLAXIOM; +import com.espertech.esper.client.EPException; +import com.espertech.esper.client.ConfigurationEventTypeXMLDOM.XPathPropertyDesc; +import com.espertech.esper.event.EventPropertyGetter; +import com.espertech.esper.event.TypedEventPropertyGetter; +import com.espertech.esper.event.xml.BaseXMLEventType; + +/** + * Optimistic try to resolve the property string into an appropiate xPath, and + * use it as getter. Mapped and Indexed properties supported. Because no type + * information is given, all property are resolved to String. No namespace + * support. Cannot access to xml attributes, only elements content. + * + * + * + * + */ +public class AxiomXMLEventType extends BaseXMLEventType { + + private final Map propertyGetterCache; + private String defaultNamespacePrefix; + private final boolean isResolvePropertiesAbsolute; + private Map xPathProperties = null; + + /** + * Ctor. + * + * @param configurationEventTypeXMLAXIOM + * configures the event type + */ + public AxiomXMLEventType( + ConfigurationEventTypeXMLAXIOM configurationEventTypeXMLAXIOM) { + super(configurationEventTypeXMLAXIOM); + + isResolvePropertiesAbsolute = configurationEventTypeXMLAXIOM + .isResolvePropertiesAbsolute(); + + // Set of namespace context for XPath expressions + AxiomXPathNamespaceContext xPathNamespaceContext = new AxiomXPathNamespaceContext(); + for (Map.Entry entry : configurationEventTypeXMLAXIOM + .getNamespacePrefixes().entrySet()) { + xPathNamespaceContext.addPrefix(entry.getKey(), entry.getValue()); + } + + if (configurationEventTypeXMLAXIOM.getDefaultNamespace() != null) { + String defaultNamespace = configurationEventTypeXMLAXIOM + .getDefaultNamespace(); + xPathNamespaceContext.setDefaultNamespace(defaultNamespace); + + // determine a default namespace prefix to use to construct XPath + // expressions from pure property names + defaultNamespacePrefix = null; + for (Map.Entry entry : configurationEventTypeXMLAXIOM + .getNamespacePrefixes().entrySet()) { + if (entry.getValue().equals(defaultNamespace)) { + defaultNamespacePrefix = entry.getKey(); + break; + } + } + } + + super.setNamespaceContext(xPathNamespaceContext); + super.setExplicitProperties(configurationEventTypeXMLAXIOM + .getXPathProperties().values()); + this.xPathProperties = configurationEventTypeXMLAXIOM + .getXPathProperties(); + propertyGetterCache = new HashMap(); + } + + protected Class doResolvePropertyType(String property) { + return String.class; + } + +// public EventPropertyGetter getGetter(String property) { +// return doResolvePropertyGetter(property); +// } + + protected EventPropertyGetter doResolvePropertyGetter(String property) { + TypedEventPropertyGetter getter = propertyGetterCache.get(property); + if (getter != null) { + return getter; + } + + AXIOMXPath axXPath = null; + // String xPathExpr + // =SimpleXMLPropertyParser.parse(property,getRootElementName(), + // defaultNamespacePrefix, isResolvePropertiesAbsolute); + XPathPropertyDesc xpd = xPathProperties.get(property); + String xPathExpr = xpd.getXpath(); + + try { + axXPath = new AXIOMXPath(xPathExpr); + } catch (JaxenException e) { + throw new EPException( + "Error constructing XPath expression from property name '" + + property + '\'', e); + } + axXPath + .setNamespaceContext((org.jaxen.NamespaceContext) namespaceContext); + getter = new AXIOMXPathPropertyGetter(property, axXPath, + XPathConstants.STRING); + propertyGetterCache.put(property, getter); + return getter; + } +} Index: src/main/java/com/espertech/esper/event/xml/axiom/AxiomXPathNamespaceContext.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/axiom/AxiomXPathNamespaceContext.java (revision 0) +++ src/main/java/com/espertech/esper/event/xml/axiom/AxiomXPathNamespaceContext.java (revision 0) @@ -0,0 +1,13 @@ +package com.espertech.esper.event.xml.axiom; + + +import org.jaxen.NamespaceContext; + +import com.espertech.esper.event.xml.XPathNamespaceContext; + +public class AxiomXPathNamespaceContext extends XPathNamespaceContext implements NamespaceContext { + + public String translateNamespacePrefixToUri(String prefix) { + return this.getNamespaceURI(prefix); + } +} Index: src/main/java/com/espertech/esper/event/xml/axiom/AXIOMXPathPropertyGetter.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/axiom/AXIOMXPathPropertyGetter.java (revision 0) +++ src/main/java/com/espertech/esper/event/xml/axiom/AXIOMXPathPropertyGetter.java (revision 0) @@ -0,0 +1,86 @@ +package com.espertech.esper.event.xml.axiom; + +import javax.xml.namespace.QName; +import javax.xml.xpath.XPathConstants; + +import org.apache.axiom.om.OMNode; +import org.apache.axiom.om.xpath.AXIOMXPath; +import org.jaxen.JaxenException; + +import com.espertech.esper.event.EventBean; +import com.espertech.esper.event.PropertyAccessException; +import com.espertech.esper.event.TypedEventPropertyGetter; + +/** + * Getter for properties of AXIOM xml events. + * + * @author paul + */ +public class AXIOMXPathPropertyGetter implements TypedEventPropertyGetter { + AXIOMXPath expression; + String property; + QName resultType; + + /** + * Ctor. + * + * @param propertyName + * is the name of the event property for which this getter gets + * values + * @param xPathExpression + * is a compile XPath expression + * @param resultType + * is the resulting type + */ + public AXIOMXPathPropertyGetter(String propertyName, AXIOMXPath xPath, + QName resultType) { + this.expression = xPath; + this.property = propertyName; + this.resultType = resultType; + } + + public Object get(EventBean eventBean) throws PropertyAccessException { + Object und = eventBean.getUnderlying(); + if (und == null) { + throw new PropertyAccessException( + "Unexpected null underlying event encountered, expecting org.w3c.dom.Node instance as underlying"); + } + if (!(und instanceof OMNode)) { + throw new PropertyAccessException( + "Unexpected underlying event of type '" + + und.getClass() + + "' encountered, expecting org.w3c.dom.Node as underlying"); + } + try { + if (resultType.equals(XPathConstants.BOOLEAN)) { + return expression.booleanValueOf(und); + } else if (resultType.equals(XPathConstants.NUMBER)) { + Number n = expression.numberValueOf(und); + return n.doubleValue(); + } else { + String result = expression.stringValueOf(und); + return result; + } + + } catch (JaxenException e) { + throw new PropertyAccessException("Error getting property " + + property, e); + } + } + + public Class getResultClass() { + if (resultType.equals(XPathConstants.BOOLEAN)) + return Boolean.class; + if (resultType.equals(XPathConstants.NUMBER)) + return Double.class; + if (resultType.equals(XPathConstants.STRING)) + return String.class; + + return String.class; + } + + public boolean isExistsProperty(EventBean eventBean) { + return true; // Property exists as the property is not dynamic + // (unchecked) + } +} Index: src/main/java/com/espertech/esper/event/xml/BaseXMLEventType.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/BaseXMLEventType.java (revision 1216) +++ src/main/java/com/espertech/esper/event/xml/BaseXMLEventType.java (working copy) @@ -2,9 +2,14 @@ import javax.xml.xpath.*; +import org.apache.axiom.om.OMNode; +import org.apache.axiom.om.xpath.AXIOMXPath; +import org.jaxen.JaxenException; import org.w3c.dom.Node; import com.espertech.esper.event.*; +import com.espertech.esper.event.xml.axiom.AXIOMXPathPropertyGetter; +import com.espertech.esper.client.ConfigurationEventTypeXMLAXIOM; import com.espertech.esper.client.ConfigurationEventTypeXMLDOM; import com.espertech.esper.client.EPException; @@ -44,6 +49,14 @@ this.configurationEventTypeXMLDOM = configurationEventTypeXMLDOM; xPathFactory = XPathFactory.newInstance(); } + + public BaseXMLEventType(ConfigurationEventTypeXMLAXIOM configurationEventTypeXMLAXIOM) + { + super(OMNode.class); + this.rootElementName = configurationEventTypeXMLAXIOM.getRootElementName(); + this.configurationEventTypeXMLDOM = configurationEventTypeXMLAXIOM; + xPathFactory = null; + } /** * Returns the name of the root element. @@ -77,15 +90,38 @@ for (ConfigurationEventTypeXMLDOM.XPathPropertyDesc property : explicitProperties) { - XPath xPath = xPathFactory.newXPath(); - if (namespaceContext != null) - { - xPath.setNamespaceContext(namespaceContext); - } + if (xPathFactory == null) + { + try + { + String xpathExpr = property.getXpath(); + AXIOMXPath axXPath = new AXIOMXPath(xpathExpr); + if (namespaceContext != null) + { + axXPath.setNamespaceContext((org.jaxen.NamespaceContext) namespaceContext); + } + AXIOMXPathPropertyGetter getter = new AXIOMXPathPropertyGetter(property.getName(), axXPath,property.getType() ); + getters.put(property.getName(), getter); + } + catch (JaxenException e) + { + throw new EPException( + "Error constructing XPath expression from property name '" + + property + '\'', e); + } + } + else + { + XPath xPath = xPathFactory.newXPath(); + if (namespaceContext != null) + { + xPath.setNamespaceContext(namespaceContext); + } - xpathExpression = property.getXpath(); - XPathExpression expression = xPath.compile(xpathExpression); - getters.put(property.getName(), new XPathPropertyGetter(property.getName(), expression, property.getType())); + xpathExpression = property.getXpath(); + XPathExpression expression = xPath.compile(xpathExpression); + getters.put(property.getName(), new XPathPropertyGetter(property.getName(), expression, property.getType())); + } } } catch (XPathExpressionException ex) @@ -125,6 +161,11 @@ { return configurationEventTypeXMLDOM; } + + public ConfigurationEventTypeXMLAXIOM getConfigurationEventTypeXMLAXIOM() + { + return (ConfigurationEventTypeXMLAXIOM) configurationEventTypeXMLDOM; + } public boolean equals(Object otherObj) { Index: src/main/java/com/espertech/esper/event/xml/SimpleXMLEventType.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/SimpleXMLEventType.java (revision 1216) +++ src/main/java/com/espertech/esper/event/xml/SimpleXMLEventType.java (working copy) @@ -1,18 +1,19 @@ package com.espertech.esper.event.xml; -import com.espertech.esper.client.ConfigurationEventTypeXMLDOM; -import com.espertech.esper.client.EPException; -import com.espertech.esper.event.EventPropertyGetter; -import com.espertech.esper.event.TypedEventPropertyGetter; +import java.util.HashMap; +import java.util.Map; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; -import java.util.HashMap; -import java.util.Map; +import com.espertech.esper.client.ConfigurationEventTypeXMLDOM; +import com.espertech.esper.client.EPException; +import com.espertech.esper.event.EventPropertyGetter; +import com.espertech.esper.event.TypedEventPropertyGetter; + /** * Optimistic try to resolve the property string into an appropiate xPath, * and use it as getter. @@ -68,7 +69,7 @@ propertyGetterCache = new HashMap(); } - + protected Class doResolvePropertyType(String property) { return String.class; } Index: src/main/java/com/espertech/esper/event/xml/XPathPropertyGetter.java =================================================================== --- src/main/java/com/espertech/esper/event/xml/XPathPropertyGetter.java (revision 1216) +++ src/main/java/com/espertech/esper/event/xml/XPathPropertyGetter.java (working copy) @@ -10,6 +10,7 @@ import com.espertech.esper.event.PropertyAccessException; import com.espertech.esper.event.TypedEventPropertyGetter; +import org.apache.axiom.om.OMNode; import org.w3c.dom.Node; /** @@ -40,7 +41,7 @@ { throw new PropertyAccessException("Unexpected null underlying event encountered, expecting org.w3c.dom.Node instance as underlying"); } - if (!(und instanceof Node)) + if (!(und instanceof Node || und instanceof OMNode)) { throw new PropertyAccessException("Unexpected underlying event of type '" + und.getClass() + "' encountered, expecting org.w3c.dom.Node as underlying"); }