[NUI] Change GetDefaultWindow() to static func (#900)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / Xaml / XamlServiceProvider.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using System.Xml;
5 using Tizen.NUI.Binding.Internals;
6
7 namespace Tizen.NUI.Xaml
8 {
9     internal class XamlServiceProvider : IServiceProvider
10     {
11         readonly Dictionary<Type, object> services = new Dictionary<Type, object>();
12
13         internal XamlServiceProvider(INode node, HydrationContext context)
14         {
15             object targetObject;
16             if (node != null && node.Parent != null && context.Values.TryGetValue(node.Parent, out targetObject))
17                 IProvideValueTarget = new XamlValueTargetProvider(targetObject, node, context, null);
18             if (context != null)
19                 IRootObjectProvider = new XamlRootObjectProvider(context.RootElement);
20             if (node != null)
21             {
22                 IXamlTypeResolver = new XamlTypeResolver(node.NamespaceResolver, XamlParser.GetElementType,
23                     context?.RootElement.GetType().GetTypeInfo().Assembly);
24
25                 var enode = node;
26                 while (enode != null && !(enode is IElementNode))
27                     enode = enode.Parent;
28                 if (enode != null)
29                     INameScopeProvider = new NameScopeProvider { NameScope = (enode as IElementNode).Namescope };
30             }
31
32             var xmlLineInfo = node as IXmlLineInfo;
33             if (xmlLineInfo != null)
34                 IXmlLineInfoProvider = new XmlLineInfoProvider(xmlLineInfo);
35
36             IValueConverterProvider = new ValueConverterProvider();
37         }
38
39         public XamlServiceProvider()
40         {
41             IValueConverterProvider = new ValueConverterProvider();
42         }
43
44         internal IProvideValueTarget IProvideValueTarget
45         {
46             get { return (IProvideValueTarget)GetService(typeof (IProvideValueTarget)); }
47             set { services[typeof (IProvideValueTarget)] = value; }
48         }
49
50         internal IXamlTypeResolver IXamlTypeResolver
51         {
52             get { return (IXamlTypeResolver)GetService(typeof (IXamlTypeResolver)); }
53             set { services[typeof (IXamlTypeResolver)] = value; }
54         }
55
56         internal IRootObjectProvider IRootObjectProvider
57         {
58             get { return (IRootObjectProvider)GetService(typeof (IRootObjectProvider)); }
59             set { services[typeof (IRootObjectProvider)] = value; }
60         }
61
62         internal IXmlLineInfoProvider IXmlLineInfoProvider
63         {
64             get { return (IXmlLineInfoProvider)GetService(typeof (IXmlLineInfoProvider)); }
65             set { services[typeof (IXmlLineInfoProvider)] = value; }
66         }
67
68         internal INameScopeProvider INameScopeProvider
69         {
70             get { return (INameScopeProvider)GetService(typeof (INameScopeProvider)); }
71             set { services[typeof (INameScopeProvider)] = value; }
72         }
73
74         internal IValueConverterProvider IValueConverterProvider
75         {
76             get { return (IValueConverterProvider)GetService(typeof (IValueConverterProvider)); }
77             set { services[typeof (IValueConverterProvider)] = value; }
78         }
79
80         public object GetService(Type serviceType)
81         {
82             object service;
83             return services.TryGetValue(serviceType, out service) ? service : null;
84         }
85
86         public void Add(Type type, object service)
87         {
88             services.Add(type, service);
89         }
90     }
91
92     internal class XamlValueTargetProvider : IProvideParentValues, IProvideValueTarget
93     {
94         public XamlValueTargetProvider(object targetObject, INode node, HydrationContext context, object targetProperty)
95         {
96             Context = context;
97             Node = node;
98             TargetObject = targetObject;
99             TargetProperty = targetProperty;
100         }
101
102         INode Node { get; }
103
104         HydrationContext Context { get; }
105         public object TargetObject { get; }
106         public object TargetProperty { get; internal set; } = null;
107
108         IEnumerable<object> IProvideParentValues.ParentObjects
109         {
110             get
111             {
112                 if (Node == null || Context == null)
113                     yield break;
114                 var n = Node;
115                 object obj = null;
116                 var context = Context;
117                 while (n.Parent != null && context != null)
118                 {
119                     if (n.Parent is IElementNode)
120                     {
121                         if (context.Values.TryGetValue(n.Parent, out obj))
122                             yield return obj;
123                         else
124                         {
125                             context = context.ParentContext;
126                             continue;
127                         }
128                     }
129                     n = n.Parent;
130                 }
131             }
132         }
133     }
134
135     internal class SimpleValueTargetProvider : IProvideParentValues, IProvideValueTarget
136     {
137         readonly object[] objectAndParents;
138         readonly object targetProperty;
139
140         [Obsolete("SimpleValueTargetProvider(object[] objectAndParents) is obsolete as of version 2.3.4. Please use SimpleValueTargetProvider(object[] objectAndParents, object targetProperty) instead.")]
141         public SimpleValueTargetProvider(object[] objectAndParents) : this (objectAndParents, null)
142         {
143         }
144
145         public SimpleValueTargetProvider(object[] objectAndParents, object targetProperty)
146         {
147             if (objectAndParents == null)
148                 throw new ArgumentNullException(nameof(objectAndParents));
149             if (objectAndParents.Length == 0)
150                 throw new ArgumentException();
151
152             this.objectAndParents = objectAndParents;
153             this.targetProperty = targetProperty;
154         }
155
156         IEnumerable<object> IProvideParentValues.ParentObjects
157         {
158             get { return objectAndParents; }
159         }
160
161         object IProvideValueTarget.TargetObject
162         {
163             get { return objectAndParents[0]; }
164         }
165
166         object IProvideValueTarget.TargetProperty
167         {
168             get { return targetProperty; }
169         }
170     }
171
172     internal class XamlTypeResolver : IXamlTypeResolver
173     {
174         readonly Assembly currentAssembly;
175         readonly GetTypeFromXmlName getTypeFromXmlName;
176         readonly IXmlNamespaceResolver namespaceResolver;
177
178         public XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, Assembly currentAssembly)
179             : this(namespaceResolver, XamlParser.GetElementType, currentAssembly)
180         {
181         }
182
183         internal XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, GetTypeFromXmlName getTypeFromXmlName,
184             Assembly currentAssembly)
185         {
186             this.currentAssembly = currentAssembly;
187             if (namespaceResolver == null)
188                 throw new ArgumentNullException();
189             if (getTypeFromXmlName == null)
190                 throw new ArgumentNullException();
191
192             this.namespaceResolver = namespaceResolver;
193             this.getTypeFromXmlName = getTypeFromXmlName;
194         }
195
196         Type IXamlTypeResolver.Resolve(string qualifiedTypeName, IServiceProvider serviceProvider)
197         {
198             XamlParseException e;
199             var type = Resolve(qualifiedTypeName, serviceProvider, out e);
200             if (e != null)
201                 throw e;
202             return type;
203         }
204
205         bool IXamlTypeResolver.TryResolve(string qualifiedTypeName, out Type type)
206         {
207             XamlParseException exception;
208             type = Resolve(qualifiedTypeName, null, out exception);
209             return exception == null;
210         }
211
212         Type Resolve(string qualifiedTypeName, IServiceProvider serviceProvider, out XamlParseException exception)
213         {
214             exception = null;
215             var split = qualifiedTypeName.Split(':');
216             if (split.Length > 2)
217                 return null;
218
219             string prefix, name;
220             if (split.Length == 2)
221             {
222                 prefix = split[0];
223                 name = split[1];
224             }
225             else
226             {
227                 prefix = "";
228                 name = split[0];
229             }
230
231             IXmlLineInfo xmlLineInfo = null;
232             if (serviceProvider != null)
233             {
234                 var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
235                 if (lineInfoProvider != null)
236                     xmlLineInfo = lineInfoProvider.XmlLineInfo;
237             }
238
239             var namespaceuri = namespaceResolver.LookupNamespace(prefix);
240             if (namespaceuri == null)
241             {
242                 exception = new XamlParseException(string.Format("No xmlns declaration for prefix \"{0}\"", prefix), xmlLineInfo);
243                 return null;
244             }
245
246             return getTypeFromXmlName(new XmlType(namespaceuri, name, null), xmlLineInfo, currentAssembly, out exception);
247         }
248
249         internal delegate Type GetTypeFromXmlName(
250             XmlType xmlType, IXmlLineInfo xmlInfo, Assembly currentAssembly, out XamlParseException exception);
251     }
252
253     internal class XamlRootObjectProvider : IRootObjectProvider
254     {
255         public XamlRootObjectProvider(object rootObject)
256         {
257             RootObject = rootObject;
258         }
259
260         public object RootObject { get; }
261     }
262
263     internal class XmlLineInfoProvider : IXmlLineInfoProvider
264     {
265         public XmlLineInfoProvider(IXmlLineInfo xmlLineInfo)
266         {
267             XmlLineInfo = xmlLineInfo;
268         }
269
270         public IXmlLineInfo XmlLineInfo { get; }
271     }
272
273     internal class NameScopeProvider : INameScopeProvider
274     {
275         public INameScope NameScope { get; set; }
276     }
277
278     internal class XmlNamespaceResolver : IXmlNamespaceResolver
279     {
280         readonly Dictionary<string, string> namespaces = new Dictionary<string, string>();
281
282         public IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
283         {
284             throw new NotImplementedException();
285         }
286
287         public string LookupNamespace(string prefix)
288         {
289             string result;
290             if (namespaces.TryGetValue(prefix, out result))
291                 return result;
292             return null;
293         }
294
295         public string LookupPrefix(string namespaceName)
296         {
297             throw new NotImplementedException();
298         }
299
300         public void Add(string prefix, string ns)
301         {
302             namespaces.Add(prefix, ns);
303         }
304     }
305 }