/* *************************************************************************************** * 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.ConfigurationEventTypeXMLDOM; import com.espertech.esper.client.EPException; import com.espertech.esper.client.EventPropertyGetter; import com.espertech.esper.client.FragmentEventType; import com.espertech.esper.epl.generated.EsperEPL2GrammarParser; import com.espertech.esper.event.EventAdapterService; import com.espertech.esper.event.EventTypeMetadata; import com.espertech.esper.event.property.Property; import com.espertech.esper.event.property.PropertyParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.xml.namespace.QName; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * 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. * <p> * If an xsd is present, then use {@link com.espertech.esper.event.xml.SchemaXMLEventType SchemaXMLEventType } * * @author pablo */ public class SimpleXMLEventType extends BaseXMLEventType { private static final Logger log = LoggerFactory.getLogger(SimpleXMLEventType.class); private final Map<String, EventPropertyGetter> propertyGetterCache; private String defaultNamespacePrefix; private final boolean isResolvePropertiesAbsolute; /** * Ctor. * * @param configurationEventTypeXMLDOM configures the event type * @param eventTypeMetadata event type metadata * @param eventAdapterService for type looking and registration * @param eventTypeId type id */ public SimpleXMLEventType(EventTypeMetadata eventTypeMetadata, int eventTypeId, ConfigurationEventTypeXMLDOM configurationEventTypeXMLDOM, EventAdapterService eventAdapterService) { super(eventTypeMetadata, eventTypeId, configurationEventTypeXMLDOM, eventAdapterService); isResolvePropertiesAbsolute = configurationEventTypeXMLDOM.isXPathResolvePropertiesAbsolute(); propertyGetterCache = new HashMap<String, EventPropertyGetter>(); // Set of namespace context for XPath expressions XPathNamespaceContext xPathNamespaceContext = new XPathNamespaceContext(); for (Map.Entry<String, String> entry : configurationEventTypeXMLDOM.getNamespacePrefixes().entrySet()) { xPathNamespaceContext.addPrefix(entry.getKey(), entry.getValue()); } if (configurationEventTypeXMLDOM.getDefaultNamespace() != null) { String defaultNamespace = configurationEventTypeXMLDOM.getDefaultNamespace(); xPathNamespaceContext.setDefaultNamespace(defaultNamespace); // determine a default namespace prefix to use to construct XPath expressions from pure property names defaultNamespacePrefix = null; for (Map.Entry<String, String> entry : configurationEventTypeXMLDOM.getNamespacePrefixes().entrySet()) { if (entry.getValue().equals(defaultNamespace)) { defaultNamespacePrefix = entry.getKey(); break; } } } super.setNamespaceContext(xPathNamespaceContext); super.initialize(configurationEventTypeXMLDOM.getXPathProperties().values(), Collections.EMPTY_LIST); } protected Class doResolvePropertyType(String propertyExpression) { EsperEPL2GrammarParser.StartEventPropertyRuleContext ast = PropertyParser.parse(propertyExpression); if (PropertyParser.isPropertyDynamic(ast)) { return org.w3c.dom.Node.class; } else { return String.class; } } protected EventPropertyGetter doResolvePropertyGetter(String propertyExpression) { EventPropertyGetter getter = propertyGetterCache.get(propertyExpression); if (getter != null) { return getter; } if (!this.getConfigurationEventTypeXMLDOM().isXPathPropertyExpr()) { Property prop = PropertyParser.parseAndWalkLaxToSimple(propertyExpression); getter = prop.getGetterDOM(); if (!prop.isDynamic()) { getter = new DOMConvertingGetter(propertyExpression, (DOMPropertyGetter) getter, String.class); } } else { XPathExpression xPathExpression; String xPathExpr; boolean isDynamic; try { EsperEPL2GrammarParser.StartEventPropertyRuleContext ast = PropertyParser.parse(propertyExpression); isDynamic = PropertyParser.isPropertyDynamic(ast); xPathExpr = SimpleXMLPropertyParser.walk(ast, propertyExpression, getRootElementName(), defaultNamespacePrefix, isResolvePropertiesAbsolute); XPath xpath = getXPathFactory().newXPath(); xpath.setNamespaceContext(namespaceContext); if (log.isInfoEnabled()) { log.info("Compiling XPath expression for property '" + propertyExpression + "' as '" + xPathExpr + "'"); } xPathExpression = xpath.compile(xPathExpr); } catch (XPathExpressionException e) { throw new EPException("Error constructing XPath expression from property name '" + propertyExpression + '\'', e); } QName xPathReturnType; if (isDynamic) { xPathReturnType = XPathConstants.NODE; } else { xPathReturnType = XPathConstants.STRING; } getter = new XPathPropertyGetter(propertyExpression, xPathExpr, xPathExpression, xPathReturnType, null, null); } // no fragment factory, fragments not allowed propertyGetterCache.put(propertyExpression, getter); return getter; } protected FragmentEventType doResolveFragmentType(String property) { return null; // Since we have no type information, the fragments are not allowed unless explicitly configured via XPath getter } }