[NUI] Adjust directory (#903)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / 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.Binding;
7 using Tizen.NUI.Binding.Internals;
8
9 namespace Tizen.NUI.Xaml
10 {
11     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
12     [EditorBrowsable(EditorBrowsableState.Never)]
13     public class XamlServiceProvider : IServiceProvider
14     {
15         readonly Dictionary<Type, object> services = new Dictionary<Type, object>();
16
17         internal XamlServiceProvider(INode node, HydrationContext context)
18         {
19             object targetObject;
20             if (node != null && node.Parent != null && context.Values.TryGetValue(node.Parent, out targetObject))
21                 IProvideValueTarget = new XamlValueTargetProvider(targetObject, node, context, null);
22             if (context != null)
23                 IRootObjectProvider = new XamlRootObjectProvider(context.RootElement);
24             if (node != null)
25             {
26                 IXamlTypeResolver = new XamlTypeResolver(node.NamespaceResolver, XamlParser.GetElementType,
27                     context?.RootElement.GetType().GetTypeInfo().Assembly);
28
29                 Add(typeof(IReferenceProvider), new ReferenceProvider(node));
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         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
40         [EditorBrowsable(EditorBrowsableState.Never)]
41         public XamlServiceProvider()
42         {
43             IValueConverterProvider = new ValueConverterProvider();
44         }
45
46         internal IProvideValueTarget IProvideValueTarget
47         {
48             get { return (IProvideValueTarget)GetService(typeof (IProvideValueTarget)); }
49             set { services[typeof (IProvideValueTarget)] = value; }
50         }
51
52         internal IXamlTypeResolver IXamlTypeResolver
53         {
54             get { return (IXamlTypeResolver)GetService(typeof (IXamlTypeResolver)); }
55             set { services[typeof (IXamlTypeResolver)] = value; }
56         }
57
58         internal IRootObjectProvider IRootObjectProvider
59         {
60             get { return (IRootObjectProvider)GetService(typeof (IRootObjectProvider)); }
61             set { services[typeof (IRootObjectProvider)] = value; }
62         }
63
64         internal IXmlLineInfoProvider IXmlLineInfoProvider
65         {
66             get { return (IXmlLineInfoProvider)GetService(typeof (IXmlLineInfoProvider)); }
67             set { services[typeof (IXmlLineInfoProvider)] = value; }
68         }
69
70         internal INameScopeProvider INameScopeProvider
71         {
72             get { return (INameScopeProvider)GetService(typeof (INameScopeProvider)); }
73             set { services[typeof (INameScopeProvider)] = value; }
74         }
75
76         internal IValueConverterProvider IValueConverterProvider
77         {
78             get { return (IValueConverterProvider)GetService(typeof (IValueConverterProvider)); }
79             set { services[typeof (IValueConverterProvider)] = value; }
80         }
81
82         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
83         [EditorBrowsable(EditorBrowsableState.Never)]
84         public object GetService(Type serviceType)
85         {
86             object service;
87             return services.TryGetValue(serviceType, out service) ? service : null;
88         }
89
90         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
91         [EditorBrowsable(EditorBrowsableState.Never)]
92         public void Add(Type type, object service)
93         {
94             services.Add(type, service);
95         }
96     }
97
98     internal class XamlValueTargetProvider : IProvideParentValues, IProvideValueTarget
99     {
100         public XamlValueTargetProvider(object targetObject, INode node, HydrationContext context, object targetProperty)
101         {
102             Context = context;
103             Node = node;
104             TargetObject = targetObject;
105             TargetProperty = targetProperty;
106         }
107
108         INode Node { get; }
109
110         HydrationContext Context { get; }
111         public object TargetObject { get; }
112         public object TargetProperty { get; internal set; } = null;
113
114         IEnumerable<object> IProvideParentValues.ParentObjects
115         {
116             get
117             {
118                 if (Node == null || Context == null)
119                     yield break;
120                 var n = Node;
121                 object obj = null;
122                 var context = Context;
123                 while (n.Parent != null && context != null)
124                 {
125                     if (n.Parent is IElementNode)
126                     {
127                         if (context.Values.TryGetValue(n.Parent, out obj))
128                             yield return obj;
129                         else
130                         {
131                             context = context.ParentContext;
132                             continue;
133                         }
134                     }
135                     n = n.Parent;
136                 }
137             }
138         }
139     }
140
141     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
142     [EditorBrowsable(EditorBrowsableState.Never)]
143     public class SimpleValueTargetProvider : IProvideParentValues, IProvideValueTarget, IReferenceProvider
144     {
145         readonly object[] objectAndParents;
146         readonly object targetProperty;
147
148         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
149         [EditorBrowsable(EditorBrowsableState.Never)]
150         [Obsolete("SimpleValueTargetProvider(object[] objectAndParents) is obsolete as of version 2.3.4. Please use SimpleValueTargetProvider(object[] objectAndParents, object targetProperty) instead.")]
151         public SimpleValueTargetProvider(object[] objectAndParents) : this (objectAndParents, null)
152         {
153         }
154
155         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
156         [EditorBrowsable(EditorBrowsableState.Never)]
157         public SimpleValueTargetProvider(object[] objectAndParents, object targetProperty)
158         {
159             if (objectAndParents == null)
160                 throw new ArgumentNullException(nameof(objectAndParents));
161             if (objectAndParents.Length == 0)
162                 throw new ArgumentException();
163
164             this.objectAndParents = objectAndParents;
165             this.targetProperty = targetProperty;
166         }
167
168         IEnumerable<object> IProvideParentValues.ParentObjects
169             => objectAndParents;
170
171         object IProvideValueTarget.TargetObject
172             => objectAndParents[0];
173
174         object IProvideValueTarget.TargetProperty
175             => targetProperty;
176
177         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
178         [EditorBrowsable(EditorBrowsableState.Never)]
179         public object FindByName(string name)
180         {
181             for (var i = 0; i < objectAndParents.Length; i++) {
182                                 var bo = objectAndParents[i] as BindableObject;
183                                 if (bo == null) continue;
184                                 var ns = NameScope.GetNameScope(bo) as INameScope;
185                                 if (ns == null) continue;
186                                 var value = ns.FindByName(name);
187                                 if (value != null)
188                                         return value;
189             }
190             return null;
191         }
192     }
193
194     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
195     [EditorBrowsable(EditorBrowsableState.Never)]
196     public class XamlTypeResolver : IXamlTypeResolver
197     {
198         readonly Assembly currentAssembly;
199         readonly GetTypeFromXmlName getTypeFromXmlName;
200         readonly IXmlNamespaceResolver namespaceResolver;
201
202         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
203         [EditorBrowsable(EditorBrowsableState.Never)]
204         public XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, Assembly currentAssembly)
205             : this(namespaceResolver, XamlParser.GetElementType, currentAssembly)
206         {
207         }
208
209         internal XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, GetTypeFromXmlName getTypeFromXmlName,
210             Assembly currentAssembly)
211         {
212             this.currentAssembly = currentAssembly;
213             if (namespaceResolver == null)
214                 throw new ArgumentNullException();
215             if (getTypeFromXmlName == null)
216                 throw new ArgumentNullException();
217
218             this.namespaceResolver = namespaceResolver;
219             this.getTypeFromXmlName = getTypeFromXmlName;
220         }
221
222         Type IXamlTypeResolver.Resolve(string qualifiedTypeName, IServiceProvider serviceProvider)
223         {
224             XamlParseException e;
225             var type = Resolve(qualifiedTypeName, serviceProvider, out e);
226             if (e != null)
227                 throw e;
228             return type;
229         }
230
231         bool IXamlTypeResolver.TryResolve(string qualifiedTypeName, out Type type)
232         {
233             XamlParseException exception;
234             type = Resolve(qualifiedTypeName, null, out exception);
235             return exception == null;
236         }
237
238         Type Resolve(string qualifiedTypeName, IServiceProvider serviceProvider, out XamlParseException exception)
239         {
240             exception = null;
241             var split = qualifiedTypeName.Split(':');
242             if (split.Length > 2)
243                 return null;
244
245             string prefix, name;
246             if (split.Length == 2)
247             {
248                 prefix = split[0];
249                 name = split[1];
250             }
251             else
252             {
253                 prefix = "";
254                 name = split[0];
255             }
256
257             IXmlLineInfo xmlLineInfo = null;
258             if (serviceProvider != null)
259             {
260                 var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
261                 if (lineInfoProvider != null)
262                     xmlLineInfo = lineInfoProvider.XmlLineInfo;
263             }
264
265             var namespaceuri = namespaceResolver.LookupNamespace(prefix);
266             if (namespaceuri == null)
267             {
268                 exception = new XamlParseException(string.Format("No xmlns declaration for prefix \"{0}\"", prefix), xmlLineInfo);
269                 return null;
270             }
271
272             return getTypeFromXmlName(new XmlType(namespaceuri, name, null), xmlLineInfo, currentAssembly, out exception);
273         }
274
275         internal delegate Type GetTypeFromXmlName(
276             XmlType xmlType, IXmlLineInfo xmlInfo, Assembly currentAssembly, out XamlParseException exception);
277     }
278
279     internal class XamlRootObjectProvider : IRootObjectProvider
280     {
281         public XamlRootObjectProvider(object rootObject)
282         {
283             RootObject = rootObject;
284         }
285
286         public object RootObject { get; }
287     }
288
289     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
290     [EditorBrowsable(EditorBrowsableState.Never)]
291     public class XmlLineInfoProvider : IXmlLineInfoProvider
292     {
293         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
294         [EditorBrowsable(EditorBrowsableState.Never)]
295         public XmlLineInfoProvider(IXmlLineInfo xmlLineInfo)
296         {
297             XmlLineInfo = xmlLineInfo;
298         }
299
300         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
301         [EditorBrowsable(EditorBrowsableState.Never)]
302         public IXmlLineInfo XmlLineInfo { get; }
303     }
304
305     class ReferenceProvider : IReferenceProvider
306     {
307         readonly INode _node;
308         internal ReferenceProvider(INode node)
309             => _node = node;
310
311         public object FindByName(string name)
312         {
313             var n = _node;
314             object value = null;
315             while (n != null) {
316                 if ((value = (n as IElementNode)?.Namescope?.FindByName(name)) != null)
317                     return value;
318                 n = n.Parent;
319             }
320             return null;
321         }
322     }
323
324     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
325     [EditorBrowsable(EditorBrowsableState.Never)]
326     [Obsolete]
327     public class NameScopeProvider : INameScopeProvider
328     {
329         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
330         [EditorBrowsable(EditorBrowsableState.Never)]
331         public INameScope NameScope { get; set; }
332     }
333
334     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
335     [EditorBrowsable(EditorBrowsableState.Never)]
336     public class XmlNamespaceResolver : IXmlNamespaceResolver
337     {
338         readonly Dictionary<string, string> namespaces = new Dictionary<string, string>();
339
340         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
341         [EditorBrowsable(EditorBrowsableState.Never)]
342         public IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
343         {
344             throw new NotImplementedException();
345         }
346
347         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
348         [EditorBrowsable(EditorBrowsableState.Never)]
349         public string LookupNamespace(string prefix)
350         {
351             string result;
352             if (namespaces.TryGetValue(prefix, out result))
353                 return result;
354             return null;
355         }
356
357         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
358         [EditorBrowsable(EditorBrowsableState.Never)]
359         public string LookupPrefix(string namespaceName)
360         {
361             throw new NotImplementedException();
362         }
363
364         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
365         [EditorBrowsable(EditorBrowsableState.Never)]
366         public void Add(string prefix, string ns)
367         {
368             namespaces.Add(prefix, ns);
369         }
370     }
371 }