/// <summary> /// Ctor. /// </summary> /// <param name="eventTypeMetadata">event type metadata</param> /// <param name="eventTypeId">The event type id.</param> /// <param name="configurationEventTypeXMLDOM">configures the event type</param> /// <param name="eventAdapterService">for type looking and registration</param> /// <param name="lockManager">The lock manager.</param> public SimpleXElementType( EventTypeMetadata eventTypeMetadata, int eventTypeId, ConfigurationEventTypeXMLDOM configurationEventTypeXMLDOM, EventAdapterService eventAdapterService, ILockManager lockManager) : base(eventTypeMetadata, eventTypeId, configurationEventTypeXMLDOM, eventAdapterService, lockManager) { _isResolvePropertiesAbsolute = configurationEventTypeXMLDOM.IsXPathResolvePropertiesAbsolute; // Set of namespace context for XPath expressions var namespaceContext = new XPathNamespaceContext(); foreach (var entry in configurationEventTypeXMLDOM.NamespacePrefixes) { namespaceContext.AddNamespace(entry.Key, entry.Value); } if (configurationEventTypeXMLDOM.DefaultNamespace != null) { var defaultNamespace = configurationEventTypeXMLDOM.DefaultNamespace; namespaceContext.AddNamespace(String.Empty, defaultNamespace); // determine a default namespace prefix to use to construct XPath expressions from pure property names _defaultNamespacePrefix = null; foreach (var entry in configurationEventTypeXMLDOM.NamespacePrefixes) { if (Equals(entry.Value, defaultNamespace)) { _defaultNamespacePrefix = entry.Key; break; } } } NamespaceContext = namespaceContext; Initialize( configurationEventTypeXMLDOM.XPathProperties.Values, Collections.GetEmptyList <ExplicitPropertyDescriptor>()); _propertyGetterCache = new Dictionary <String, EventPropertyGetterSPI>(); }
/// <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)); }
/// <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); }