2 // Copyright (C) 2010 Novell Inc. http://novell.com
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:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
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.
24 using System.Collections.Generic;
27 namespace System.Xaml.Schema
29 public class XamlTypeName
31 public static XamlTypeName Parse (string typeName, IXamlNamespaceResolver namespaceResolver)
34 if (!TryParse (typeName, namespaceResolver, out n))
35 throw new FormatException (String.Format ("Invalid typeName: '{0}'", typeName));
39 public static bool TryParse (string typeName, IXamlNamespaceResolver namespaceResolver, out XamlTypeName result)
42 throw new ArgumentNullException ("typeName");
43 if (namespaceResolver == null)
44 throw new ArgumentNullException ("namespaceResolver");
47 IList<XamlTypeName> args = null;
49 int idx = typeName.IndexOf ('(');
51 if (typeName [typeName.Length - 1] != ')')
53 if (!TryParseList (typeName.Substring (idx + 1, typeName.Length - idx - 2), namespaceResolver, out args))
55 typeName = typeName.Substring (0, idx);
58 idx = typeName.IndexOf (':');
61 prefix = String.Empty;
64 prefix = typeName.Substring (0, idx);
65 local = typeName.Substring (idx + 1);
66 if (!XamlLanguage.IsValidXamlName (prefix))
69 if (!XamlLanguage.IsValidXamlName (local))
71 string ns = namespaceResolver.GetNamespace (prefix);
75 result = new XamlTypeName (ns, local, args);
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));
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");
97 var split = typeNameList.Split (commas);
98 if (split.Length == 0)
101 var arr = new XamlTypeName [split.Length];
103 for (int i = 0; i < split.Length; i++) {
104 var s = split [i].Trim ();
106 if (!TryParse (s, namespaceResolver, out tn))
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)
129 foreach (var ta in typeNameList) {
134 ret += ta.ToString (prefixLookup);
141 public XamlTypeName ()
145 static readonly XamlTypeName [] empty_type_args = new XamlTypeName [0];
147 public XamlTypeName (XamlType xamlType)
149 if (xamlType == null)
150 throw new ArgumentNullException ("xamlType");
151 Namespace = xamlType.PreferredXamlNamespace;
152 Name = xamlType.Name;
153 if (xamlType.TypeArguments != null && xamlType.TypeArguments.Count > 0) {
154 var l = new List<XamlTypeName> ();
155 l.AddRange (from x in xamlType.TypeArguments.AsQueryable () select new XamlTypeName (x));
159 TypeArguments = empty_type_args;
162 public XamlTypeName (string xamlNamespace, string name)
163 : this (xamlNamespace, name, null)
167 public XamlTypeName (string xamlNamespace, string name, IEnumerable<XamlTypeName> typeArguments)
169 Namespace = xamlNamespace;
171 if (typeArguments != null) {
172 if (typeArguments.Any (t => t == null))
173 throw new ArgumentNullException ("typeArguments", "typeArguments array contains one or more null XamlTypeName");
174 var l = new List<XamlTypeName> ();
175 l.AddRange (typeArguments);
179 TypeArguments = empty_type_args;
182 public string Name { get; set; }
183 public string Namespace { get; set; }
184 public IList<XamlTypeName> TypeArguments { get; private set; }
186 public override string ToString ()
188 return ToString (null);
191 public string ToString (INamespacePrefixLookup prefixLookup)
193 if (Namespace == null)
194 throw new InvalidOperationException ("Namespace must be set before calling ToString method.");
196 throw new InvalidOperationException ("Name must be set before calling ToString method.");
199 if (prefixLookup == null)
200 ret = String.Concat ("{", Namespace, "}", Name);
202 string p = prefixLookup.LookupPrefix (Namespace);
204 throw new InvalidOperationException (String.Format ("Could not lookup prefix for namespace '{0}'", Namespace));
205 ret = p.Length == 0 ? Name : p + ":" + Name;
208 if (TypeArguments.Count > 0)
209 ret += String.Concat ("(", DoToString (TypeArguments, prefixLookup), ")");