Shape.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. //------------------------------------------------------------------------------
  2. // <copyright file="Shape.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">derekdb</owner>
  6. //------------------------------------------------------------------------------
  7. #if ENABLEDATABINDING
  8. using System;
  9. using System.Xml;
  10. using System.Xml.Schema;
  11. using System.Xml.XPath;
  12. using System.Collections;
  13. using System.Diagnostics;
  14. using System.ComponentModel;
  15. using System.Text;
  16. namespace System.Xml.XPath.DataBinding
  17. {
  18. internal enum BindingType {
  19. Text,
  20. Element,
  21. Attribute,
  22. ElementNested,
  23. Repeat,
  24. Sequence,
  25. Choice,
  26. All
  27. }
  28. internal sealed class Shape
  29. {
  30. string name;
  31. BindingType bindingType;
  32. ArrayList particles; // XmlSchemaElement or XmlSchemaAttribute
  33. ArrayList subShapes;
  34. Shape nestedShape;
  35. PropertyDescriptor[] propertyDescriptors;
  36. XmlSchemaElement containerDecl;
  37. static object[] emptyIList = new object[0];
  38. public Shape(string name, BindingType bindingType)
  39. {
  40. this.name = name;
  41. this.bindingType = bindingType;
  42. }
  43. public string Name {
  44. get { return this.name; }
  45. set { this.name = value; }
  46. }
  47. public BindingType BindingType {
  48. get { return this.bindingType; }
  49. set { this.bindingType = value; }
  50. }
  51. public XmlSchemaElement ContainerDecl {
  52. get { return this.containerDecl; }
  53. set { this.containerDecl = value; }
  54. }
  55. public bool IsNestedTable {
  56. get {
  57. switch (this.BindingType) {
  58. case BindingType.ElementNested:
  59. case BindingType.Repeat:
  60. case BindingType.Sequence:
  61. case BindingType.Choice:
  62. case BindingType.All:
  63. return true;
  64. default:
  65. return false;
  66. }
  67. }
  68. }
  69. public bool IsGroup {
  70. get {
  71. switch (this.BindingType) {
  72. case BindingType.Sequence:
  73. case BindingType.Choice:
  74. case BindingType.All:
  75. return true;
  76. default:
  77. return false;
  78. }
  79. }
  80. }
  81. public XmlSchemaType SchemaType {
  82. get {
  83. switch (this.bindingType) {
  84. case BindingType.Text:
  85. case BindingType.Element:
  86. case BindingType.ElementNested: {
  87. Debug.Assert(this.particles.Count == 1);
  88. XmlSchemaElement xse = (XmlSchemaElement)this.particles[0];
  89. return xse.ElementSchemaType;
  90. }
  91. case BindingType.Attribute: {
  92. Debug.Assert(this.particles.Count == 1);
  93. XmlSchemaAttribute xsa = (XmlSchemaAttribute)this.particles[0];
  94. return xsa.AttributeSchemaType;
  95. }
  96. default:
  97. return null;
  98. }
  99. }
  100. }
  101. public XmlSchemaElement XmlSchemaElement {
  102. get {
  103. switch (this.bindingType) {
  104. case BindingType.Text:
  105. case BindingType.Element:
  106. case BindingType.ElementNested: {
  107. Debug.Assert(this.particles.Count == 1);
  108. return (XmlSchemaElement)this.particles[0];
  109. }
  110. default:
  111. return this.containerDecl;
  112. }
  113. }
  114. }
  115. public IList Particles {
  116. get {
  117. if (null == this.particles)
  118. return emptyIList;
  119. return this.particles;
  120. }
  121. }
  122. public IList SubShapes {
  123. get {
  124. if (null == this.subShapes)
  125. return emptyIList;
  126. return this.subShapes;
  127. }
  128. }
  129. public Shape SubShape(int i) {
  130. return (Shape)SubShapes[i];
  131. }
  132. public Shape NestedShape {
  133. get {
  134. //Debug.Assert(this.bindingType == BindingType.ElementNested);
  135. return this.nestedShape;
  136. }
  137. set {
  138. this.nestedShape = value;
  139. }
  140. }
  141. public XmlQualifiedName AttributeName {
  142. get {
  143. Debug.Assert(this.bindingType == BindingType.Attribute);
  144. XmlSchemaAttribute xsa = (XmlSchemaAttribute)this.particles[0];
  145. return xsa.QualifiedName;
  146. }
  147. }
  148. public void Clear() {
  149. if (this.subShapes != null) {
  150. this.subShapes.Clear();
  151. this.subShapes = null;
  152. }
  153. if (this.particles != null) {
  154. this.particles.Clear();
  155. this.particles = null;
  156. }
  157. }
  158. public void AddParticle(XmlSchemaElement elem) {
  159. if (null == this.particles)
  160. this.particles = new ArrayList();
  161. Debug.Assert(this.bindingType != BindingType.Attribute);
  162. this.particles.Add(elem);
  163. }
  164. public void AddParticle(XmlSchemaAttribute elem) {
  165. Debug.Assert(this.bindingType == BindingType.Attribute);
  166. Debug.Assert(this.particles == null);
  167. this.particles = new ArrayList();
  168. this.particles.Add(elem);
  169. }
  170. public void AddSubShape(Shape shape) {
  171. if (null == this.subShapes)
  172. this.subShapes = new ArrayList();
  173. this.subShapes.Add(shape);
  174. foreach (object p in shape.Particles) {
  175. XmlSchemaElement xse = p as XmlSchemaElement;
  176. if (null != xse)
  177. AddParticle(xse);
  178. }
  179. }
  180. public void AddAttrShapeAt(Shape shape, int pos) {
  181. if (null == this.subShapes)
  182. this.subShapes = new ArrayList();
  183. this.subShapes.Insert(pos, shape);
  184. }
  185. public string[] SubShapeNames() {
  186. string[] names = new string[SubShapes.Count];
  187. for (int i=0; i<SubShapes.Count; i++)
  188. names[i] = this.SubShape(i).Name;
  189. return names;
  190. }
  191. public PropertyDescriptor[] PropertyDescriptors {
  192. get {
  193. if (null == this.propertyDescriptors) {
  194. PropertyDescriptor[] descs;
  195. switch (this.BindingType) {
  196. case BindingType.Element:
  197. case BindingType.Text:
  198. case BindingType.Attribute:
  199. case BindingType.Repeat:
  200. descs = new PropertyDescriptor[1];
  201. descs[0] = new XPathNodeViewPropertyDescriptor(this);
  202. break;
  203. case BindingType.ElementNested:
  204. descs = this.nestedShape.PropertyDescriptors;
  205. break;
  206. case BindingType.Sequence:
  207. case BindingType.Choice:
  208. case BindingType.All:
  209. descs = new PropertyDescriptor[SubShapes.Count];
  210. for (int i=0; i < descs.Length; i++) {
  211. descs[i] = new XPathNodeViewPropertyDescriptor(this, this.SubShape(i), i);
  212. }
  213. break;
  214. default:
  215. throw new NotSupportedException();
  216. }
  217. this.propertyDescriptors = descs;
  218. }
  219. return this.propertyDescriptors;
  220. }
  221. }
  222. public int FindNamedSubShape(string name) {
  223. for (int i=0; i<SubShapes.Count; i++) {
  224. Shape shape = SubShape(i);
  225. if (shape.Name == name)
  226. return i;
  227. }
  228. return -1;
  229. }
  230. public int FindMatchingSubShape(object particle) {
  231. for (int i=0; i<SubShapes.Count; i++) {
  232. Shape shape = SubShape(i);
  233. if (shape.IsParticleMatch(particle))
  234. return i;
  235. }
  236. return -1;
  237. }
  238. public bool IsParticleMatch(object particle) {
  239. for (int i=0; i<this.particles.Count; i++) {
  240. if (particle == this.particles[i])
  241. return true;
  242. }
  243. return false;
  244. }
  245. #if DEBUG
  246. public string DebugDump() {
  247. StringBuilder sb = new StringBuilder();
  248. DebugDump(sb,"");
  249. return sb.ToString();
  250. }
  251. void DebugDump(StringBuilder sb, String indent) {
  252. sb.AppendFormat("{0}{1} '{2}'", indent, this.BindingType.ToString(), this.Name);
  253. if (this.subShapes != null) {
  254. sb.AppendLine(" {");
  255. string subindent = String.Concat(indent, " ");
  256. foreach (Shape s in this.SubShapes) {
  257. s.DebugDump(sb, subindent);
  258. }
  259. sb.Append(indent);
  260. sb.Append('}');
  261. }
  262. sb.AppendLine();
  263. }
  264. #endif
  265. }
  266. }
  267. #endif