Beispiel #1
0
        public static void PopulateObject(String operatorName,
                                          int operatorNum,
                                          String dataFlowName,
                                          IDictionary <String, Object> objectProperties,
                                          Object top,
                                          EngineImportService engineImportService,
                                          EPDataFlowOperatorParameterProvider optionalParameterProvider,
                                          IDictionary <String, Object> optionalParameterURIs)
        {
            var applicableClass  = top.GetType();
            var writables        = PropertyHelper.GetWritableProperties(applicableClass);
            var annotatedFields  = TypeHelper.FindAnnotatedFields(applicableClass, typeof(DataFlowOpParameterAttribute));
            var annotatedMethods = TypeHelper.FindAnnotatedMethods(applicableClass, typeof(DataFlowOpParameterAttribute));

            // find catch-all methods
            var catchAllMethods = new LinkedHashSet <MethodInfo>();

            if (annotatedMethods != null)
            {
                foreach (var method in annotatedMethods)
                {
                    var anno = (DataFlowOpParameterAttribute)TypeHelper.GetAnnotations(
                        typeof(DataFlowOpParameterAttribute),
                        method.GetCustomAttributes(true).Cast <Attribute>().ToArray())[0];
                    if (anno.All)
                    {
                        var parameterTypes = method.GetParameterTypes();
                        if ((parameterTypes.Length == 2) &&
                            (parameterTypes[0] == typeof(String)) &&
                            (parameterTypes[1] == typeof(Object)))
                        {
                            catchAllMethods.Add(method);
                            continue;
                        }
                        throw new ExprValidationException("Invalid annotation for catch-call");
                    }
                }
            }

            // map provided values
            foreach (var property in objectProperties)
            {
                var found        = false;
                var propertyName = property.Key;

                // invoke catch-all setters
                foreach (var method in catchAllMethods)
                {
                    try {
                        method.Invoke(top, new Object[] { propertyName, property.Value });
                    }
                    catch (MemberAccessException e)
                    {
                        throw new ExprValidationException("Illegal access invoking method for property '" + propertyName + "' for class " + applicableClass.Name + " method " + method.Name, e);
                    }
                    catch (TargetInvocationException e)
                    {
                        throw new ExprValidationException("Exception invoking method for property '" + propertyName + "' for class " + applicableClass.Name + " method " + method.Name + ": " + e.InnerException.Message, e);
                    }
                    found = true;
                }

                if (propertyName.ToLower() == CLASS_PROPERTY_NAME)
                {
                    continue;
                }

                // use the writeable property descriptor (appropriate setter method) from writing the property
                var descriptor = FindDescriptor(applicableClass, propertyName, writables);
                if (descriptor != null)
                {
                    var coerceProperty = CoerceProperty(propertyName, applicableClass, property.Value, descriptor.PropertyType, engineImportService, false, true);

                    try {
                        descriptor.WriteMethod.Invoke(top, new Object[] { coerceProperty });
                    }
                    catch (ArgumentException e) {
                        throw new ExprValidationException("Illegal argument invoking setter method for property '" + propertyName + "' for class " + applicableClass.Name + " method " + descriptor.WriteMethod.Name + " provided value " + coerceProperty, e);
                    }
                    catch (MemberAccessException e) {
                        throw new ExprValidationException("Illegal access invoking setter method for property '" + propertyName + "' for class " + applicableClass.Name + " method " + descriptor.WriteMethod.Name, e);
                    }
                    catch (TargetInvocationException e) {
                        throw new ExprValidationException("Exception invoking setter method for property '" + propertyName + "' for class " + applicableClass.Name + " method " + descriptor.WriteMethod.Name + ": " + e.InnerException.Message, e);
                    }
                    continue;
                }

                // in .NET, it's common to name fields with an underscore prefix, this modified
                // notation is preserved in the modPropertyName
                var modPropertyName = "_" + propertyName;
                // find the field annotated with <seealso cref="GraphOpProperty" />
                foreach (var annotatedField in annotatedFields)
                {
                    var anno = (DataFlowOpParameterAttribute)TypeHelper.GetAnnotations(
                        typeof(DataFlowOpParameterAttribute),
                        annotatedField.GetCustomAttributes(true).Cast <Attribute>().ToArray())[0];
                    if ((anno.Name == propertyName) || (annotatedField.Name == propertyName) || (annotatedField.Name == modPropertyName))
                    {
                        var coerceProperty = CoerceProperty(
                            propertyName, applicableClass, property.Value, annotatedField.FieldType, engineImportService,
                            true, true);
                        try
                        {
                            annotatedField.SetValue(top, coerceProperty);
                        }
                        catch (Exception e)
                        {
                            throw new ExprValidationException(
                                      "Failed to set field '" + annotatedField.Name + "': " + e.Message, e);
                        }
                        found = true;
                        break;
                    }
                }

                if (found)
                {
                    continue;
                }

                throw new ExprValidationException("Failed to find writable property '" + propertyName + "' for class " + applicableClass);
            }

            // second pass: if a parameter URI - value pairs were provided, check that
            if (optionalParameterURIs != null)
            {
                foreach (var annotatedField in annotatedFields)
                {
                    try {
                        var uri = operatorName + "/" + annotatedField.Name;
                        if (optionalParameterURIs.ContainsKey(uri))
                        {
                            var value = optionalParameterURIs.Get(uri);
                            annotatedField.SetValue(top, value);
                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug("Found parameter '" + uri + "' for data flow " + dataFlowName + " setting " + value);
                            }
                        }
                        else
                        {
                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug("Not found parameter '" + uri + "' for data flow " + dataFlowName);
                            }
                        }
                    }
                    catch (Exception e) {
                        throw new ExprValidationException("Failed to set field '" + annotatedField.Name + "': " + e.Message, e);
                    }
                }

                foreach (var method in annotatedMethods)
                {
                    //var anno = (DataFlowOpParameterAttribute) TypeHelper.GetAnnotations<DataFlowOpParameterAttribute>(method.GetCustomAttributes(false))[0];

                    var anno = method.GetCustomAttributes(typeof(DataFlowOpParameterAttribute), false)
                               .Cast <DataFlowOpParameterAttribute>()
                               .First();

                    if (anno.All)
                    {
                        var parameterTypes = method.GetParameterTypes();
                        if (parameterTypes.Length == 2 && parameterTypes[0] == typeof(string) && parameterTypes[1] == typeof(object))
                        {
                            foreach (var entry in optionalParameterURIs)
                            {
                                var uri      = new Uri(entry.Key, UriKind.RelativeOrAbsolute);
                                var elements = URIUtil.ParsePathElements(uri);
                                if (elements.Length < 2)
                                {
                                    throw new ExprValidationException(string.Format("Failed to parse URI '{0}', expected 'operator_name/property_name' format", entry.Key));
                                }
                                if (elements[0] == operatorName)
                                {
                                    try
                                    {
                                        method.Invoke(top, new Object[] { elements[1], entry.Value });
                                    }
                                    catch (ArgumentException e)
                                    {
                                        throw new ExprValidationException("Illegal argument invoking setter method for property '" + entry.Key + "' for class " + applicableClass.Name + " method " + method.Name, e);
                                    }
                                    catch (MemberAccessException e)
                                    {
                                        throw new ExprValidationException("Illegal access invoking setter method for property '" + entry.Key + "' for class " + applicableClass.Name + " method " + method.Name, e);
                                    }
                                    catch (TargetInvocationException e)
                                    {
                                        throw new ExprValidationException("Exception invoking setter method for property '" + entry.Key + "' for class " + applicableClass.Name + " method " + method.Name + ": " + e.InnerException.Message, e);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // third pass: if a parameter provider is provided, use that
            if (optionalParameterProvider != null)
            {
                foreach (var annotatedField in annotatedFields)
                {
                    try {
                        var provided = annotatedField.GetValue(top);
                        var value    = optionalParameterProvider.Provide(new EPDataFlowOperatorParameterProviderContext(operatorName, annotatedField.Name, top, operatorNum, provided, dataFlowName));
                        if ((value == null) && (annotatedField.Name.StartsWith("_")))
                        {
                            value = optionalParameterProvider.Provide(new EPDataFlowOperatorParameterProviderContext(operatorName, annotatedField.Name.Substring(1), top, operatorNum, provided, dataFlowName));
                        }

                        if (value != null)
                        {
                            annotatedField.SetValue(top, value);
                        }
                    }
                    catch (Exception e) {
                        throw new ExprValidationException("Failed to set field '" + annotatedField.Name + "': " + e.Message, e);
                    }
                }
            }
        }
Beispiel #2
0
        public void TestSortRelevance()
        {
            var uris = new[]
            {
                new object[] { "a/relative/one", -1 },
                new object[] { "other:mailto:test", 0 },
                new object[] { "other://a", 1 },
                new object[] { "type://a/b2/c1", 2 },
                new object[] { "type://a/b3", 3 },
                new object[] { "type://a/b2/c2", 4 },
                new object[] { "type://a", 5 },
                new object[] { "type://x?query#fragment&param", 6 },
                new object[] { "type://a/b1/c1", 7 },
                new object[] { "type://a/b1/c2", 8 },
                new object[] { "type://a/b1/c2/d1", 9 },
                new object[] { "type://a/b2", 10 },
                new object[] { "type://x/a?query#fragment&param", 11 },
                new object[] { "type://x/a/b?query#fragment&param", 12 },
                new object[] { "/a/b/c", 13 },
                new object[] { "/a", 14 },
                new object[] { "//a/b/c", 15 },
                new object[] { "//a", 16 },
            };

            // setup input
            IDictionary <Uri, Object> input = new Dictionary <Uri, Object>();

            foreach (var uri1 in uris)
            {
                var uri2 = new Uri((String)uri1[0], UriKind.RelativeOrAbsolute);
                input.Put(uri2, uri1[1]);
            }

            var uri      = new Uri("type://x/a/b?qqq", UriKind.RelativeOrAbsolute);
            var result   = URIUtil.FilterSort(uri, input);
            var expected = new[]
            {
                "type://x/a/b?query#fragment&param", "type://x/a?query#fragment&param",
                "type://x?query#fragment&param"
            };

            RunAssertion(uri, input, result, expected);

            // unspecific child
            uri      = new Uri("type://a/b2", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "type://a/b2", "type://a" };
            RunAssertion(uri, input, result, expected);

            // very specific child
            uri      = new Uri("type://a/b2/c2/d/e", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "type://a/b2/c2", "type://a/b2", "type://a" };
            RunAssertion(uri, input, result, expected);

            // less specific child
            uri      = new Uri("type://a/b1/c2", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "type://a/b1/c2", "type://a" };
            RunAssertion(uri, input, result, expected);

            // unspecific child
            uri      = new Uri("type://a/b4", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "type://a" };
            RunAssertion(uri, input, result, expected);

            uri      = new Uri("type://b/b1", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new String[] {};
            RunAssertion(uri, input, result, expected);

            uri      = new Uri("type://a/b1/c2/d1/e1/f1", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "type://a/b1/c2/d1", "type://a/b1/c2", "type://a" };
            RunAssertion(uri, input, result, expected);

            uri      = new Uri("other:mailto:test", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "other:mailto:test" };
            RunAssertion(uri, input, result, expected);

            uri      = new Uri("type://x/a?qqq", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "type://x/a?query#fragment&param", "type://x?query#fragment&param" };
            RunAssertion(uri, input, result, expected);

            uri      = new Uri("other://x/a?qqq", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new String[] {};
            RunAssertion(uri, input, result, expected);

            // this is seen as relative, must be a full hit (no path checking)
            uri      = new Uri("/a/b", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new String[] {};
            RunAssertion(uri, input, result, expected);

            // this is seen as relative
            uri      = new Uri("/a/b/c", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "/a/b/c" };
            RunAssertion(uri, input, result, expected);

            // this is seen as relative
            uri      = new Uri("//a/b", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new String[] {};
            RunAssertion(uri, input, result, expected);

            // this is seen as relative
            uri      = new Uri("//a/b/c", UriKind.RelativeOrAbsolute);
            result   = URIUtil.FilterSort(uri, input);
            expected = new[] { "//a/b/c" };
            RunAssertion(uri, input, result, expected);
        }