/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package com.espertech.esper.client;
import com.espertech.esper.util.JavaClassHelper;
import com.espertech.esper.util.MetaDefItem;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathConstants;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Configuration object for enabling the engine to process events represented as XML DOM document nodes.
* <p>
* Use this class to configure the engine for processing of XML DOM objects that represent events
* and contain all the data for event properties used by statements.
* <p>
* Minimally required is the root element name which allows the engine to map the document
* to the event type that has been named in an EPL or pattern statement.
* <p>
* Event properties that are results of XPath expressions can be made known to the engine via this class.
* For XPath expressions that must refer to namespace prefixes those prefixes and their
* namespace name must be supplied to the engine. A default namespace can be supplied as well.
* <p>
* By supplying a schema resource the engine can interrogate the schema, allowing the engine to
* verify event properties and return event properties in the type defined by the schema.
* When a schema resource is supplied, the optional root element namespace defines the namespace in case the
* root element name occurs in multiple namespaces.
* <p>
*/
public class ConfigurationEventTypeXMLDOM implements MetaDefItem, Serializable
{
private String rootElementName;
// Root element namespace.
// Used to find root element in schema. Useful and required in the case where the root element exists in
// multiple namespaces.
private String rootElementNamespace;
// Default name space.
// For XPath expression evaluation.
private String defaultNamespace;
private String schemaResource;
private String schemaText;
private Map<String, XPathPropertyDesc> xPathProperties;
private Map<String, String> namespacePrefixes;
private boolean isXPathPropertyExpr;
private boolean isXPathResolvePropertiesAbsolute;
private boolean isEventSenderValidatesRoot;
private boolean isAutoFragment;
private String xPathFunctionResolver;
private String xPathVariableResolver;
private String startTimestampPropertyName;
private String endTimestampPropertyName;
private boolean updateStoredType; // For use with EsperHA to enable new type configuration to overwrite an existing type configuration
private static final long serialVersionUID = -7488596902855838072L;
/**
* Ctor.
*/
public ConfigurationEventTypeXMLDOM()
{
xPathProperties = new LinkedHashMap<String, XPathPropertyDesc>();
namespacePrefixes = new HashMap<String, String>();
isXPathResolvePropertiesAbsolute = true;
isXPathPropertyExpr = false;
isEventSenderValidatesRoot = true;
isAutoFragment = true;
}
/**
* Returns the root element name.
* @return root element name
*/
public String getRootElementName()
{
return rootElementName;
}
/**
* Sets the root element name.
* @param rootElementName is the name of the root element
*/
public void setRootElementName(String rootElementName)
{
this.rootElementName = rootElementName;
}
/**
* Returns the root element namespace.
* @return root element namespace
*/
public String getRootElementNamespace()
{
return rootElementNamespace;
}
/**
* Sets the root element namespace.
* @param rootElementNamespace is the namespace for the root element
*/
public void setRootElementNamespace(String rootElementNamespace)
{
this.rootElementNamespace = rootElementNamespace;
}
/**
* Returns the default namespace.
* @return default namespace
*/
public String getDefaultNamespace()
{
return defaultNamespace;
}
/**
* Sets the default namespace.
* @param defaultNamespace is the default namespace
*/
public void setDefaultNamespace(String defaultNamespace)
{
this.defaultNamespace = defaultNamespace;
}
/**
* Returns the schema resource.
* @return schema resource
*/
public String getSchemaResource()
{
return schemaResource;
}
/**
* Sets the schema resource.
* @param schemaResource is the schema resource
*/
public void setSchemaResource(String schemaResource)
{
this.schemaResource = schemaResource;
}
/**
* Returns the schema text, if provided instead of a schema resource, this call returns the actual text of the schema document.
* <p>
* Set a schema text first. This call will not resolve the schema resource to a text.
* @return schema text, if provided, or null value
*/
public String getSchemaText() {
return schemaText;
}
/**
* Sets the schema text, for use when the schema resource is impractical and when providing the actual text
* of the schema instead.
* @param schemaText schema text is the actual content of an XSD schema file as a string,
* provide instead of a schema resource name
*/
public void setSchemaText(String schemaText) {
this.schemaText = schemaText;
}
/**
* Returns a map of property name and descriptor for XPath-expression properties.
* @return XPath property information
*/
public Map<String, XPathPropertyDesc> getXPathProperties()
{
return xPathProperties;
}
/**
* Returns false to indicate that property expressions are evaluated by the DOM-walker
* implementation (the default), or true to indicate that property expressions are rewritten into XPath expressions.
* @return indicator how property expressions are evaluated
*/
public boolean isXPathPropertyExpr()
{
return isXPathPropertyExpr;
}
/**
* Set to false to indicate that property expressions are evaluated by the DOM-walker
* implementation (the default), or set to true to indicate that property expressions are rewritten into XPath expressions.
* @param xPathPropertyExpr indicator how property expressions are evaluated
*/
public void setXPathPropertyExpr(boolean xPathPropertyExpr)
{
isXPathPropertyExpr = xPathPropertyExpr;
}
/**
* Returns true to indicate that an {@link EventSender} returned for this event type validates
* the root document element name against the one configured (the default), or false to not validate the root document
* element name as configured.
* @return true for validation of root document element name by event sender, false for no validation
*/
public boolean isEventSenderValidatesRoot()
{
return isEventSenderValidatesRoot;
}
/**
* Set to true to indicate that an {@link EventSender} returned for this event type validates
* the root document element name against the one configured (the default), or false to not validate the root document
* element name as configured.
* @param eventSenderValidatesRoot true for validation of root document element name by event sender, false for no validation
*/
public void setEventSenderValidatesRoot(boolean eventSenderValidatesRoot)
{
isEventSenderValidatesRoot = eventSenderValidatesRoot;
}
/**
* Set to true (the default) to look up or create event types representing fragments of an XML document
* automatically upon request for fragment event type information; Or false when only explicit
* properties may return fragments.
* @return indicator whether to allow splitting-up (fragmenting) properties (nodes) in an document
*/
public boolean isAutoFragment()
{
return isAutoFragment;
}
/**
* Set to true (the default) to look up or create event types representing fragments of an XML document
* automatically upon request for fragment event type information; Or false when only explicit
* properties may return fragments.
* @param autoFragment indicator whether to allow splitting-up (fragmenting) properties (nodes) in an document
*/
public void setAutoFragment(boolean autoFragment)
{
isAutoFragment = autoFragment;
}
/**
* Adds an event property for which the engine uses the supplied XPath expression against
* a DOM document node to resolve a property value.
* @param name of the event property
* @param xpath is an arbitrary xpath expression
* @param type is a constant obtained from javax.xml.xpath.XPathConstants. Typical values are
* XPathConstants.NUMBER, STRING and BOOLEAN.
*/
public void addXPathProperty(String name, String xpath, QName type)
{
XPathPropertyDesc desc = new XPathPropertyDesc(name, xpath, type);
xPathProperties.put(name, desc);
}
/**
* Adds an event property for which the engine uses the supplied XPath expression against
* a DOM document node to resolve a property value.
* @param name of the event property
* @param xpath is an arbitrary xpath expression
* @param type is a constant obtained from javax.xml.xpath.XPathConstants. Typical values are
* XPathConstants.NUMBER, STRING and BOOLEAN.
* @param castToType is the type name of the type that the return value of the xpath expression is casted to
*/
public void addXPathProperty(String name, String xpath, QName type, String castToType)
{
Class castToTypeClass = null;
if (castToType != null)
{
boolean isArray = false;
if (castToType.trim().endsWith("[]"))
{
isArray = true;
castToType = castToType.replace("[]", "");
}
castToTypeClass = JavaClassHelper.getClassForSimpleName(castToType);
if (castToTypeClass == null) {
throw new ConfigurationException("Invalid cast-to type for xpath expression named '" + name + "', the type is not recognized");
}
if (isArray) {
castToTypeClass = Array.newInstance(castToTypeClass, 0).getClass();
}
}
XPathPropertyDesc desc = new XPathPropertyDesc(name, xpath, type, castToTypeClass);
xPathProperties.put(name, desc);
}
/**
* Adds an event property for which the engine uses the supplied XPath expression against
* a DOM document node to resolve a property value.
* @param name of the event property
* @param xpath is an arbitrary xpath expression
* @param type is a constant obtained from javax.xml.xpath.XPathConstants. Typical values are
* XPathConstants.NODE and XPathConstants.NODESET.
* @param eventTypeName is the name of another event type that represents the XPath nodes
*/
public void addXPathPropertyFragment(String name, String xpath, QName type, String eventTypeName)
{
if ((type != XPathConstants.NODE) && (type != XPathConstants.NODESET))
{
throw new IllegalArgumentException("XPath property for fragments requires an Node or Nodeset (XPathConstants.NODE/NODESET) return value for property '" + name + "'");
}
XPathPropertyDesc desc = new XPathPropertyDesc(name, xpath, type, eventTypeName);
xPathProperties.put(name, desc);
}
/**
* Returns the namespace prefixes in a map of prefix as key and namespace name as value.
* @return namespace prefixes
*/
public Map<String, String> getNamespacePrefixes()
{
return namespacePrefixes;
}
/**
* Add a prefix and namespace name for use in XPath expressions refering to that prefix.
* @param prefix is the prefix of the namespace
* @param namespace is the namespace name
*/
public void addNamespacePrefix(String prefix, String namespace)
{
namespacePrefixes.put(prefix, namespace);
}
/**
* Add prefixes and namespace names for use in XPath expressions refering to that prefix.
* @param prefixNamespaceMap map of prefixes and namespaces
*/
public void addNamespacePrefixes(Map<String, String> prefixNamespaceMap)
{
namespacePrefixes.putAll(prefixNamespaceMap);
}
/**
* Indicates whether properties are compiled into absolute or deep XPath expressions (see setter method for more detail).
* @return true for absolute properties, false for deep properties
*/
public boolean isXPathResolvePropertiesAbsolute()
{
return isXPathResolvePropertiesAbsolute;
}
/**
* When set to true (the default), indicates that when properties are compiled to XPath expressions that the
* compilation should generate an absolute XPath expression such as "/getQuote/request" for the
* simple request property, or "/getQuote/request/symbol" for a "request.symbol" nested property,
* wherein the root element node is "getQuote".
* <p>
* When set to false, indicates that when properties are compiled to XPath expressions that the
* compilation should generate a deep XPath expression such as "//symbol" for the
* simple symbol property, or "//request/symbol" for a "request.symbol" nested property.
* @param XPathResolvePropertiesAbsolute true for absolute XPath for properties (default), false for deep XPath
*/
public void setXPathResolvePropertiesAbsolute(boolean XPathResolvePropertiesAbsolute)
{
this.isXPathResolvePropertiesAbsolute = XPathResolvePropertiesAbsolute;
}
/**
* Returns the class name of the XPath function resolver to be assigned to the XPath factory instance
* upon type initialization.
* @return class name of xpath function resolver, or null if none set
*/
public String getXPathFunctionResolver()
{
return xPathFunctionResolver;
}
/**
* Sets the class name of the XPath function resolver to be assigned to the XPath factory instance
* upon type initialization.
* @param xPathFunctionResolver class name of xpath function resolver, or null if none set
*/
public void setXPathFunctionResolver(String xPathFunctionResolver)
{
this.xPathFunctionResolver = xPathFunctionResolver;
}
/**
* Returns the class name of the XPath variable resolver to be assigned to the XPath factory instance
* upon type initialization.
* @return class name of xpath function resolver, or null if none set
*/
public String getXPathVariableResolver()
{
return xPathVariableResolver;
}
/**
* Sets the class name of the XPath variable resolver to be assigned to the XPath factory instance
* upon type initialization.
* @param xPathVariableResolver class name of xpath function resolver, or null if none set
*/
public void setXPathVariableResolver(String xPathVariableResolver)
{
this.xPathVariableResolver = xPathVariableResolver;
}
/**
* Indicator for use with EsperHA, false by default to indicate that stored type information takes
* precedence over configuration type information provided at engine initialization time. Set to true to indicate that
* configuration type information takes precedence over stored type information.
* @return indicator is false (the default) to indicate that stored type information takes precedence over configuration type information
*/
public boolean isUpdateStoredType() {
return updateStoredType;
}
/**
* Indicator for use with EsperHA, false by default to indicate that stored type information takes
* precedence over configuration type information provided at engine initialization time. Set to true to indicate that
* configuration type information takes precedence over stored type information.
* <p>
* When setting this flag to true care should be taken about the compatibility of the supplied XML type
* configuration information and the existing EPL statements and stored events, if any. For more information
* please consult {@link ConfigurationOperations#replaceXMLEventType(String, ConfigurationEventTypeXMLDOM)}.
* @param updateStoredType set to false (the default) to indicate that stored type information takes precedence over configuration type information
*/
public void setUpdateStoredType(boolean updateStoredType) {
this.updateStoredType = updateStoredType;
}
/**
* Descriptor class for event properties that are resolved via XPath-expression.
*/
public static class XPathPropertyDesc implements Serializable
{
private String name;
private String xpath;
private QName type;
private Class optionalCastToType;
private String optionaleventTypeName;
private static final long serialVersionUID = -4141721949296588319L;
/**
* Ctor.
* @param name is the event property name
* @param xpath is an arbitrary XPath expression
* @param type is a javax.xml.xpath.XPathConstants constant
*/
public XPathPropertyDesc(String name, String xpath, QName type)
{
this.name = name;
this.xpath = xpath;
this.type = type;
}
/**
* Ctor.
* @param name is the event property name
* @param xpath is an arbitrary XPath expression
* @param type is a javax.xml.xpath.XPathConstants constant
* @param optionalCastToType if non-null then the return value of the xpath expression is cast to this value
*/
public XPathPropertyDesc(String name, String xpath, QName type, Class optionalCastToType)
{
this.name = name;
this.xpath = xpath;
this.type = type;
this.optionalCastToType = optionalCastToType;
}
/**
* Ctor.
* @param name is the event property name
* @param xpath is an arbitrary XPath expression
* @param type is a javax.xml.xpath.XPathConstants constant
* @param eventTypeName the name of an event type that represents the fragmented property value
*/
public XPathPropertyDesc(String name, String xpath, QName type, String eventTypeName)
{
this.name = name;
this.xpath = xpath;
this.type = type;
this.optionaleventTypeName = eventTypeName;
}
/**
* Returns the event property name.
* @return event property name
*/
public String getName()
{
return name;
}
/**
* Returns the XPath expression.
* @return XPath expression
*/
public String getXpath()
{
return xpath;
}
/**
* Returns the javax.xml.xpath.XPathConstants constant representing the event property type.
* @return type infomation
*/
public QName getType()
{
return type;
}
/**
* Returns the class that the return value of the xpath expression is cast to, or null if no casting.
* @return class to cast result of xpath expression to
*/
public Class getOptionalCastToType()
{
return optionalCastToType;
}
/**
* Returns the event type name assigned to the explicit property.
* @return type name
*/
public String getOptionaleventTypeName()
{
return optionaleventTypeName;
}
}
/**
* Returns the property name of the property providing the start timestamp value.
* @return start timestamp property name
*/
public String getStartTimestampPropertyName() {
return startTimestampPropertyName;
}
/**
* Sets the property name of the property providing the start timestamp value.
* @param startTimestampPropertyName start timestamp property name
*/
public void setStartTimestampPropertyName(String startTimestampPropertyName) {
this.startTimestampPropertyName = startTimestampPropertyName;
}
/**
* Returns the property name of the property providing the end timestamp value.
* @return end timestamp property name
*/
public String getEndTimestampPropertyName() {
return endTimestampPropertyName;
}
/**
* Sets the property name of the property providing the end timestamp value.
* @param endTimestampPropertyName start timestamp property name
*/
public void setEndTimestampPropertyName(String endTimestampPropertyName) {
this.endTimestampPropertyName = endTimestampPropertyName;
}
public boolean equals(Object otherObj)
{
if (!(otherObj instanceof ConfigurationEventTypeXMLDOM))
{
return false;
}
ConfigurationEventTypeXMLDOM other = (ConfigurationEventTypeXMLDOM) otherObj;
if (!(other.rootElementName.equals(rootElementName)))
{
return false;
}
if (((other.rootElementNamespace == null) && (rootElementNamespace != null)) ||
((other.rootElementNamespace != null) && (rootElementNamespace == null)))
{
return false;
}
if ((other.rootElementNamespace != null) && (rootElementNamespace != null))
{
return rootElementNamespace.equals(other.rootElementNamespace);
}
return true;
}
public int hashCode()
{
return rootElementName.hashCode();
}
}