Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Xml / System / Xml / Schema / NamespaceList.cs
blob93ecf3f6045dd2ddb75b75b9b2498a2db93908c7
1 //------------------------------------------------------------------------------
2 // <copyright file="NamespaceList.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
9 namespace System.Xml.Schema {
10 using System.Collections;
11 using System.Text;
12 using System.Diagnostics;
14 internal class NamespaceList {
15 public enum ListType {
16 Any,
17 Other,
18 Set
21 private ListType type = ListType.Any;
22 private Hashtable set = null;
23 private string targetNamespace;
25 public NamespaceList() {
28 public NamespaceList(string namespaces, string targetNamespace) {
29 Debug.Assert(targetNamespace != null);
30 this.targetNamespace = targetNamespace;
31 namespaces = namespaces.Trim();
32 if (namespaces == "##any" || namespaces.Length == 0) {
33 type = ListType.Any;
35 else if (namespaces == "##other") {
36 type = ListType.Other;
38 else {
39 type = ListType.Set;
40 set = new Hashtable();
41 string[] splitString = XmlConvert.SplitString(namespaces);
42 for (int i = 0; i < splitString.Length; ++i) {
43 if (splitString[i] == "##local") {
44 set[string.Empty] = string.Empty;
46 else if (splitString[i] == "##targetNamespace") {
47 set[targetNamespace] = targetNamespace;
49 else {
50 XmlConvert.ToUri (splitString[i]); // can throw
51 set[splitString[i]] = splitString[i];
57 public NamespaceList Clone() {
58 NamespaceList nsl = (NamespaceList)MemberwiseClone();
59 if (type == ListType.Set) {
60 Debug.Assert(set != null);
61 nsl.set = (Hashtable)(set.Clone());
63 return nsl;
66 public ListType Type {
67 get { return type; }
70 public string Excluded {
71 get { return targetNamespace; }
74 public ICollection Enumerate {
75 get {
76 switch (type) {
77 case ListType.Set:
78 return set.Keys;
79 case ListType.Other:
80 case ListType.Any:
81 default:
82 throw new InvalidOperationException();
87 public virtual bool Allows(string ns) {
88 switch (type) {
89 case ListType.Any:
90 return true;
91 case ListType.Other:
92 return ns != targetNamespace && ns.Length != 0;
93 case ListType.Set:
94 return set[ns] != null;
96 Debug.Assert(false);
97 return false;
100 public bool Allows(XmlQualifiedName qname) {
101 return Allows(qname.Namespace);
104 public override string ToString() {
105 switch (type) {
106 case ListType.Any:
107 return "##any";
108 case ListType.Other:
109 return "##other";
110 case ListType.Set:
111 StringBuilder sb = new StringBuilder();
112 bool first = true;
113 foreach(string s in set.Keys) {
114 if (first) {
115 first = false;
117 else {
118 sb.Append(" ");
120 if (s == targetNamespace) {
121 sb.Append("##targetNamespace");
123 else if (s.Length == 0) {
124 sb.Append("##local");
126 else {
127 sb.Append(s);
130 return sb.ToString();
132 Debug.Assert(false);
133 return string.Empty;
136 public static bool IsSubset(NamespaceList sub, NamespaceList super) {
137 if (super.type == ListType.Any) {
138 return true;
140 else if (sub.type == ListType.Other && super.type == ListType.Other) {
141 return super.targetNamespace == sub.targetNamespace;
143 else if (sub.type == ListType.Set) {
144 if (super.type == ListType.Other) {
145 return !sub.set.Contains(super.targetNamespace);
147 else {
148 Debug.Assert(super.type == ListType.Set);
149 foreach (string ns in sub.set.Keys) {
150 if (!super.set.Contains(ns)) {
151 return false;
154 return true;
157 return false;
161 public static NamespaceList Union(NamespaceList o1, NamespaceList o2, bool v1Compat) {
162 NamespaceList nslist = null;
163 Debug.Assert(o1 != o2);
164 if (o1.type == ListType.Any) { //clause 2 - o1 is Any
165 nslist = new NamespaceList();
167 else if (o2.type == ListType.Any) { //clause 2 - o2 is Any
168 nslist = new NamespaceList();
170 else if (o1.type == ListType.Set && o2.type == ListType.Set) { //clause 3 , both are sets
171 nslist = o1.Clone();
172 foreach (string ns in o2.set.Keys) {
173 nslist.set[ns] = ns;
176 else if (o1.type == ListType.Other && o2.type == ListType.Other) { //clause 4, both are negations
177 if (o1.targetNamespace == o2.targetNamespace) { //negation of same value
178 nslist = o1.Clone();
180 else { //Not a breaking change, going from not expressible to not(absent)
181 nslist = new NamespaceList("##other", string.Empty); //clause 4, negations of different values, result is not(absent)
184 else if (o1.type == ListType.Set && o2.type == ListType.Other) {
185 if (v1Compat) {
186 if (o1.set.Contains(o2.targetNamespace)) {
187 nslist = new NamespaceList();
189 else { //This was not there originally in V1, added for consistency since its not breaking
190 nslist = o2.Clone();
193 else {
194 if (o2.targetNamespace != string.Empty) { //clause 5, o1 is set S, o2 is not(tns)
195 nslist = o1.CompareSetToOther(o2);
197 else if (o1.set.Contains(string.Empty)) { //clause 6.1 - set S includes absent, o2 is not(absent)
198 nslist = new NamespaceList();
200 else { //clause 6.2 - set S does not include absent, result is not(absent)
201 nslist = new NamespaceList("##other", string.Empty);
205 else if (o2.type == ListType.Set && o1.type == ListType.Other) {
206 if (v1Compat) {
207 if (o2.set.Contains(o2.targetNamespace)) {
208 nslist = new NamespaceList();
210 else {
211 nslist = o1.Clone();
214 else { //New rules
215 if (o1.targetNamespace != string.Empty) { //clause 5, o1 is set S, o2 is not(tns)
216 nslist = o2.CompareSetToOther(o1);
218 else if (o2.set.Contains(string.Empty)) { //clause 6.1 - set S includes absent, o2 is not(absent)
219 nslist = new NamespaceList();
221 else { //clause 6.2 - set S does not include absent, result is not(absent)
222 nslist = new NamespaceList("##other", string.Empty);
226 return nslist;
229 private NamespaceList CompareSetToOther(NamespaceList other) {
230 //clause 5.1
231 NamespaceList nslist = null;
232 if (this.set.Contains(other.targetNamespace)) { //S contains negated ns
233 if (this.set.Contains(string.Empty)) { // AND S contains absent
234 nslist = new NamespaceList(); //any is the result
236 else { //clause 5.2
237 nslist = new NamespaceList("##other", string.Empty);
240 else if (this.set.Contains(string.Empty)) { //clause 5.3 - Not expressible
241 nslist = null;
243 else { //clause 5.4 - Set S does not contain negated ns or absent
244 nslist = other.Clone();
246 return nslist;
249 public static NamespaceList Intersection(NamespaceList o1, NamespaceList o2, bool v1Compat) {
250 NamespaceList nslist = null;
251 Debug.Assert(o1 != o2); //clause 1
252 if (o1.type == ListType.Any) { //clause 2 - o1 is any
253 nslist = o2.Clone();
255 else if (o2.type == ListType.Any) { //clause 2 - o2 is any
256 nslist = o1.Clone();
258 else if (o1.type == ListType.Set && o2.type == ListType.Other) { //Clause 3 o2 is other
259 nslist = o1.Clone();
260 nslist.RemoveNamespace(o2.targetNamespace);
261 if (!v1Compat) {
262 nslist.RemoveNamespace(string.Empty); //remove ##local
265 else if (o1.type == ListType.Other && o2.type == ListType.Set) { //Clause 3 o1 is other
266 nslist = o2.Clone();
267 nslist.RemoveNamespace(o1.targetNamespace);
268 if (!v1Compat) {
269 nslist.RemoveNamespace(string.Empty); //remove ##local
272 else if (o1.type == ListType.Set && o2.type == ListType.Set) { //clause 4
273 nslist = o1.Clone();
274 nslist = new NamespaceList();
275 nslist.type = ListType.Set;
276 nslist.set = new Hashtable();
277 foreach(string ns in o1.set.Keys) {
278 if (o2.set.Contains(ns)) {
279 nslist.set.Add(ns, ns);
283 else if (o1.type == ListType.Other && o2.type == ListType.Other) {
284 if (o1.targetNamespace == o2.targetNamespace) { //negation of same namespace name
285 nslist = o1.Clone();
286 return nslist;
288 if (!v1Compat) {
289 if (o1.targetNamespace == string.Empty) { // clause 6 - o1 is negation of absent
290 nslist = o2.Clone();
292 else if (o2.targetNamespace == string.Empty) { //clause 6 - o1 is negation of absent
293 nslist = o1.Clone();
296 //if it comes here, its not expressible //clause 5
298 return nslist;
301 private void RemoveNamespace(string tns) {
302 if (this.set[tns] != null) {
303 this.set.Remove(tns);
307 public bool IsEmpty() {
308 return ((type == ListType.Set) && ((set == null) || set.Count == 0));
313 internal class NamespaceListV1Compat : NamespaceList {
314 public NamespaceListV1Compat(string namespaces, string targetNamespace) : base(namespaces, targetNamespace) {}
316 public override bool Allows(string ns) {
317 if (this.Type == ListType.Other) {
318 return ns != Excluded;
320 else {
321 return base.Allows(ns);