DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
SqlXmlNode.cs
Go to the documentation of this file.
1 using System;
2 using System.IO;
3 using System.Text;
4 using System.Xml;
5 using System.Xml.XPath;
6 
7 namespace Deveel.Data.Sql.Objects {
8  public sealed class SqlXmlNode : ISqlObject, IDisposable {
9  private byte[] content;
10  private XPathNavigator navigator;
11 
12  public static readonly SqlXmlNode Null = new SqlXmlNode(null, true);
13 
14  private SqlXmlNode(byte[] content, bool isNull) {
15  this.content = content;
16  IsNull = isNull;
17 
18  navigator = CreateNavigator();
19  }
20 
21  public SqlXmlNode(byte[] content)
22  : this(content, false) {
23  }
24 
25  int IComparable.CompareTo(object obj) {
26  throw new NotSupportedException();
27  }
28 
29  int IComparable<ISqlObject>.CompareTo(ISqlObject other) {
30  throw new NotSupportedException();
31  }
32 
33  public bool IsNull { get; private set; }
34 
36  return false;
37  }
38 
39  private XPathNavigator CreateNavigator() {
40  if (IsNull)
41  return null;
42 
43  using (var stream = new MemoryStream(content)) {
44  using (var xmlReader = new StreamReader(stream, Encoding.UTF8)) {
45  var xmlDocument = new XmlDocument();
46  xmlDocument.Load(xmlReader);
47  return xmlDocument.CreateNavigator();
48  }
49  }
50  }
51 
52  private XmlNamespaceManager NamespaceManager(string xmlNs) {
53  XmlNamespaceManager nsManager = null;
54  if (!String.IsNullOrEmpty(xmlNs)) {
55  var nameTable = new NameTable();
56  nameTable.Add(xmlNs);
57  nsManager = new XmlNamespaceManager(nameTable);
58  }
59 
60  return nsManager;
61  }
62 
63  private void AsserCanEdit() {
64  if (!navigator.CanEdit)
65  throw new NotSupportedException("The current node cannot be edited.");
66  }
67 
68  private byte[] SelectSingle(string xpath, string xmlNs) {
69  var nodeNavigator = navigator.SelectSingleNode(xpath, NamespaceManager(xmlNs));
70  if (nodeNavigator == null)
71  return null;
72 
73  return AsBinary(nodeNavigator);
74  }
75 
76  private static byte[] AsBinary(XPathNavigator navigator) {
77  using (var stream = new MemoryStream()) {
78  using (var writer = new StreamWriter(stream, Encoding.UTF8)) {
79  using (var xmlWriter = new XmlTextWriter(writer)) {
80  xmlWriter.Formatting = Formatting.None;
81 
82  navigator.WriteSubtree(xmlWriter);
83 
84  xmlWriter.Flush();
85 
86  return stream.ToArray();
87  }
88  }
89  }
90  }
91 
92  private bool SelectSingleValue(string xpath, string xmlNs, out object value, out Type valueType) {
93  value = null;
94  valueType = null;
95 
96  var nodeNavigator = navigator.SelectSingleNode(xpath, NamespaceManager(xmlNs));
97  if (nodeNavigator == null)
98  return false;
99 
100  valueType = nodeNavigator.ValueType;
101  value = nodeNavigator.TypedValue;
102  return true;
103  }
104 
105  private bool Update(string xpath, object value, string xmlNs, out byte[] updated) {
106  AsserCanEdit();
107 
108  updated = null;
109 
110  var rootNavigator = navigator.Clone();
111  var nodeNavigator = rootNavigator.SelectSingleNode(xpath, NamespaceManager(xmlNs));
112  if (nodeNavigator == null)
113  return false;
114 
115  nodeNavigator.SetValue(value.ToString());
116 
117  updated = AsBinary(rootNavigator);
118  return true;
119  }
120 
121  public SqlXmlNode Extract(string xpath) {
122  return Extract(xpath, null);
123  }
124 
125  public SqlXmlNode Extract(string xpath, string xmlNs) {
126  if (IsNull)
127  return Null;
128 
129  var bytes = SelectSingle(xpath, xmlNs);
130  if (bytes == null)
131  return Null;
132 
133  // TODO: Control the encoding on properties of the type...
134  return new SqlXmlNode(bytes);
135  }
136 
137  public ISqlObject ExtractValue(string xpath) {
138  return ExtractValue(xpath, null);
139  }
140 
141  public ISqlObject ExtractValue(string xpath, string xmlNs) {
142  if (IsNull)
143  return Null;
144 
145  object value;
146  Type valueType;
147  if (!SelectSingleValue(xpath, xmlNs, out value, out valueType))
148  return SqlNull.Value;
149 
150  if (valueType == typeof(string))
151  return new SqlString((string)value);
152 
153  // TODO: support other types
154 
155  throw new NotSupportedException();
156  }
157 
158  public SqlXmlNode Update(string xpath, ISqlObject value) {
159  return Update(xpath, value, null);
160  }
161 
162  public SqlXmlNode Update(string xpath, ISqlObject value, string xmlNs) {
163  byte[] updated;
164  if (!Update(xpath, value, xmlNs, out updated))
165  return Null;
166 
167  return new SqlXmlNode(updated);
168  }
169 
171  if (IsNull)
172  return SqlString.Null;
173 
174  var bytes = Encoding.Convert(Encoding.UTF8, Encoding.Unicode, content);
175  return new SqlString(bytes);
176  }
177 
179  if (IsNull)
180  return SqlBinary.Null;
181 
182  return new SqlBinary(content);
183  }
184 
185  public void Dispose() {
186  navigator = null;
187  content = null;
188  }
189 
190  public SqlXmlNode AppendChild(string xpath, SqlXmlNode value) {
191  throw new NotImplementedException();
192  }
193 
194  public SqlXmlNode Delete(string xpath) {
195  throw new NotImplementedException();
196  }
197 
198  public XmlNode ToXmlNode() {
199  throw new NotImplementedException();
200  }
201 
202  public byte[] ToBytes() {
203  return content;
204  }
205 
206  public SqlXmlNode InsertChild(string xpath, SqlXmlNode child, SqlXmlNode value) {
207  throw new NotImplementedException();
208  }
209  }
210 }
SqlXmlNode Extract(string xpath)
Definition: SqlXmlNode.cs:121
static byte[] AsBinary(XPathNavigator navigator)
Definition: SqlXmlNode.cs:76
SqlXmlNode InsertChild(string xpath, SqlXmlNode child, SqlXmlNode value)
Definition: SqlXmlNode.cs:206
SqlXmlNode AppendChild(string xpath, SqlXmlNode value)
Definition: SqlXmlNode.cs:190
SqlXmlNode(byte[] content, bool isNull)
Definition: SqlXmlNode.cs:14
Implements a BINARY object that handles a limited number of bytes, not exceding MaxLength.
Definition: SqlBinary.cs:27
byte[] SelectSingle(string xpath, string xmlNs)
Definition: SqlXmlNode.cs:68
static readonly SqlNull Value
Definition: SqlNull.cs:24
Defines the contract for a valid SQL Object
Definition: ISqlObject.cs:23
A user-defined TYPE that holds complex objects in a database column.
ISqlObject ExtractValue(string xpath, string xmlNs)
Definition: SqlXmlNode.cs:141
XPathNavigator CreateNavigator()
Definition: SqlXmlNode.cs:39
SqlXmlNode Delete(string xpath)
Definition: SqlXmlNode.cs:194
SqlXmlNode Extract(string xpath, string xmlNs)
Definition: SqlXmlNode.cs:125
bool IsComparableTo(ISqlObject other)
Checks if the current object is comparable with the given one.
ISqlObject ExtractValue(string xpath)
Definition: SqlXmlNode.cs:137
SqlXmlNode Update(string xpath, ISqlObject value, string xmlNs)
Definition: SqlXmlNode.cs:162
bool SelectSingleValue(string xpath, string xmlNs, out object value, out Type valueType)
Definition: SqlXmlNode.cs:92
bool Update(string xpath, object value, string xmlNs, out byte[] updated)
Definition: SqlXmlNode.cs:105
Deveel.Data.Sql.Objects.SqlString SqlString
Definition: DataObject.cs:27
SqlXmlNode Update(string xpath, ISqlObject value)
Definition: SqlXmlNode.cs:158
static readonly SqlBinary Null
Definition: SqlBinary.cs:29
XmlNamespaceManager NamespaceManager(string xmlNs)
Definition: SqlXmlNode.cs:52