1 //------------------------------------------------------------------------------
2 // <copyright file="NamespaceList.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
9 namespace System
.Xml
.Schema
{
10 using System
.Collections
;
12 using System
.Diagnostics
;
14 internal class NamespaceList
{
15 public enum ListType
{
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) {
35 else if (namespaces
== "##other") {
36 type
= ListType
.Other
;
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
;
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());
66 public ListType Type
{
70 public string Excluded
{
71 get { return targetNamespace; }
74 public ICollection Enumerate
{
82 throw new InvalidOperationException();
87 public virtual bool Allows(string ns
) {
92 return ns
!= targetNamespace
&& ns
.Length
!= 0;
94 return set[ns
] != null;
100 public bool Allows(XmlQualifiedName qname
) {
101 return Allows(qname
.Namespace
);
104 public override string ToString() {
111 StringBuilder sb
= new StringBuilder();
113 foreach(string s
in set.Keys
) {
120 if (s
== targetNamespace
) {
121 sb
.Append("##targetNamespace");
123 else if (s
.Length
== 0) {
124 sb
.Append("##local");
130 return sb
.ToString();
136 public static bool IsSubset(NamespaceList sub
, NamespaceList super
) {
137 if (super
.type
== ListType
.Any
) {
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
);
148 Debug
.Assert(super
.type
== ListType
.Set
);
149 foreach (string ns
in sub
.set.Keys
) {
150 if (!super
.set.Contains(ns
)) {
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
172 foreach (string ns
in o2
.set.Keys
) {
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
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
) {
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
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
) {
207 if (o2
.set.Contains(o2
.targetNamespace
)) {
208 nslist
= new NamespaceList();
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
);
229 private NamespaceList
CompareSetToOther(NamespaceList other
) {
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
237 nslist
= new NamespaceList("##other", string.Empty
);
240 else if (this.set.Contains(string.Empty
)) { //clause 5.3 - Not expressible
243 else { //clause 5.4 - Set S does not contain negated ns or absent
244 nslist
= other
.Clone();
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
255 else if (o2
.type
== ListType
.Any
) { //clause 2 - o2 is any
258 else if (o1
.type
== ListType
.Set
&& o2
.type
== ListType
.Other
) { //Clause 3 o2 is other
260 nslist
.RemoveNamespace(o2
.targetNamespace
);
262 nslist
.RemoveNamespace(string.Empty
); //remove ##local
265 else if (o1
.type
== ListType
.Other
&& o2
.type
== ListType
.Set
) { //Clause 3 o1 is other
267 nslist
.RemoveNamespace(o1
.targetNamespace
);
269 nslist
.RemoveNamespace(string.Empty
); //remove ##local
272 else if (o1
.type
== ListType
.Set
&& o2
.type
== ListType
.Set
) { //clause 4
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
289 if (o1
.targetNamespace
== string.Empty
) { // clause 6 - o1 is negation of absent
292 else if (o2
.targetNamespace
== string.Empty
) { //clause 6 - o1 is negation of absent
296 //if it comes here, its not expressible //clause 5
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
;
321 return base.Allows(ns
);