/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* 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.event.xml;
import com.espertech.esper.client.*;
import com.espertech.esper.client.util.ClassForNameProviderDefault;
import com.espertech.esper.event.*;
import com.espertech.esper.util.ClassInstantiationException;
import com.espertech.esper.util.JavaClassHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import javax.xml.xpath.*;
import java.util.*;
/**
* Base class for XML event types.
*/
public abstract class BaseXMLEventType extends BaseConfigurableEventType {
private static final Logger log = LoggerFactory.getLogger(BaseXMLEventType.class);
private final XPathFactory xPathFactory;
private final String rootElementName;
private final ConfigurationEventTypeXMLDOM configurationEventTypeXMLDOM;
private String startTimestampPropertyName;
private String endTimestampPropertyName;
/**
* XPath namespace context.
*/
protected XPathNamespaceContext namespaceContext;
/**
* Ctor.
*
* @param configurationEventTypeXMLDOM is the XML DOM configuration such as root element and schema names
* @param metadata event type metadata
* @param eventAdapterService for registration and lookup of types
* @param eventTypeId type id
*/
public BaseXMLEventType(EventTypeMetadata metadata, int eventTypeId, ConfigurationEventTypeXMLDOM configurationEventTypeXMLDOM, EventAdapterService eventAdapterService) {
super(eventAdapterService, metadata, eventTypeId, Node.class);
this.rootElementName = configurationEventTypeXMLDOM.getRootElementName();
this.configurationEventTypeXMLDOM = configurationEventTypeXMLDOM;
xPathFactory = XPathFactory.newInstance();
if (configurationEventTypeXMLDOM.getXPathFunctionResolver() != null) {
try {
XPathFunctionResolver fresolver = (XPathFunctionResolver) JavaClassHelper.instantiate(XPathFunctionResolver.class, configurationEventTypeXMLDOM.getXPathFunctionResolver(), ClassForNameProviderDefault.INSTANCE);
xPathFactory.setXPathFunctionResolver(fresolver);
} catch (ClassInstantiationException ex) {
throw new ConfigurationException("Error configuring XPath function resolver for XML type '" + configurationEventTypeXMLDOM.getRootElementName() + "' : " + ex.getMessage(), ex);
}
}
if (configurationEventTypeXMLDOM.getXPathVariableResolver() != null) {
try {
XPathVariableResolver vresolver = (XPathVariableResolver) JavaClassHelper.instantiate(XPathVariableResolver.class, configurationEventTypeXMLDOM.getXPathVariableResolver(), ClassForNameProviderDefault.INSTANCE);
xPathFactory.setXPathVariableResolver(vresolver);
} catch (ClassInstantiationException ex) {
throw new ConfigurationException("Error configuring XPath variable resolver for XML type '" + configurationEventTypeXMLDOM.getRootElementName() + "' : " + ex.getMessage(), ex);
}
}
}
/**
* Returns the name of the root element.
*
* @return root element name
*/
public String getRootElementName() {
return rootElementName;
}
/**
* Sets the namespace context for use in XPath expression resolution.
*
* @param namespaceContext for XPath expressions
*/
protected void setNamespaceContext(XPathNamespaceContext namespaceContext) {
this.namespaceContext = namespaceContext;
}
/**
* Set the preconfigured event properties resolved by XPath expression.
*
* @param explicitXPathProperties are preconfigured event properties
* @param additionalSchemaProperties the explicit properties
*/
protected void initialize(Collection<ConfigurationEventTypeXMLDOM.XPathPropertyDesc> explicitXPathProperties,
List<ExplicitPropertyDescriptor> additionalSchemaProperties) {
// make sure we override those explicitly provided with those derived from a metadataz
Map<String, ExplicitPropertyDescriptor> namedProperties = new LinkedHashMap<String, ExplicitPropertyDescriptor>();
for (ExplicitPropertyDescriptor desc : additionalSchemaProperties) {
namedProperties.put(desc.getDescriptor().getPropertyName(), desc);
}
String xpathExpression = null;
try {
for (ConfigurationEventTypeXMLDOM.XPathPropertyDesc property : explicitXPathProperties) {
XPath xPath = xPathFactory.newXPath();
if (namespaceContext != null) {
xPath.setNamespaceContext(namespaceContext);
}
xpathExpression = property.getXpath();
if (log.isInfoEnabled()) {
log.info("Compiling XPath expression for property '" + property.getName() + "' as '" + xpathExpression + "'");
}
XPathExpression expression = xPath.compile(xpathExpression);
FragmentFactoryXPathPredefinedGetter fragmentFactory = null;
boolean isFragment = false;
if (property.getOptionaleventTypeName() != null) {
fragmentFactory = new FragmentFactoryXPathPredefinedGetter(this.getEventAdapterService(), property.getOptionaleventTypeName(), property.getName());
isFragment = true;
}
boolean isArray = false;
if (property.getType().equals(XPathConstants.NODESET)) {
isArray = true;
}
EventPropertyGetter getter = new XPathPropertyGetter(property.getName(), xpathExpression, expression, property.getType(), property.getOptionalCastToType(), fragmentFactory);
Class returnType = SchemaUtil.toReturnType(property.getType(), property.getOptionalCastToType());
EventPropertyDescriptor desc = new EventPropertyDescriptor(property.getName(), returnType, null, false, false, isArray, false, isFragment);
ExplicitPropertyDescriptor explicit = new ExplicitPropertyDescriptor(desc, getter, isArray, property.getOptionaleventTypeName());
namedProperties.put(desc.getPropertyName(), explicit);
}
} catch (XPathExpressionException ex) {
throw new EPException("XPath expression could not be compiled for expression '" + xpathExpression + '\'', ex);
}
super.initialize(new ArrayList<ExplicitPropertyDescriptor>(namedProperties.values()));
// evaluate start and end timestamp properties if any
startTimestampPropertyName = configurationEventTypeXMLDOM.getStartTimestampPropertyName();
endTimestampPropertyName = configurationEventTypeXMLDOM.getEndTimestampPropertyName();
EventTypeUtility.validateTimestampProperties(this, startTimestampPropertyName, endTimestampPropertyName);
}
/**
* Returns the XPath factory used.
*
* @return XPath factory
*/
protected XPathFactory getXPathFactory() {
return xPathFactory;
}
public EventType[] getSuperTypes() {
return null;
}
public Iterator<EventType> getDeepSuperTypes() {
return null;
}
/**
* Returns the configuration XML for the XML type.
*
* @return config XML
*/
public ConfigurationEventTypeXMLDOM getConfigurationEventTypeXMLDOM() {
return configurationEventTypeXMLDOM;
}
public boolean equalsCompareType(EventType eventType) {
if (!(eventType instanceof BaseXMLEventType)) {
return false;
}
BaseXMLEventType other = (BaseXMLEventType) eventType;
return configurationEventTypeXMLDOM.equals(other.configurationEventTypeXMLDOM);
}
/**
* Same-Root XML types are actually equivalent.
*
* @param otherObj to compare to
* @return indicator
*/
public boolean equals(Object otherObj) {
if (!(otherObj instanceof BaseXMLEventType)) {
return false;
}
BaseXMLEventType other = (BaseXMLEventType) otherObj;
return configurationEventTypeXMLDOM.equals(other.configurationEventTypeXMLDOM);
}
public int hashCode() {
return configurationEventTypeXMLDOM.hashCode();
}
public EventPropertyWriter getWriter(String propertyName) {
return null;
}
public EventPropertyDescriptor[] getWriteableProperties() {
return new EventPropertyDescriptor[0];
}
public EventBeanCopyMethod getCopyMethod(String[] properties) {
return null;
}
public EventPropertyDescriptor getWritableProperty(String propertyName) {
return null;
}
public EventBeanWriter getWriter(String[] properties) {
return null;
}
public EventBeanReader getReader() {
return null;
}
public String getStartTimestampPropertyName() {
return startTimestampPropertyName;
}
public String getEndTimestampPropertyName() {
return endTimestampPropertyName;
}
}