[NUI]Add xaml support for nui and nui xaml test sample (#230)
[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.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         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         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 }