Merge pull request #961 from ermshiperete/bug-xamarin-18118
[mono.git] / mcs / class / System.Xaml / System.Xaml / ValueSerializerContext.cs
index 3af9bdc59216683572dd8605251b79aa9cde2890..174b17ec32205d525ef4a2c177a397a56a8fc712 100644 (file)
@@ -35,14 +35,16 @@ using System.Xml;
 
 namespace System.Xaml
 {
-       internal class ValueSerializerContext : IValueSerializerContext
+       internal class ValueSerializerContext : IValueSerializerContext, IXamlSchemaContextProvider
        {
                XamlNameResolver name_resolver = new XamlNameResolver ();
                XamlTypeResolver type_resolver;
                NamespaceResolver namespace_resolver;
                PrefixLookup prefix_lookup;
+               XamlSchemaContext sctx;
+               IAmbientProvider ambient_provider;
 
-               public ValueSerializerContext (PrefixLookup prefixLookup, XamlSchemaContext schemaContext)
+               public ValueSerializerContext (PrefixLookup prefixLookup, XamlSchemaContext schemaContext, IAmbientProvider ambientProvider)
                {
                        if (prefixLookup == null)
                                throw new ArgumentNullException ("prefixLookup");
@@ -51,6 +53,8 @@ namespace System.Xaml
                        prefix_lookup = prefixLookup;
                        namespace_resolver = new NamespaceResolver (prefix_lookup.Namespaces);
                        type_resolver = new XamlTypeResolver (namespace_resolver, schemaContext);
+                       sctx = schemaContext;
+                       ambient_provider = ambientProvider;
                }
 
                public object GetService (Type serviceType)
@@ -61,10 +65,21 @@ namespace System.Xaml
                                return namespace_resolver;
                        if (serviceType == typeof (IXamlNameResolver))
                                return name_resolver;
+                       if (serviceType == typeof (IXamlNameProvider))
+                               return name_resolver;
                        if (serviceType == typeof (IXamlTypeResolver))
                                return type_resolver;
+                       if (serviceType == typeof (IAmbientProvider))
+                               return ambient_provider;
+                       if (serviceType == typeof (IXamlSchemaContextProvider))
+                               return this;
                        return null;
                }
+               
+               XamlSchemaContext IXamlSchemaContextProvider.SchemaContext {
+                       get { return sctx; }
+               }
+               
                public IContainer Container {
                        get { throw new NotImplementedException (); }
                }
@@ -133,4 +148,82 @@ namespace System.Xaml
                        return source;
                }
        }
+
+       internal class AmbientProvider : IAmbientProvider
+       {
+               List<AmbientPropertyValue> values = new List<AmbientPropertyValue> ();
+               Stack<AmbientPropertyValue> live_stack = new Stack<AmbientPropertyValue> ();
+
+               public void Push (AmbientPropertyValue v)
+               {
+                       live_stack.Push (v);
+                       values.Add (v);
+               }
+
+               public void Pop ()
+               {
+                       live_stack.Pop ();
+               }
+
+               public IEnumerable<object> GetAllAmbientValues (params XamlType [] types)
+               {
+                       return GetAllAmbientValues (null, false, types);
+               }
+               
+               public IEnumerable<AmbientPropertyValue> GetAllAmbientValues (IEnumerable<XamlType> ceilingTypes, params XamlMember [] properties)
+               {
+                       return GetAllAmbientValues (ceilingTypes, false, null, properties);
+               }
+               
+               public IEnumerable<AmbientPropertyValue> GetAllAmbientValues (IEnumerable<XamlType> ceilingTypes, bool searchLiveStackOnly, IEnumerable<XamlType> types, params XamlMember [] properties)
+               {
+                       return DoGetAllAmbientValues (ceilingTypes, searchLiveStackOnly, types, properties).ToList ();
+               }
+               
+               IEnumerable<AmbientPropertyValue> DoGetAllAmbientValues (IEnumerable<XamlType> ceilingTypes, bool searchLiveStackOnly, IEnumerable<XamlType> types, params XamlMember [] properties)
+               {
+                       if (searchLiveStackOnly) {
+                               if (live_stack.Count > 0) {
+                                       // pop, call recursively, then push back.
+                                       var p = live_stack.Pop ();
+                                       if (p.RetrievedProperty != null && ceilingTypes != null && ceilingTypes.Contains (p.RetrievedProperty.Type))
+                                               yield break;
+                                       if (DoesAmbientPropertyApply (p, types, properties))
+                                               yield return p;
+
+                                       foreach (var i in GetAllAmbientValues (ceilingTypes, searchLiveStackOnly, types, properties))
+                                               yield return i;
+
+                                       live_stack.Push (p);
+                               }
+                       } else {
+                               // FIXME: does ceilingTypes matter?
+                               foreach (var p in values)
+                                       if (DoesAmbientPropertyApply (p, types, properties))
+                                               yield return p;
+                       }
+               }
+               
+               bool DoesAmbientPropertyApply (AmbientPropertyValue p, IEnumerable<XamlType> types, params XamlMember [] properties)
+               {
+                       if (types == null || !types.Any () || types.Any (xt => xt.UnderlyingType != null && xt.UnderlyingType.IsInstanceOfType (p.Value)))
+                               if (properties == null || !properties.Any () || properties.Contains (p.RetrievedProperty))
+                                       return true;
+                       return false;
+               }
+               
+               public object GetFirstAmbientValue (params XamlType [] types)
+               {
+                       foreach (var obj in GetAllAmbientValues (types))
+                               return obj;
+                       return null;
+               }
+               
+               public AmbientPropertyValue GetFirstAmbientValue (IEnumerable<XamlType> ceilingTypes, params XamlMember [] properties)
+               {
+                       foreach (var obj in GetAllAmbientValues (ceilingTypes, properties))
+                               return obj;
+                       return null;
+               }
+       }
 }