private static Pair <String, XPathResultType> MakeAttributeProperty(SchemaItemAttribute attribute, Property property, XPathNamespaceContext ctx) { var prefix = ctx.LookupPrefix(attribute.Namespace); if (String.IsNullOrEmpty(prefix)) { prefix = ""; } else { prefix += ':'; } if (IsAnySimpleProperty(property)) { XPathResultType type = SchemaUtil.SimpleTypeToResultType(attribute.SimpleType); String path = "/@" + prefix + property.PropertyNameAtomic; return(new Pair <String, XPathResultType>(path, type)); } if (IsAnyMappedProperty(property)) { throw new Exception("Mapped properties not applicable to attributes"); } throw new Exception("Indexed properties not applicable to attributes"); }
public Object Get(EventBean eventBean) { var und = eventBean.Underlying; if (und == null) { throw new PropertyAccessException( "Unexpected null underlying event encountered, expecting System.Xml.XmlNode instance as underlying"); } XPathNavigator navigator; var xnode = und as XElement; if (xnode == null) { var node = und as XmlNode; if (node == null) { throw new PropertyAccessException("Unexpected underlying event of type '" + und.GetType().FullName + "' encountered, expecting System.Xml.XmlNode as underlying"); } if (Log.IsDebugEnabled) { Log.Debug( "Running XPath '{0}' for property '{1}' against Node XML : {2}", _expressionText, _property, SchemaUtil.Serialize((XmlNode)und)); } navigator = node.CreateNavigator(); } else { navigator = xnode.CreateNavigator(); } return(EvaluateXPathGet( navigator, _expression, _expressionText, _property, _optionalCastToType, _resultType, _isCastToArray, _simpleTypeParser)); }
private static Pair <String, XPathResultType> MakeProperty(SchemaElementComplex parent, Property property, XPathNamespaceContext ctx, bool isLast, bool isDynamic, String defaultNamespacePrefix) { var text = property.PropertyNameAtomic; var obj = SchemaUtil.FindPropertyMapping(parent, text); if ((obj is SchemaElementSimple) || (obj is SchemaElementComplex)) { return(MakeElementProperty((SchemaElement)obj, property, ctx, isLast, isDynamic, defaultNamespacePrefix)); } if (obj != null) { return(MakeAttributeProperty((SchemaItemAttribute)obj, property, ctx)); } if (isDynamic) { return(MakeElementProperty(null, property, ctx, isLast, isDynamic, defaultNamespacePrefix)); } return(null); }
private Type DoResolvePropertyType(String propertyExpression, bool allowSimpleProperties) { // see if this is an indexed property int index = ASTUtil.UnescapedIndexOfDot(propertyExpression); if ((!allowSimpleProperties) && (index == -1)) { // parse, can be an indexed property Property property = PropertyParser.ParseAndWalkLaxToSimple(propertyExpression); if (!property.IsDynamic) { if (!(property is IndexedProperty)) { return(null); } var indexedProp = (IndexedProperty)property; EventPropertyDescriptor descriptor = PropertyDescriptorMap.Get(indexedProp.PropertyNameAtomic); if (descriptor == null) { return(null); } return(descriptor.PropertyType); } } Property prop = PropertyParser.ParseAndWalkLaxToSimple(propertyExpression); if (prop.IsDynamic) { return(typeof(XmlNode)); } SchemaItem item = prop.GetPropertyTypeSchema(_schemaModelRoot, EventAdapterService); if (item == null) { return(null); } return(SchemaUtil.ToReturnType(item)); }
/// <summary> /// Return the xPath corresponding to the given property. The PropertyName String /// may be simple, nested, indexed or mapped. /// </summary> /// <param name="propertyName">is the event property name</param> /// <param name="namespace">is the default namespace</param> /// <param name="schemaModel">is the schema model</param> /// <param name="xPathContext">is the xpath factory instance to use</param> /// <param name="rootElementName">is the name of the root element</param> /// <param name="eventAdapterService">for type lookup and creation</param> /// <param name="xmlEventType">the resolving type</param> /// <param name="isAllowFragment">whether fragmenting is allowed</param> /// <param name="defaultNamespace">default namespace</param> /// <returns> /// xpath expression /// </returns> /// <throws>EPException is there are XPath errors</throws> public static EventPropertyGetter GetXPathResolution(String propertyName, XPathNamespaceContext xPathContext, String rootElementName, String @namespace, SchemaModel schemaModel, EventAdapterService eventAdapterService, BaseXMLEventType xmlEventType, bool isAllowFragment, String defaultNamespace) { if (Log.IsDebugEnabled) { Log.Debug("Determining XPath expression for property '" + propertyName + "'"); } var ctx = new XPathNamespaceContext(); var namespaces = schemaModel.Namespaces; string defaultNamespacePrefix = null; for (int i = 0; i < namespaces.Count; i++) { var namespacePrefix = "n" + i; ctx.AddNamespace(namespacePrefix, namespaces[i]); if ((defaultNamespace != null) && (defaultNamespace == namespaces[i])) { defaultNamespacePrefix = namespacePrefix; } } Property property = PropertyParser.ParseAndWalk(propertyName); var isDynamic = property.IsDynamic; var rootComplexElement = SchemaUtil.FindRootElement(schemaModel, @namespace, rootElementName); string prefix = ctx.LookupPrefix(rootComplexElement.Namespace); if (prefix == null) { prefix = ""; } else { prefix += ':'; } var xPathBuf = new StringBuilder(); xPathBuf.Append('/'); xPathBuf.Append(prefix); if (rootElementName.StartsWith("//")) { xPathBuf.Append(rootElementName.Substring(2)); } else { xPathBuf.Append(rootElementName); } var parentComplexElement = rootComplexElement; Pair <String, XPathResultType> pair = null; if (!(property is NestedProperty)) { pair = MakeProperty(rootComplexElement, property, ctx, true, isDynamic, defaultNamespacePrefix); if (pair == null) { throw new PropertyAccessException("Failed to locate property '" + propertyName + "' in schema"); } xPathBuf.Append(pair.First); } else { NestedProperty nestedProperty = (NestedProperty)property; int indexLast = nestedProperty.Properties.Count - 1; for (int i = 0; i < indexLast + 1; i++) { var isLast = i == indexLast; var propertyNested = nestedProperty.Properties[i]; pair = MakeProperty(parentComplexElement, propertyNested, ctx, isLast, isDynamic, defaultNamespacePrefix); if (pair == null) { throw new PropertyAccessException("Failed to locate property '" + propertyName + "' nested property part '" + property.PropertyNameAtomic + "' in schema"); } var text = propertyNested.PropertyNameAtomic; var obj = SchemaUtil.FindPropertyMapping(parentComplexElement, text); if (obj is SchemaElementComplex) { parentComplexElement = (SchemaElementComplex)obj; } xPathBuf.Append(pair.First); } } var xPath = xPathBuf.ToString(); if ((ExecutionPathDebugLog.IsEnabled) && (Log.IsDebugEnabled)) { Log.Debug(".parse XPath for property '" + propertyName + "' is expression=" + xPath); } // Compile assembled XPath expression if (Log.IsDebugEnabled) { Log.Debug("Compiling XPath expression '" + xPath + "' for property '" + propertyName + "' using namespace context :" + ctx); } XPathExpression expr; try { expr = XPathExpression.Compile(xPath, ctx); } catch (XPathException e) { String detail = "Error constructing XPath expression from property expression '" + propertyName + "' expression '" + xPath + "'"; if (e.Message != null) { throw new EPException(detail + " :" + e.Message, e); } throw new EPException(detail, e); } // get type var item = property.GetPropertyTypeSchema(rootComplexElement, eventAdapterService); if ((item == null) && (!isDynamic)) { return(null); } var resultType = isDynamic ? typeof(XmlNode) : SchemaUtil.ToReturnType(item); FragmentFactory fragmentFactory = null; if (isAllowFragment) { fragmentFactory = new FragmentFactoryDOMGetter(eventAdapterService, xmlEventType, propertyName); } return(new XPathPropertyGetter(propertyName, xPath, expr, pair.Second, resultType, fragmentFactory)); }
private static Pair <String, XPathResultType> MakeElementProperty(SchemaElement schemaElement, Property property, XPathNamespaceContext ctx, bool isAlone, bool isDynamic, String defaultNamespacePrefix) { XPathResultType type; if (isDynamic) { type = XPathResultType.Any; } else if (schemaElement is SchemaElementSimple) { var element = (SchemaElementSimple)schemaElement; type = SchemaUtil.SimpleTypeToResultType(element.SimpleType); } else { var complex = (SchemaElementComplex)schemaElement; type = XPathResultType.Any; //if (complex.OptionalSimpleType != null) //{ // type = SchemaUtil.SimpleTypeToQName(complex.OptionalSimpleType); //} //else //{ // // The result is a node // type = XPathResultType.Any; //} } var prefix = isDynamic ? defaultNamespacePrefix : ctx.LookupPrefix(schemaElement.Namespace); if (String.IsNullOrEmpty(prefix)) { prefix = String.Empty; } else { prefix += ':'; } if (IsAnySimpleProperty(property)) { if (!isDynamic && schemaElement.IsArray && !isAlone) { throw new PropertyAccessException("Simple property not allowed in repeating elements at '" + schemaElement.Name + "'"); } return(new Pair <String, XPathResultType>('/' + prefix + property.PropertyNameAtomic, type)); } if (IsAnyMappedProperty(property)) { if (!isDynamic && !schemaElement.IsArray) { throw new PropertyAccessException("Element " + property.PropertyNameAtomic + " is not a collection, cannot be used as mapped property"); } String key = GetMappedPropertyKey(property); return(new Pair <String, XPathResultType>('/' + prefix + property.PropertyNameAtomic + "[@id='" + key + "']", type)); } if (!isDynamic && !schemaElement.IsArray) { throw new PropertyAccessException("Element " + property.PropertyNameAtomic + " is not a collection, cannot be used as mapped property"); } int index = GetIndexedPropertyIndex(property); int xPathPosition = index + 1; return(new Pair <String, XPathResultType>('/' + prefix + property.PropertyNameAtomic + "[position() = " + xPathPosition + ']', type)); }
/// <summary> /// Set the preconfigured event properties resolved by XPath expression. /// </summary> /// <param name="explicitXPathProperties">are preconfigured event properties</param> /// <param name="additionalSchemaProperties">the explicit properties</param> protected void Initialize(ICollection <ConfigurationEventTypeXMLDOM.XPathPropertyDesc> explicitXPathProperties, IList <ExplicitPropertyDescriptor> additionalSchemaProperties) { // make sure we override those explicitly provided with those derived from a metadataz var namedProperties = new LinkedHashMap <String, ExplicitPropertyDescriptor>(); foreach (ExplicitPropertyDescriptor desc in additionalSchemaProperties) { namedProperties[desc.Descriptor.PropertyName] = desc; } String xPathExpression = null; try { foreach (ConfigurationEventTypeXMLDOM.XPathPropertyDesc property in explicitXPathProperties) { xPathExpression = property.XPath; if (Log.IsInfoEnabled) { Log.Info("Compiling XPath expression for property '" + property.Name + "' as '" + xPathExpression + "'"); } var expressionContext = NamespaceContext ?? GetExtendedContext(); var expression = XPathExpression.Compile(xPathExpression, expressionContext); FragmentFactoryXPathPredefinedGetter fragmentFactory = null; var isFragment = false; if (property.OptionalEventTypeName != null) { fragmentFactory = new FragmentFactoryXPathPredefinedGetter( EventAdapterService, property.OptionalEventTypeName, property.Name); isFragment = true; } var getter = new XPathPropertyGetter( property.Name, xPathExpression, expression, property.ResultType, property.OptionalCastToType, fragmentFactory); var returnType = SchemaUtil.ToReturnType( property.ResultType, property.OptionalCastToType.GetBoxedType()); var indexType = returnType.GetIndexType(); var isIndexed = indexType != null; if (property.ResultType == XPathResultType.NodeSet) { isIndexed = true; } var desc = new EventPropertyDescriptor( property.Name, returnType, indexType, false, false, isIndexed, false, isFragment); var @explicit = new ExplicitPropertyDescriptor( desc, getter, isIndexed, property.OptionalEventTypeName); namedProperties[desc.PropertyName] = @explicit; } } catch (XPathException ex) { throw new EPException( "XPath expression could not be compiled for expression '" + xPathExpression + '\'', ex); } Initialize(namedProperties.Values); // evaluate start and end timestamp properties if any _startTimestampPropertyName = ConfigurationEventTypeXMLDOM.StartTimestampPropertyName; _endTimestampPropertyName = ConfigurationEventTypeXMLDOM.EndTimestampPropertyName; EventTypeUtility.ValidateTimestampProperties(this, _startTimestampPropertyName, _endTimestampPropertyName); }
/// <summary> /// Ctor. /// </summary> /// <param name="eventTypeMetadata">event type metadata</param> /// <param name="eventTypeId">The event type id.</param> /// <param name="config">configuration for type</param> /// <param name="schemaModel">the schema representation</param> /// <param name="eventAdapterService">type lookup and registration</param> public SchemaXMLEventType(EventTypeMetadata eventTypeMetadata, int eventTypeId, ConfigurationEventTypeXMLDOM config, SchemaModel schemaModel, EventAdapterService eventAdapterService) : base(eventTypeMetadata, eventTypeId, config, eventAdapterService) { _propertyGetterCache = new Dictionary <String, EventPropertyGetter>(); _schemaModel = schemaModel; _rootElementNamespace = config.RootElementNamespace; _schemaModelRoot = SchemaUtil.FindRootElement(schemaModel, _rootElementNamespace, RootElementName); _isPropertyExpressionXPath = config.IsXPathPropertyExpr; // Set of namespace context for XPath expressions var ctx = new XPathNamespaceContext(); if (config.DefaultNamespace != null) { ctx.SetDefaultNamespace(config.DefaultNamespace); } foreach (var entry in config.NamespacePrefixes) { ctx.AddNamespace(entry.Key, entry.Value); } NamespaceContext = ctx; // add properties for the root element var additionalSchemaProps = new List <ExplicitPropertyDescriptor>(); // Add a property for each complex child element foreach (SchemaElementComplex complex in _schemaModelRoot.ComplexElements) { var propertyName = complex.Name; var returnType = typeof(XmlNode); Type propertyComponentType = null; if (complex.OptionalSimpleType != null) { returnType = SchemaUtil.ToReturnType(complex); } if (complex.IsArray) { // We use XmlNode[] for arrays and NodeList for XPath-Expressions returning Nodeset returnType = typeof(XmlNode[]); propertyComponentType = typeof(XmlNode); } bool isFragment = false; if (ConfigurationEventTypeXMLDOM.IsAutoFragment && (!ConfigurationEventTypeXMLDOM.IsXPathPropertyExpr)) { isFragment = CanFragment(complex); } var indexType = returnType.GetIndexType(); var isIndexed = indexType != null; var getter = DoResolvePropertyGetter(propertyName, true); var desc = new EventPropertyDescriptor(propertyName, returnType, indexType, false, false, isIndexed, false, isFragment); var @explicit = new ExplicitPropertyDescriptor(desc, getter, false, null); additionalSchemaProps.Add(@explicit); } // Add a property for each simple child element foreach (SchemaElementSimple simple in _schemaModelRoot.SimpleElements) { var propertyName = simple.Name; var returnType = SchemaUtil.ToReturnType(simple); var getter = DoResolvePropertyGetter(propertyName, true); var indexType = returnType.GetIndexType(); var isIndexed = indexType != null; var desc = new EventPropertyDescriptor(propertyName, returnType, indexType, false, false, isIndexed, false, false); var @explicit = new ExplicitPropertyDescriptor(desc, getter, false, null); additionalSchemaProps.Add(@explicit); } // Add a property for each attribute foreach (SchemaItemAttribute attribute in _schemaModelRoot.Attributes) { var propertyName = attribute.Name; var returnType = SchemaUtil.ToReturnType(attribute); var getter = DoResolvePropertyGetter(propertyName, true); var indexType = returnType.GetIndexType(); var isIndexed = indexType != null; var desc = new EventPropertyDescriptor(propertyName, returnType, indexType, false, false, isIndexed, false, false); var @explicit = new ExplicitPropertyDescriptor(desc, getter, false, null); additionalSchemaProps.Add(@explicit); } // Finally add XPath properties as that may depend on the rootElementNamespace Initialize(config.XPathProperties.Values, additionalSchemaProps); }
private EventPropertyGetter DoResolvePropertyGetter(String propertyExpression, bool allowSimpleProperties) { EventPropertyGetter getter = _propertyGetterCache.Get(propertyExpression); if (getter != null) { return(getter); } if (!allowSimpleProperties) { // see if this is an indexed property int index = ASTUtil.UnescapedIndexOfDot(propertyExpression); if (index == -1) { // parse, can be an indexed property Property property = PropertyParser.ParseAndWalkLaxToSimple(propertyExpression); if (!property.IsDynamic) { if (!(property is IndexedProperty)) { return(null); } var indexedProp = (IndexedProperty)property; getter = PropertyGetters.Get(indexedProp.PropertyNameAtomic); if (null == getter) { return(null); } EventPropertyDescriptor descriptor = PropertyDescriptorMap.Get(indexedProp.PropertyNameAtomic); if (descriptor == null) { return(null); } if (!descriptor.IsIndexed) { return(null); } if (descriptor.PropertyType == typeof(XmlNodeList)) { FragmentFactory fragmentFactory = new FragmentFactoryDOMGetter( EventAdapterService, this, indexedProp.PropertyNameAtomic); return(new XPathPropertyArrayItemGetter(getter, indexedProp.Index, fragmentFactory)); } if (descriptor.PropertyType == typeof(string)) { FragmentFactory fragmentFactory = new FragmentFactoryDOMGetter( EventAdapterService, this, indexedProp.PropertyNameAtomic); return(new XPathPropertyArrayItemGetter(getter, indexedProp.Index, fragmentFactory)); } } } } if (!_isPropertyExpressionXPath) { Property prop = PropertyParser.ParseAndWalkLaxToSimple(propertyExpression); bool isDynamic = prop.IsDynamic; if (!isDynamic) { SchemaItem item = prop.GetPropertyTypeSchema(_schemaModelRoot, EventAdapterService); if (item == null) { return(null); } getter = prop.GetGetterDOM(_schemaModelRoot, EventAdapterService, this, propertyExpression); if (getter == null) { return(null); } Type returnType = SchemaUtil.ToReturnType(item); if ((returnType != typeof(XmlNode)) && (returnType != typeof(XmlNodeList))) { if (!returnType.IsArray) { getter = new DOMConvertingGetter(propertyExpression, (DOMPropertyGetter)getter, returnType); } else { getter = new DOMConvertingArrayGetter((DOMPropertyGetter)getter, returnType.GetElementType()); } } } else { return(prop.GetGetterDOM()); } } else { bool allowFragments = !ConfigurationEventTypeXMLDOM.IsXPathPropertyExpr; getter = SchemaXMLPropertyParser.GetXPathResolution( propertyExpression, NamespaceContext, RootElementName, _rootElementNamespace, _schemaModel, EventAdapterService, this, allowFragments, ConfigurationEventTypeXMLDOM.DefaultNamespace); } _propertyGetterCache.Put(propertyExpression, getter); return(getter); }
public Object Get(EventBean eventBean) { var und = eventBean.Underlying; if (und == null) { throw new PropertyAccessException("Unexpected null underlying event encountered, expecting System.Xml.XmlNode instance as underlying"); } XPathNavigator navigator; var xnode = und as XElement; if (xnode == null) { var node = und as XmlNode; if (node == null) { throw new PropertyAccessException("Unexpected underlying event of type '" + und.GetType().FullName + "' encountered, expecting System.Xml.XmlNode as underlying"); } if (Log.IsDebugEnabled) { Log.Debug( "Running XPath '{0}' for property '{1}' against Node XML : {2}", _expressionText, _property, SchemaUtil.Serialize((XmlNode)und)); } navigator = node.CreateNavigator(); } else { navigator = xnode.CreateNavigator(); } try { var result = navigator.Evaluate(_expression); if (result == null) { return(null); } // if there is no parser, return xpath expression type if (_optionalCastToType == null) { var nodeIterator = result as XPathNodeIterator; if (nodeIterator != null) { if (nodeIterator.Count == 0) { return(null); } if (nodeIterator.Count == 1) { nodeIterator.MoveNext(); switch (_resultType) { case XPathResultType.Any: return(((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode()); case XPathResultType.String: return(nodeIterator.Current.TypedValue); case XPathResultType.Boolean: return(nodeIterator.Current.ValueAsBoolean); case XPathResultType.Number: return(nodeIterator.Current.ValueAsDouble); default: return(nodeIterator.Current.TypedValue); } } else { return(new XPathIteratorNodeList(nodeIterator)); } } return(result); } if (_isCastToArray) { return(CastToArray(result)); } if (result is XPathNodeIterator) { var nodeIterator = result as XPathNodeIterator; if (nodeIterator.Count == 0) { return(null); } if (nodeIterator.Count == 1) { nodeIterator.MoveNext(); result = nodeIterator.Current.TypedValue; } else { if (_simpleTypeParser == null) { var resultList = new List <object>(); while (nodeIterator.MoveNext()) { result = nodeIterator.Current.TypedValue; resultList.Add(result); } return(resultList.ToArray()); } else { throw new NotImplementedException(); } } } // string results get parsed if (result is String) { try { return(_simpleTypeParser.Invoke((string)result)); } catch { Log.Warn("Error parsing XPath property named '" + _property + "' expression result '" + result + " as type " + _optionalCastToType.Name); return(null); } } // coercion if (result is Double) { try { return(CoercerFactory.CoerceBoxed(result, _optionalCastToType)); } catch { Log.Warn("Error coercing XPath property named '" + _property + "' expression result '" + result + " as type " + _optionalCastToType.Name); return(null); } } // check bool type if (result is Boolean) { if (_optionalCastToType != typeof(bool?)) { Log.Warn("Error coercing XPath property named '" + _property + "' expression result '" + result + " as type " + _optionalCastToType.Name); return(null); } return(result); } Log.Warn("Error processing XPath property named '" + _property + "' expression result '" + result + ", not a known type"); return(null); } catch (XPathException e) { throw new PropertyAccessException("Error getting property " + _property, e); } }
public Object GetFragment(EventBean eventBean) { if (_fragmentFactory == null) { return(null); } Object und = eventBean.Underlying; if (und == null) { throw new PropertyAccessException("Unexpected null underlying event encountered, expecting System.Xml.XmlNode instance as underlying"); } var node = und as XmlNode; if (node == null) { throw new PropertyAccessException("Unexpected underlying event of type '" + und.GetType().FullName + "' encountered, expecting System.Xml.XmlNode as underlying"); } try { if (Log.IsDebugEnabled) { Log.Debug( "Running XPath '{0}' for property '{1}' against Node XML : {2}", _expressionText, _property, SchemaUtil.Serialize((XmlNode)und)); } var navigator = node.CreateNavigator(); var result = navigator.Evaluate(_expression); if (result == null) { return(null); } if (result is XPathNodeIterator) { var nodeIterator = result as XPathNodeIterator; if (nodeIterator.Count == 0) { return(null); } if (nodeIterator.Count == 1) { nodeIterator.MoveNext(); return(_fragmentFactory.GetEvent(((IHasXmlNode)nodeIterator.Current).GetNode())); } var events = new List <EventBean>(); while (nodeIterator.MoveNext()) { events.Add(_fragmentFactory.GetEvent(((IHasXmlNode)nodeIterator.Current).GetNode())); } return(events.ToArray()); } Log.Warn("Error processing XPath property named '" + _property + "' expression result is not of type Node or Nodeset"); return(null); } catch (XPathException e) { throw new PropertyAccessException("Error getting property " + _property, e); } }