aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Data/WindowsInstaller/Table.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/Table.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/Table.cs')
-rw-r--r--src/WixToolset.Data/WindowsInstaller/Table.cs333
1 files changed, 333 insertions, 0 deletions
diff --git a/src/WixToolset.Data/WindowsInstaller/Table.cs b/src/WixToolset.Data/WindowsInstaller/Table.cs
new file mode 100644
index 00000000..7fcc1b31
--- /dev/null
+++ b/src/WixToolset.Data/WindowsInstaller/Table.cs
@@ -0,0 +1,333 @@
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.Diagnostics;
8 using System.Xml;
9 using WixToolset.Data.WindowsInstaller.Rows;
10
11 /// <summary>
12 /// Object that represents a table in a database.
13 /// </summary>
14 public class Table
15 {
16 /// <summary>
17 /// Creates a table.
18 /// </summary>
19 /// <param name="tableDefinition">Definition of the table.</param>
20 public Table(TableDefinition tableDefinition)
21 {
22 this.Definition = tableDefinition;
23 this.Rows = new List<Row>();
24 }
25
26 /// <summary>
27 /// Gets the table definition.
28 /// </summary>
29 /// <value>Definition of the table.</value>
30 public TableDefinition Definition { get; }
31
32 /// <summary>
33 /// Gets the name of the table.
34 /// </summary>
35 /// <value>Name of the table.</value>
36 public string Name => this.Definition.Name;
37
38 /// <summary>
39 /// Gets or sets the table transform operation.
40 /// </summary>
41 /// <value>The table transform operation.</value>
42 public TableOperation Operation { get; set; }
43
44 /// <summary>
45 /// Gets the rows contained in the table.
46 /// </summary>
47 /// <value>Rows contained in the table.</value>
48 public IList<Row> Rows { get; }
49
50 /// <summary>
51 /// Creates a new row in the table.
52 /// </summary>
53 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
54 /// <param name="add">Specifies whether to only create the row or add it to the table automatically.</param>
55 /// <returns>Row created in table.</returns>
56 public Row CreateRow(SourceLineNumber sourceLineNumbers, bool add = true)
57 {
58 Row row;
59
60 switch (this.Name)
61 {
62 case "BBControl":
63 row = new BBControlRow(sourceLineNumbers, this);
64 break;
65 case "WixBundlePackage":
66 row = new WixBundlePackageRow(sourceLineNumbers, this);
67 break;
68 case "WixBundleExePackage":
69 row = new WixBundleExePackageRow(sourceLineNumbers, this);
70 break;
71 case "WixBundleMsiPackage":
72 row = new WixBundleMsiPackageRow(sourceLineNumbers, this);
73 break;
74 case "WixBundleMspPackage":
75 row = new WixBundleMspPackageRow(sourceLineNumbers, this);
76 break;
77 case "WixBundleMsuPackage":
78 row = new WixBundleMsuPackageRow(sourceLineNumbers, this);
79 break;
80 case "Component":
81 row = new ComponentRow(sourceLineNumbers, this);
82 break;
83 case "WixBundleContainer":
84 row = new WixBundleContainerRow(sourceLineNumbers, this);
85 break;
86 case "Control":
87 row = new ControlRow(sourceLineNumbers, this);
88 break;
89 case "File":
90 row = new FileRow(sourceLineNumbers, this);
91 break;
92 case "WixBundleMsiFeature":
93 row = new WixBundleMsiFeatureRow(sourceLineNumbers, this);
94 break;
95 case "WixBundleMsiProperty":
96 row = new WixBundleMsiPropertyRow(sourceLineNumbers, this);
97 break;
98 case "Media":
99 row = new MediaRow(sourceLineNumbers, this);
100 break;
101 case "WixBundlePayload":
102 row = new WixBundlePayloadRow(sourceLineNumbers, this);
103 break;
104 case "Property":
105 row = new PropertyRow(sourceLineNumbers, this);
106 break;
107 case "WixRelatedBundle":
108 row = new WixRelatedBundleRow(sourceLineNumbers, this);
109 break;
110 case "WixBundleRelatedPackage":
111 row = new WixBundleRelatedPackageRow(sourceLineNumbers, this);
112 break;
113 case "WixBundleRollbackBoundary":
114 row = new WixBundleRollbackBoundaryRow(sourceLineNumbers, this);
115 break;
116 case "Upgrade":
117 row = new UpgradeRow(sourceLineNumbers, this);
118 break;
119 case "WixBundleVariable":
120 row = new WixBundleVariableRow(sourceLineNumbers, this);
121 break;
122 case "WixAction":
123 row = new WixActionRow(sourceLineNumbers, this);
124 break;
125 case "WixApprovedExeForElevation":
126 row = new WixApprovedExeForElevationRow(sourceLineNumbers, this);
127 break;
128 case "WixBundle":
129 row = new WixBundleRow(sourceLineNumbers, this);
130 break;
131 case "WixBundlePackageExitCode":
132 row = new WixBundlePackageExitCodeRow(sourceLineNumbers, this);
133 break;
134 case "WixBundlePatchTargetCode":
135 row = new WixBundlePatchTargetCodeRow(sourceLineNumbers, this);
136 break;
137 case "WixBundleSlipstreamMsp":
138 row = new WixBundleSlipstreamMspRow(sourceLineNumbers, this);
139 break;
140 case "WixBundleUpdate":
141 row = new WixBundleUpdateRow(sourceLineNumbers, this);
142 break;
143 case "WixBundleCatalog":
144 row = new WixBundleCatalogRow(sourceLineNumbers, this);
145 break;
146 case "WixChain":
147 row = new WixChainRow(sourceLineNumbers, this);
148 break;
149 case "WixChainItem":
150 row = new WixChainItemRow(sourceLineNumbers, this);
151 break;
152 case "WixBundlePackageCommandLine":
153 row = new WixBundlePackageCommandLineRow(sourceLineNumbers, this);
154 break;
155 case "WixComplexReference":
156 row = new WixComplexReferenceRow(sourceLineNumbers, this);
157 break;
158 case "WixDeltaPatchFile":
159 row = new WixDeltaPatchFileRow(sourceLineNumbers, this);
160 break;
161 case "WixDeltaPatchSymbolPaths":
162 row = new WixDeltaPatchSymbolPathsRow(sourceLineNumbers, this);
163 break;
164 case "WixFile":
165 row = new WixFileRow(sourceLineNumbers, this);
166 break;
167 case "WixGroup":
168 row = new WixGroupRow(sourceLineNumbers, this);
169 break;
170 case "WixMedia":
171 row = new WixMediaRow(sourceLineNumbers, this);
172 break;
173 case "WixMediaTemplate":
174 row = new WixMediaTemplateRow(sourceLineNumbers, this);
175 break;
176 case "WixMerge":
177 row = new WixMergeRow(sourceLineNumbers, this);
178 break;
179 case "WixPayloadProperties":
180 row = new WixPayloadPropertiesRow(sourceLineNumbers, this);
181 break;
182 case "WixProperty":
183 row = new WixPropertyRow(sourceLineNumbers, this);
184 break;
185 case "WixSimpleReference":
186 row = new WixSimpleReferenceRow(sourceLineNumbers, this);
187 break;
188 case "WixUpdateRegistration":
189 row = new WixUpdateRegistrationRow(sourceLineNumbers, this);
190 break;
191
192 default:
193 row = new Row(sourceLineNumbers, this);
194 break;
195 }
196
197 if (add)
198 {
199 this.Rows.Add(row);
200 }
201
202 return row;
203 }
204
205 /// <summary>
206 /// Parse a table from the xml.
207 /// </summary>
208 /// <param name="reader">XmlReader where the intermediate is persisted.</param>
209 /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param>
210 /// <returns>The parsed table.</returns>
211 internal static Table Read(XmlReader reader, TableDefinitionCollection tableDefinitions)
212 {
213 Debug.Assert("table" == reader.LocalName);
214
215 bool empty = reader.IsEmptyElement;
216 TableOperation operation = TableOperation.None;
217 string name = null;
218
219 while (reader.MoveToNextAttribute())
220 {
221 switch (reader.LocalName)
222 {
223 case "name":
224 name = reader.Value;
225 break;
226 case "op":
227 switch (reader.Value)
228 {
229 case "add":
230 operation = TableOperation.Add;
231 break;
232 case "drop":
233 operation = TableOperation.Drop;
234 break;
235 default:
236 throw new XmlException();
237 }
238 break;
239 }
240 }
241
242 if (null == name)
243 {
244 throw new XmlException();
245 }
246
247 TableDefinition tableDefinition = tableDefinitions[name];
248 Table table = new Table(tableDefinition);
249 table.Operation = operation;
250
251 if (!empty)
252 {
253 bool done = false;
254
255 // loop through all the rows in a table
256 while (!done && reader.Read())
257 {
258 switch (reader.NodeType)
259 {
260 case XmlNodeType.Element:
261 switch (reader.LocalName)
262 {
263 case "row":
264 Row.Read(reader, table);
265 break;
266 default:
267 throw new XmlException();
268 }
269 break;
270 case XmlNodeType.EndElement:
271 done = true;
272 break;
273 }
274 }
275
276 if (!done)
277 {
278 throw new XmlException();
279 }
280 }
281
282 return table;
283 }
284
285 /// <summary>
286 /// Persists a row in an XML format.
287 /// </summary>
288 /// <param name="writer">XmlWriter where the Row should persist itself as XML.</param>
289 internal void Write(XmlWriter writer)
290 {
291 if (null == writer)
292 {
293 throw new ArgumentNullException("writer");
294 }
295
296 writer.WriteStartElement("table", Intermediate.XmlNamespaceUri);
297 writer.WriteAttributeString("name", this.Name);
298
299 if (TableOperation.None != this.Operation)
300 {
301 writer.WriteAttributeString("op", this.Operation.ToString().ToLowerInvariant());
302 }
303
304 foreach (var row in this.Rows)
305 {
306 row.Write(writer);
307 }
308
309 writer.WriteEndElement();
310 }
311
312 /// <summary>
313 /// Validates the rows of this OutputTable and throws if it collides on
314 /// primary keys.
315 /// </summary>
316 public void ValidateRows()
317 {
318 var primaryKeys = new Dictionary<string, SourceLineNumber>();
319
320 foreach (var row in this.Rows)
321 {
322 var primaryKey = row.GetPrimaryKey();
323
324 if (primaryKeys.TryGetValue(primaryKey, out var collisionSourceLineNumber))
325 {
326 throw new WixException(WixDataErrors.DuplicatePrimaryKey(collisionSourceLineNumber, primaryKey, this.Definition.Name));
327 }
328
329 primaryKeys.Add(primaryKey, row.SourceLineNumbers);
330 }
331 }
332 }
333}