예제 #1
0
        /// <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));
        }
예제 #2
0
        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);
        }