Fix generic XamlTypeName output and GetType() to get some xml reader case working.
[mono-project.git] / mcs / class / System.Xaml / System.Xaml.Schema / XamlTypeName.cs
blob36cf2f1aca60dcfa5f2054c43d33b173dc28f2aa
1 //
2 // Copyright (C) 2010 Novell Inc. http://novell.com
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 using System;
24 using System.Collections.Generic;
25 using System.Linq;
27 namespace System.Xaml.Schema
29 public class XamlTypeName
31 public static XamlTypeName Parse (string typeName, IXamlNamespaceResolver namespaceResolver)
33 XamlTypeName n;
34 if (!TryParse (typeName, namespaceResolver, out n))
35 throw new FormatException (String.Format ("Invalid typeName: '{0}'", typeName));
36 return n;
39 public static bool TryParse (string typeName, IXamlNamespaceResolver namespaceResolver, out XamlTypeName result)
41 if (typeName == null)
42 throw new ArgumentNullException ("typeName");
43 if (namespaceResolver == null)
44 throw new ArgumentNullException ("namespaceResolver");
46 result = null;
47 IList<XamlTypeName> args = null;
49 int idx = typeName.IndexOf ('(');
50 if (idx >= 0) {
51 if (typeName [typeName.Length - 1] != ')')
52 return false;
53 if (!TryParseList (typeName.Substring (idx + 1, typeName.Length - idx - 2), namespaceResolver, out args))
54 return false;
55 typeName = typeName.Substring (0, idx);
58 idx = typeName.IndexOf (':');
59 string prefix, local;
60 if (idx < 0) {
61 prefix = String.Empty;
62 local = typeName;
63 } else {
64 prefix = typeName.Substring (0, idx);
65 local = typeName.Substring (idx + 1);
66 if (!XamlLanguage.IsValidXamlName (prefix))
67 return false;
69 if (!XamlLanguage.IsValidXamlName (local))
70 return false;
71 string ns = namespaceResolver.GetNamespace (prefix);
72 if (ns == null)
73 return false;
75 result = new XamlTypeName (ns, local, args);
76 return true;
79 static readonly char [] commas = {','};
81 public static IList<XamlTypeName> ParseList (string typeNameList, IXamlNamespaceResolver namespaceResolver)
83 IList<XamlTypeName> list;
84 if (!TryParseList (typeNameList, namespaceResolver, out list))
85 throw new FormatException (String.Format ("Invalid type name list: '{0}'", typeNameList));
86 return list;
89 public static bool TryParseList (string typeNameList, IXamlNamespaceResolver namespaceResolver, out IList<XamlTypeName> list)
91 if (typeNameList == null)
92 throw new ArgumentNullException ("typeNameList");
93 if (namespaceResolver == null)
94 throw new ArgumentNullException ("namespaceResolver");
96 list = null;
97 var split = typeNameList.Split (commas);
98 if (split.Length == 0)
99 return false;
101 var arr = new XamlTypeName [split.Length];
103 for (int i = 0; i < split.Length; i++) {
104 var s = split [i].Trim ();
105 XamlTypeName tn;
106 if (!TryParse (s, namespaceResolver, out tn))
107 return false;
108 arr [i] = tn;
111 list = arr;
112 return true;
115 public static string ToString (IList<XamlTypeName> typeNameList, INamespacePrefixLookup prefixLookup)
117 if (typeNameList == null)
118 throw new ArgumentNullException ("typeNameList");
119 if (prefixLookup == null)
120 throw new ArgumentNullException ("prefixLookup");
122 return DoToString (typeNameList, prefixLookup);
125 static string DoToString (IList<XamlTypeName> typeNameList, INamespacePrefixLookup prefixLookup)
127 bool comma = false;
128 string ret = "";
129 foreach (var ta in typeNameList) {
130 if (comma)
131 ret += ", ";
132 else
133 comma = true;
134 ret += ta.ToString (prefixLookup);
136 return ret;
139 // instance members
141 public XamlTypeName ()
143 TypeArguments = empty_type_args;
146 static readonly XamlTypeName [] empty_type_args = new XamlTypeName [0];
148 public XamlTypeName (XamlType xamlType)
149 : this ()
151 if (xamlType == null)
152 throw new ArgumentNullException ("xamlType");
153 Namespace = xamlType.PreferredXamlNamespace;
154 Name = xamlType.Name;
155 if (xamlType.TypeArguments != null && xamlType.TypeArguments.Count > 0) {
156 var l = new List<XamlTypeName> ();
157 l.AddRange (from x in xamlType.TypeArguments.AsQueryable () select new XamlTypeName (x));
158 TypeArguments = l;
162 public XamlTypeName (string xamlNamespace, string name)
163 : this (xamlNamespace, name, null)
167 public XamlTypeName (string xamlNamespace, string name, IEnumerable<XamlTypeName> typeArguments)
168 : this ()
170 Namespace = xamlNamespace;
171 Name = name;
172 if (typeArguments != null) {
173 if (typeArguments.Any (t => t == null))
174 throw new ArgumentNullException ("typeArguments", "typeArguments array contains one or more null XamlTypeName");
175 var l = new List<XamlTypeName> ();
176 l.AddRange (typeArguments);
177 TypeArguments = l;
181 public string Name { get; set; }
182 public string Namespace { get; set; }
183 public IList<XamlTypeName> TypeArguments { get; private set; }
185 public override string ToString ()
187 return ToString (null);
190 public string ToString (INamespacePrefixLookup prefixLookup)
192 if (Namespace == null)
193 throw new InvalidOperationException ("Namespace must be set before calling ToString method.");
194 if (Name == null)
195 throw new InvalidOperationException ("Name must be set before calling ToString method.");
197 string ret;
198 if (prefixLookup == null)
199 ret = String.Concat ("{", Namespace, "}", Name);
200 else {
201 string p = prefixLookup.LookupPrefix (Namespace);
202 if (p == null)
203 throw new InvalidOperationException (String.Format ("Could not lookup prefix for namespace '{0}'", Namespace));
204 ret = p.Length == 0 ? Name : p + ":" + Name;
207 if (TypeArguments.Count > 0)
208 ret += String.Concat ("(", DoToString (TypeArguments, prefixLookup), ")");
210 return ret;