[NUI] Split NUI Assemblies (#865)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Xaml / src / public / Xaml / XamlServiceProvider.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Reflection;
5 using System.Xml;
6 using Tizen.NUI.XamlBinding;
7 using Tizen.NUI.XamlBinding.Internals;
8
9 namespace Tizen.NUI.Xaml
10 {
11     /// <summary>
12     /// The class to provide xaml service.
13     /// </summary>
14     /// <since_tizen> 6 </since_tizen>
15     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
16     [EditorBrowsable(EditorBrowsableState.Never)]
17     public class XamlServiceProvider : IServiceProvider
18     {
19         readonly Dictionary<Type, object> services = new Dictionary<Type, object>();
20
21         internal XamlServiceProvider(INode node, HydrationContext context)
22         {
23             object targetObject;
24             if (node != null && node.Parent != null && context.Values.TryGetValue(node.Parent, out targetObject))
25                 IProvideValueTarget = new XamlValueTargetProvider(targetObject, node, context, null);
26             if (context != null)
27                 IRootObjectProvider = new XamlRootObjectProvider(context.RootElement);
28             if (node != null)
29             {
30                 IXamlTypeResolver = new XamlTypeResolver(node.NamespaceResolver, XamlParser.GetElementType,
31                     context?.RootElement.GetType().GetTypeInfo().Assembly);
32
33                 var enode = node;
34                 while (enode != null && !(enode is IElementNode))
35                     enode = enode.Parent;
36                 if (enode != null)
37                     INameScopeProvider = new NameScopeProvider { NameScope = (enode as IElementNode).Namescope };
38             }
39
40             var xmlLineInfo = node as IXmlLineInfo;
41             if (xmlLineInfo != null)
42                 IXmlLineInfoProvider = new XmlLineInfoProvider(xmlLineInfo);
43
44             IValueConverterProvider = new ValueConverterProvider();
45         }
46
47         /// <summary>
48         /// Create a new XamlServiceProvider.
49         /// </summary>
50         /// <since_tizen> 6 </since_tizen>
51         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
52         [EditorBrowsable(EditorBrowsableState.Never)]
53         public XamlServiceProvider()
54         {
55             IValueConverterProvider = new ValueConverterProvider();
56         }
57
58         internal IProvideValueTarget IProvideValueTarget
59         {
60             get { return (IProvideValueTarget)GetService(typeof (IProvideValueTarget)); }
61             set { services[typeof (IProvideValueTarget)] = value; }
62         }
63
64         internal IXamlTypeResolver IXamlTypeResolver
65         {
66             get { return (IXamlTypeResolver)GetService(typeof (IXamlTypeResolver)); }
67             set { services[typeof (IXamlTypeResolver)] = value; }
68         }
69
70         internal IRootObjectProvider IRootObjectProvider
71         {
72             get { return (IRootObjectProvider)GetService(typeof (IRootObjectProvider)); }
73             set { services[typeof (IRootObjectProvider)] = value; }
74         }
75
76         internal IXmlLineInfoProvider IXmlLineInfoProvider
77         {
78             get { return (IXmlLineInfoProvider)GetService(typeof (IXmlLineInfoProvider)); }
79             set { services[typeof (IXmlLineInfoProvider)] = value; }
80         }
81
82         internal INameScopeProvider INameScopeProvider
83         {
84             get { return (INameScopeProvider)GetService(typeof (INameScopeProvider)); }
85             set { services[typeof (INameScopeProvider)] = value; }
86         }
87
88         internal IValueConverterProvider IValueConverterProvider
89         {
90             get { return (IValueConverterProvider)GetService(typeof (IValueConverterProvider)); }
91             set { services[typeof (IValueConverterProvider)] = value; }
92         }
93
94         /// <summary>
95         /// Get service.
96         /// </summary>
97         /// <since_tizen> 6 </since_tizen>
98         [EditorBrowsable(EditorBrowsableState.Never)]
99         public object GetService(Type serviceType)
100         {
101             object service;
102             return services.TryGetValue(serviceType, out service) ? service : null;
103         }
104
105         /// <summary>
106         /// Add service.
107         /// </summary>
108         /// <since_tizen> 6 </since_tizen>
109         [EditorBrowsable(EditorBrowsableState.Never)]
110         public void Add(Type type, object service)
111         {
112             services.Add(type, service);
113         }
114     }
115
116     internal class XamlValueTargetProvider : IProvideParentValues, IProvideValueTarget
117     {
118         public XamlValueTargetProvider(object targetObject, INode node, HydrationContext context, object targetProperty)
119         {
120             Context = context;
121             Node = node;
122             TargetObject = targetObject;
123             TargetProperty = targetProperty;
124         }
125
126         INode Node { get; }
127
128         HydrationContext Context { get; }
129         public object TargetObject { get; }
130         public object TargetProperty { get; internal set; } = null;
131
132         IEnumerable<object> IProvideParentValues.ParentObjects
133         {
134             get
135             {
136                 if (Node == null || Context == null)
137                     yield break;
138                 var n = Node;
139                 object obj = null;
140                 var context = Context;
141                 while (n.Parent != null && context != null)
142                 {
143                     if (n.Parent is IElementNode)
144                     {
145                         if (context.Values.TryGetValue(n.Parent, out obj))
146                             yield return obj;
147                         else
148                         {
149                             context = context.ParentContext;
150                             continue;
151                         }
152                     }
153                     n = n.Parent;
154                 }
155             }
156         }
157     }
158
159     /// <summary>
160     /// The class to provide simple value target.
161     /// </summary>
162     /// <since_tizen> 6 </since_tizen>
163     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
164     [EditorBrowsable(EditorBrowsableState.Never)]
165     public class SimpleValueTargetProvider : IProvideParentValues, IProvideValueTarget, IReferenceProvider
166     {
167         readonly object[] objectAndParents;
168         readonly object targetProperty;
169
170         /// <summary>
171         /// Create a new SimpleValueTargetProvider.
172         /// </summary>
173         /// <since_tizen> 6 </since_tizen>
174         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
175         [EditorBrowsable(EditorBrowsableState.Never)]
176         [Obsolete("SimpleValueTargetProvider(object[] objectAndParents) is obsolete as of version 2.3.4. Please use SimpleValueTargetProvider(object[] objectAndParents, object targetProperty) instead.")]
177         public SimpleValueTargetProvider(object[] objectAndParents) : this (objectAndParents, null)
178         {
179         }
180
181         /// <summary>
182         /// Create a new SimpleValueTargetProvider.
183         /// </summary>
184         /// <since_tizen> 6 </since_tizen>
185         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
186         [EditorBrowsable(EditorBrowsableState.Never)]
187         public SimpleValueTargetProvider(object[] objectAndParents, object targetProperty)
188         {
189             if (objectAndParents == null)
190                 throw new ArgumentNullException(nameof(objectAndParents));
191             if (objectAndParents.Length == 0)
192                 throw new ArgumentException();
193
194             this.objectAndParents = objectAndParents;
195             this.targetProperty = targetProperty;
196         }
197
198         IEnumerable<object> IProvideParentValues.ParentObjects
199         {
200             get { return objectAndParents; }
201         }
202
203         object IProvideValueTarget.TargetObject
204         {
205             get { return objectAndParents[0]; }
206         }
207
208         object IProvideValueTarget.TargetProperty
209         {
210             get { return targetProperty; }
211         }
212
213         /// <summary>
214         /// Find target by name.
215         /// </summary>
216         /// <since_tizen> 6 </since_tizen>
217         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
218         [EditorBrowsable(EditorBrowsableState.Never)]
219         public object FindByName(string name)
220         {
221             for (var i = 0; i < objectAndParents.Length; i++)
222             {
223                 var bo = objectAndParents[i] as BindableObject;
224                 if (bo == null) continue;
225                 var ns = NameScope.GetNameScope(bo) as INameScope;
226                 if (ns == null) continue;
227                 var value = ns.FindByName(name);
228                 if (value != null)
229                     return value;
230             }
231             return null;
232         }
233     }
234
235     /// <summary>
236     /// The class to resolve xaml type.
237     /// </summary>
238     /// <since_tizen> 6 </since_tizen>
239     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
240     [EditorBrowsable(EditorBrowsableState.Never)]
241     public class XamlTypeResolver : IXamlTypeResolver
242     {
243         readonly Assembly currentAssembly;
244         readonly GetTypeFromXmlName getTypeFromXmlName;
245         readonly IXmlNamespaceResolver namespaceResolver;
246
247         /// <summary>
248         /// Create a new XamlTypeResolver.
249         /// </summary>
250         /// <since_tizen> 6 </since_tizen>
251         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
252         [EditorBrowsable(EditorBrowsableState.Never)]
253         public XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, Assembly currentAssembly)
254             : this(namespaceResolver, XamlParser.GetElementType, currentAssembly)
255         {
256         }
257
258         internal XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, GetTypeFromXmlName getTypeFromXmlName,
259             Assembly currentAssembly)
260         {
261             this.currentAssembly = currentAssembly;
262             if (namespaceResolver == null)
263                 throw new ArgumentNullException();
264             if (getTypeFromXmlName == null)
265                 throw new ArgumentNullException();
266
267             this.namespaceResolver = namespaceResolver;
268             this.getTypeFromXmlName = getTypeFromXmlName;
269         }
270
271         Type IXamlTypeResolver.Resolve(string qualifiedTypeName, IServiceProvider serviceProvider)
272         {
273             XamlParseException e;
274             var type = Resolve(qualifiedTypeName, serviceProvider, out e);
275             if (e != null)
276                 throw e;
277             return type;
278         }
279
280         bool IXamlTypeResolver.TryResolve(string qualifiedTypeName, out Type type)
281         {
282             XamlParseException exception;
283             type = Resolve(qualifiedTypeName, null, out exception);
284             return exception == null;
285         }
286
287         Type Resolve(string qualifiedTypeName, IServiceProvider serviceProvider, out XamlParseException exception)
288         {
289             exception = null;
290             var split = qualifiedTypeName.Split(':');
291             if (split.Length > 2)
292                 return null;
293
294             string prefix, name;
295             if (split.Length == 2)
296             {
297                 prefix = split[0];
298                 name = split[1];
299             }
300             else
301             {
302                 prefix = "";
303                 name = split[0];
304             }
305
306             IXmlLineInfo xmlLineInfo = null;
307             if (serviceProvider != null)
308             {
309                 var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
310                 if (lineInfoProvider != null)
311                     xmlLineInfo = lineInfoProvider.XmlLineInfo;
312             }
313
314             var namespaceuri = namespaceResolver.LookupNamespace(prefix);
315             if (namespaceuri == null)
316             {
317                 exception = new XamlParseException(string.Format("No xmlns declaration for prefix \"{0}\"", prefix), xmlLineInfo);
318                 return null;
319             }
320
321             return getTypeFromXmlName(new XmlType(namespaceuri, name, null), xmlLineInfo, currentAssembly, out exception);
322         }
323
324         internal delegate Type GetTypeFromXmlName(
325             XmlType xmlType, IXmlLineInfo xmlInfo, Assembly currentAssembly, out XamlParseException exception);
326     }
327
328     /// <summary>
329     /// The class to provide xaml root object.
330     /// </summary>
331     /// <since_tizen> 6 </since_tizen>
332     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
333     [EditorBrowsable(EditorBrowsableState.Never)]
334     public class XamlRootObjectProvider : IRootObjectProvider
335     {
336         /// <summary>
337         /// Create a new XamlRootObjectProvider.
338         /// </summary>
339         /// <since_tizen> 6 </since_tizen>
340         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
341         [EditorBrowsable(EditorBrowsableState.Never)]
342         public XamlRootObjectProvider(object rootObject)
343         {
344             RootObject = rootObject;
345         }
346
347         /// <summary>
348         /// Attribute RootObject.
349         /// </summary>
350         /// <since_tizen> 6 </since_tizen>
351         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
352         [EditorBrowsable(EditorBrowsableState.Never)]
353         public object RootObject { get; }
354     }
355
356     /// <summary>
357     /// The class to provide xaml line info.
358     /// </summary>
359     /// <since_tizen> 6 </since_tizen>
360     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
361     [EditorBrowsable(EditorBrowsableState.Never)]
362     public class XmlLineInfoProvider : IXmlLineInfoProvider
363     {
364         /// <summary>
365         /// Create a new XmlLineInfoProvider.
366         /// </summary>
367         /// <since_tizen> 6 </since_tizen>
368         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
369         [EditorBrowsable(EditorBrowsableState.Never)]
370         public XmlLineInfoProvider(IXmlLineInfo xmlLineInfo)
371         {
372             XmlLineInfo = xmlLineInfo;
373         }
374
375         /// <summary>
376         /// Attribute XmlLineInfo.
377         /// </summary>
378         /// <since_tizen> 6 </since_tizen>
379         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
380         [EditorBrowsable(EditorBrowsableState.Never)]
381         public IXmlLineInfo XmlLineInfo { get; }
382     }
383
384     /// <summary>
385     /// The class to provide name scope.
386     /// </summary>
387     /// <since_tizen> 6 </since_tizen>
388     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
389     [EditorBrowsable(EditorBrowsableState.Never)]
390     public class NameScopeProvider : INameScopeProvider
391     {
392         /// <summary>
393         /// Attribute NameScope.
394         /// </summary>
395         /// <since_tizen> 6 </since_tizen>
396         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
397         [EditorBrowsable(EditorBrowsableState.Never)]
398         public INameScope NameScope { get; set; }
399     }
400
401     /// <summary>
402     /// The class to resolve xml namespace.
403     /// </summary>
404     /// <since_tizen> 6 </since_tizen>
405     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
406     [EditorBrowsable(EditorBrowsableState.Never)]
407     public class XmlNamespaceResolver : IXmlNamespaceResolver
408     {
409         readonly Dictionary<string, string> namespaces = new Dictionary<string, string>();
410
411         /// <summary>
412         /// Get namespace.
413         /// </summary>
414         /// <since_tizen> 6 </since_tizen>
415         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
416         [EditorBrowsable(EditorBrowsableState.Never)]
417         public IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
418         {
419             throw new NotImplementedException();
420         }
421
422         /// <summary>
423         /// Look up name space.
424         /// </summary>
425         /// <since_tizen> 6 </since_tizen>
426         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
427         [EditorBrowsable(EditorBrowsableState.Never)]
428         public string LookupNamespace(string prefix)
429         {
430             string result;
431             if (namespaces.TryGetValue(prefix, out result))
432                 return result;
433             return null;
434         }
435
436         /// <summary>
437         /// Look up prefix.
438         /// </summary>
439         /// <since_tizen> 6 </since_tizen>
440         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
441         [EditorBrowsable(EditorBrowsableState.Never)]
442         public string LookupPrefix(string namespaceName)
443         {
444             throw new NotImplementedException();
445         }
446
447         /// <summary>
448         /// Add prefix and ns.
449         /// </summary>
450         /// <since_tizen> 6 </since_tizen>
451         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
452         [EditorBrowsable(EditorBrowsableState.Never)]
453         public void Add(string prefix, string ns)
454         {
455             namespaces.Add(prefix, ns);
456         }
457     }
458 }