aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Data/WindowsInstaller/TableDefinition.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2017-12-07 14:17:39 -0800
committerRob Mensching <rob@firegiant.com>2017-12-07 14:17:39 -0800
commit221da62c05ef2b515eb507c77655514cd0ec32a4 (patch)
treefabec5b8ac871f17de6fe0aad3e6188b9af42bfb /src/WixToolset.Data/WindowsInstaller/TableDefinition.cs
parentca376995792d2e2a1a7f39760989496702a8f603 (diff)
downloadwix-221da62c05ef2b515eb507c77655514cd0ec32a4.tar.gz
wix-221da62c05ef2b515eb507c77655514cd0ec32a4.tar.bz2
wix-221da62c05ef2b515eb507c77655514cd0ec32a4.zip
Reintegrate MSI constructs into WxToolset.Data.WindowsInstaller namespace
Diffstat (limited to 'src/WixToolset.Data/WindowsInstaller/TableDefinition.cs')
-rw-r--r--src/WixToolset.Data/WindowsInstaller/TableDefinition.cs218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/WixToolset.Data/WindowsInstaller/TableDefinition.cs b/src/WixToolset.Data/WindowsInstaller/TableDefinition.cs
new file mode 100644
index 00000000..518f0926
--- /dev/null
+++ b/src/WixToolset.Data/WindowsInstaller/TableDefinition.cs
@@ -0,0 +1,218 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Data.WindowsInstaller
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Collections.ObjectModel;
8 using System.Xml;
9
10 /// <summary>
11 /// Definition of a table in a database.
12 /// </summary>
13 public sealed class TableDefinition : IComparable<TableDefinition>
14 {
15 /// <summary>
16 /// Tracks the maximum number of columns supported in a real table.
17 /// This is a Windows Installer limitation.
18 /// </summary>
19 public const int MaxColumnsInRealTable = 32;
20
21 /// <summary>
22 /// Creates a table definition.
23 /// </summary>
24 /// <param name="name">Name of table to create.</param>
25 /// <param name="columns">Column definitions for the table.</param>
26 /// <param name="unreal">Flag if table is unreal.</param>
27 /// <param name="bootstrapperApplicationData">Flag if table is part of UX Manifest.</param>
28 public TableDefinition(string name, IList<ColumnDefinition> columns, bool unreal = false, bool bootstrapperApplicationData = false)
29 {
30 this.Name = name;
31 this.Unreal = unreal;
32 this.BootstrapperApplicationData = bootstrapperApplicationData;
33
34 this.Columns = new ReadOnlyCollection<ColumnDefinition>(columns);
35 }
36
37 /// <summary>
38 /// Gets the name of the table.
39 /// </summary>
40 /// <value>Name of the table.</value>
41 public string Name { get; private set; }
42
43 /// <summary>
44 /// Gets if the table is unreal.
45 /// </summary>
46 /// <value>Flag if table is unreal.</value>
47 public bool Unreal { get; private set; }
48
49 /// <summary>
50 /// Gets if the table is a part of the bootstrapper application data manifest.
51 /// </summary>
52 /// <value>Flag if table is a part of the bootstrapper application data manifest.</value>
53 public bool BootstrapperApplicationData { get; private set; }
54
55 /// <summary>
56 /// Gets the collection of column definitions for this table.
57 /// </summary>
58 /// <value>Collection of column definitions for this table.</value>
59 public IList<ColumnDefinition> Columns { get; private set; }
60
61 /// <summary>
62 /// Gets the column definition in the table by index.
63 /// </summary>
64 /// <param name="columnIndex">Index of column to locate.</param>
65 /// <value>Column definition in the table by index.</value>
66 public ColumnDefinition this[int columnIndex]
67 {
68 get { return this.Columns[columnIndex]; }
69 }
70
71 /// <summary>
72 /// Compares this table definition to another table definition.
73 /// </summary>
74 /// <remarks>
75 /// Only Windows Installer traits are compared, allowing for updates to WiX-specific table definitions.
76 /// </remarks>
77 /// <param name="updated">The updated <see cref="TableDefinition"/> to compare with this target definition.</param>
78 /// <returns>0 if the tables' core properties are the same; otherwise, non-0.</returns>
79 public int CompareTo(TableDefinition updated)
80 {
81 // by definition, this object is greater than null
82 if (null == updated)
83 {
84 return 1;
85 }
86
87 // compare the table names
88 int ret = String.Compare(this.Name, updated.Name, StringComparison.Ordinal);
89
90 // compare the column count
91 if (0 == ret)
92 {
93 // transforms can only add columns
94 ret = Math.Min(0, updated.Columns.Count - this.Columns.Count);
95
96 // compare name, type, and length of each column
97 for (int i = 0; 0 == ret && this.Columns.Count > i; i++)
98 {
99 ColumnDefinition thisColumnDef = this.Columns[i];
100 ColumnDefinition updatedColumnDef = updated.Columns[i];
101
102 ret = thisColumnDef.CompareTo(updatedColumnDef);
103 }
104 }
105
106 return ret;
107 }
108
109 /// <summary>
110 /// Parses table definition from xml reader.
111 /// </summary>
112 /// <param name="reader">Reader to get data from.</param>
113 /// <returns>The TableDefintion represented by the Xml.</returns>
114 internal static TableDefinition Read(XmlReader reader)
115 {
116 bool empty = reader.IsEmptyElement;
117 string name = null;
118 bool unreal = false;
119 bool bootstrapperApplicationData = false;
120
121 while (reader.MoveToNextAttribute())
122 {
123 switch (reader.LocalName)
124 {
125 case "name":
126 name = reader.Value;
127 break;
128 case "unreal":
129 unreal = reader.Value.Equals("yes");
130 break;
131 case "bootstrapperApplicationData":
132 bootstrapperApplicationData = reader.Value.Equals("yes");
133 break;
134 }
135 }
136
137 if (null == name)
138 {
139 throw new XmlException();
140 }
141
142 List<ColumnDefinition> columns = new List<ColumnDefinition>();
143 bool hasPrimaryKeyColumn = false;
144
145 // parse the child elements
146 if (!empty)
147 {
148 bool done = false;
149
150 while (!done && reader.Read())
151 {
152 switch (reader.NodeType)
153 {
154 case XmlNodeType.Element:
155 switch (reader.LocalName)
156 {
157 case "columnDefinition":
158 ColumnDefinition columnDefinition = ColumnDefinition.Read(reader);
159 columns.Add(columnDefinition);
160
161 if (columnDefinition.PrimaryKey)
162 {
163 hasPrimaryKeyColumn = true;
164 }
165 break;
166 default:
167 throw new XmlException();
168 }
169 break;
170 case XmlNodeType.EndElement:
171 done = true;
172 break;
173 }
174 }
175
176 if (!unreal && !bootstrapperApplicationData && !hasPrimaryKeyColumn)
177 {
178 throw new WixException(WixDataErrors.RealTableMissingPrimaryKeyColumn(SourceLineNumber.CreateFromUri(reader.BaseURI), name));
179 }
180
181 if (!done)
182 {
183 throw new XmlException();
184 }
185 }
186
187 return new TableDefinition(name, columns, unreal, bootstrapperApplicationData);
188 }
189
190 /// <summary>
191 /// Persists an output in an XML format.
192 /// </summary>
193 /// <param name="writer">XmlWriter where the Output should persist itself as XML.</param>
194 internal void Write(XmlWriter writer)
195 {
196 writer.WriteStartElement("tableDefinition", TableDefinitionCollection.XmlNamespaceUri);
197
198 writer.WriteAttributeString("name", this.Name);
199
200 if (this.Unreal)
201 {
202 writer.WriteAttributeString("unreal", "yes");
203 }
204
205 if (this.BootstrapperApplicationData)
206 {
207 writer.WriteAttributeString("bootstrapperApplicationData", "yes");
208 }
209
210 foreach (ColumnDefinition columnDefinition in this.Columns)
211 {
212 columnDefinition.Write(writer);
213 }
214
215 writer.WriteEndElement();
216 }
217 }
218}