diff options
Diffstat (limited to 'src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs')
-rw-r--r-- | src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs new file mode 100644 index 00000000..3009e59d --- /dev/null +++ b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs | |||
@@ -0,0 +1,374 @@ | |||
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 | |||
3 | namespace WixToolset.Data.Rows | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Diagnostics; | ||
8 | using System.Globalization; | ||
9 | using System.Xml; | ||
10 | using System.Xml.Schema; | ||
11 | |||
12 | /// <summary> | ||
13 | /// The Sequence tables that actions may belong to. | ||
14 | /// </summary> | ||
15 | public enum SequenceTable | ||
16 | { | ||
17 | /// <summary>AdminUISequence</summary> | ||
18 | AdminUISequence, | ||
19 | |||
20 | /// <summary>AdminExecuteSequence</summary> | ||
21 | AdminExecuteSequence, | ||
22 | |||
23 | /// <summary>AdvtExecuteSequence</summary> | ||
24 | AdvtExecuteSequence, | ||
25 | |||
26 | /// <summary>InstallUISequence</summary> | ||
27 | InstallUISequence, | ||
28 | |||
29 | /// <summary>InstallExecuteSequence</summary> | ||
30 | InstallExecuteSequence | ||
31 | } | ||
32 | |||
33 | /// <summary> | ||
34 | /// Specialization of a row for the sequence tables. | ||
35 | /// </summary> | ||
36 | public sealed class WixActionRow : Row, IComparable | ||
37 | { | ||
38 | private WixActionRowCollection previousActionRows; | ||
39 | private WixActionRowCollection nextActionRows; | ||
40 | |||
41 | /// <summary> | ||
42 | /// Instantiates an ActionRow that belongs to a table. | ||
43 | /// </summary> | ||
44 | /// <param name="sourceLineNumbers">Original source lines for this row.</param> | ||
45 | /// <param name="table">Table this Action row belongs to and should get its column definitions from.</param> | ||
46 | public WixActionRow(SourceLineNumber sourceLineNumbers, Table table) : | ||
47 | base(sourceLineNumbers, table) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | /// <summary> | ||
52 | /// Instantiates a standard ActionRow. | ||
53 | /// </summary> | ||
54 | /// <param name="sequenceTable">The sequence table of the standard action.</param> | ||
55 | /// <param name="action">The name of the standard action.</param> | ||
56 | /// <param name="condition">The condition of the standard action.</param> | ||
57 | /// <param name="sequence">The suggested sequence number of the standard action.</param> | ||
58 | private WixActionRow(SequenceTable sequenceTable, string action, string condition, int sequence) : | ||
59 | base(null, WindowsInstallerStandard.GetTableDefinitions()["WixAction"]) | ||
60 | { | ||
61 | this.SequenceTable = sequenceTable; | ||
62 | this.Action = action; | ||
63 | this.Condition = condition; | ||
64 | this.Sequence = sequence; | ||
65 | this.Overridable = true; // all standard actions are overridable by default | ||
66 | } | ||
67 | |||
68 | /// <summary> | ||
69 | /// Instantiates an ActionRow by copying data from another ActionRow. | ||
70 | /// </summary> | ||
71 | /// <param name="source">The row the data is copied from.</param> | ||
72 | /// <remarks>The previous and next action collections are not copied.</remarks> | ||
73 | private WixActionRow(WixActionRow source) | ||
74 | : base(source) | ||
75 | { | ||
76 | } | ||
77 | |||
78 | /// <summary> | ||
79 | /// Gets or sets the name of the action. | ||
80 | /// </summary> | ||
81 | /// <value>The name of the action.</value> | ||
82 | public string Action | ||
83 | { | ||
84 | get { return (string)this.Fields[1].Data; } | ||
85 | set { this.Fields[1].Data = value; } | ||
86 | } | ||
87 | |||
88 | /// <summary> | ||
89 | /// Gets the name of the action this action should be scheduled after. | ||
90 | /// </summary> | ||
91 | /// <value>The name of the action this action should be scheduled after.</value> | ||
92 | public string After | ||
93 | { | ||
94 | get { return (string)this.Fields[5].Data; } | ||
95 | set { this.Fields[5].Data = value; } | ||
96 | } | ||
97 | |||
98 | /// <summary> | ||
99 | /// Gets the name of the action this action should be scheduled before. | ||
100 | /// </summary> | ||
101 | /// <value>The name of the action this action should be scheduled before.</value> | ||
102 | public string Before | ||
103 | { | ||
104 | get { return (string)this.Fields[4].Data; } | ||
105 | set { this.Fields[4].Data = value; } | ||
106 | } | ||
107 | |||
108 | /// <summary> | ||
109 | /// Gets or sets the condition of the action. | ||
110 | /// </summary> | ||
111 | /// <value>The condition of the action.</value> | ||
112 | public string Condition | ||
113 | { | ||
114 | get { return (string)this.Fields[2].Data; } | ||
115 | set { this.Fields[2].Data = value; } | ||
116 | } | ||
117 | |||
118 | /// <summary> | ||
119 | /// Gets or sets whether this action is overridable. | ||
120 | /// </summary> | ||
121 | /// <value>Whether this action is overridable.</value> | ||
122 | public bool Overridable | ||
123 | { | ||
124 | get { return (1 == Convert.ToInt32(this.Fields[6].Data, CultureInfo.InvariantCulture)); } | ||
125 | set { this.Fields[6].Data = (value ? 1 : 0); } | ||
126 | } | ||
127 | |||
128 | /// <summary> | ||
129 | /// Gets or sets the sequence number of this action. | ||
130 | /// </summary> | ||
131 | /// <value>The sequence number of this action.</value> | ||
132 | public int Sequence | ||
133 | { | ||
134 | get { return Convert.ToInt32(this.Fields[3].Data, CultureInfo.InvariantCulture); } | ||
135 | set { this.Fields[3].Data = value; } | ||
136 | } | ||
137 | |||
138 | /// <summary> | ||
139 | /// Gets of sets the sequence table of this action. | ||
140 | /// </summary> | ||
141 | /// <value>The sequence table of this action.</value> | ||
142 | public SequenceTable SequenceTable | ||
143 | { | ||
144 | get { return (SequenceTable)Enum.Parse(typeof(SequenceTable), (string)this.Fields[0].Data); } | ||
145 | set { this.Fields[0].Data = value.ToString(); } | ||
146 | } | ||
147 | |||
148 | /// <summary> | ||
149 | /// Gets the actions that should be scheduled after this action. | ||
150 | /// </summary> | ||
151 | /// <value>The actions that should be scheduled after this action.</value> | ||
152 | public WixActionRowCollection NextActionRows | ||
153 | { | ||
154 | get | ||
155 | { | ||
156 | if (null == this.nextActionRows) | ||
157 | { | ||
158 | this.nextActionRows = new WixActionRowCollection(); | ||
159 | } | ||
160 | |||
161 | return this.nextActionRows; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | /// <summary> | ||
166 | /// Gets the actions that should be scheduled before this action. | ||
167 | /// </summary> | ||
168 | /// <value>The actions that should be scheduled before this action.</value> | ||
169 | public WixActionRowCollection PreviousActionRows | ||
170 | { | ||
171 | get | ||
172 | { | ||
173 | if (null == this.previousActionRows) | ||
174 | { | ||
175 | this.previousActionRows = new WixActionRowCollection(); | ||
176 | } | ||
177 | |||
178 | return this.previousActionRows; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | /// <summary> | ||
183 | /// Creates a clone of the action row. | ||
184 | /// </summary> | ||
185 | /// <returns>A shallow copy of the source object.</returns> | ||
186 | /// <remarks>The previous and next action collections are not copied.</remarks> | ||
187 | public WixActionRow Clone() | ||
188 | { | ||
189 | return new WixActionRow(this); | ||
190 | } | ||
191 | |||
192 | /// <summary> | ||
193 | /// Compares the current instance with another object of the same type. | ||
194 | /// </summary> | ||
195 | /// <param name="obj">Other reference to compare this one to.</param> | ||
196 | /// <returns>Returns less than 0 for less than, 0 for equals, and greater than 0 for greater.</returns> | ||
197 | public int CompareTo(object obj) | ||
198 | { | ||
199 | WixActionRow otherActionRow = (WixActionRow)obj; | ||
200 | |||
201 | return this.Sequence.CompareTo(otherActionRow.Sequence); | ||
202 | } | ||
203 | |||
204 | /// <summary> | ||
205 | /// Parses ActionRows from the Xml reader. | ||
206 | /// </summary> | ||
207 | /// <param name="reader">Xml reader that contains serialized ActionRows.</param> | ||
208 | /// <returns>The parsed ActionRows.</returns> | ||
209 | internal static WixActionRow[] Parse(XmlReader reader) | ||
210 | { | ||
211 | Debug.Assert("action" == reader.LocalName); | ||
212 | |||
213 | string id = null; | ||
214 | string condition = null; | ||
215 | bool empty = reader.IsEmptyElement; | ||
216 | int sequence = int.MinValue; | ||
217 | int sequenceCount = 0; | ||
218 | SequenceTable[] sequenceTables = new SequenceTable[Enum.GetValues(typeof(SequenceTable)).Length]; | ||
219 | |||
220 | while (reader.MoveToNextAttribute()) | ||
221 | { | ||
222 | switch (reader.Name) | ||
223 | { | ||
224 | case "name": | ||
225 | id = reader.Value; | ||
226 | break; | ||
227 | case "AdminExecuteSequence": | ||
228 | if (reader.Value.Equals("yes")) | ||
229 | { | ||
230 | sequenceTables[sequenceCount] = SequenceTable.AdminExecuteSequence; | ||
231 | ++sequenceCount; | ||
232 | } | ||
233 | break; | ||
234 | case "AdminUISequence": | ||
235 | if (reader.Value.Equals("yes")) | ||
236 | { | ||
237 | sequenceTables[sequenceCount] = SequenceTable.AdminUISequence; | ||
238 | ++sequenceCount; | ||
239 | } | ||
240 | break; | ||
241 | case "AdvtExecuteSequence": | ||
242 | if (reader.Value.Equals("yes")) | ||
243 | { | ||
244 | sequenceTables[sequenceCount] = SequenceTable.AdvtExecuteSequence; | ||
245 | ++sequenceCount; | ||
246 | } | ||
247 | break; | ||
248 | case "condition": | ||
249 | condition = reader.Value; | ||
250 | break; | ||
251 | case "InstallExecuteSequence": | ||
252 | if (reader.Value.Equals("yes")) | ||
253 | { | ||
254 | sequenceTables[sequenceCount] = SequenceTable.InstallExecuteSequence; | ||
255 | ++sequenceCount; | ||
256 | } | ||
257 | break; | ||
258 | case "InstallUISequence": | ||
259 | if (reader.Value.Equals("yes")) | ||
260 | { | ||
261 | sequenceTables[sequenceCount] = SequenceTable.InstallUISequence; | ||
262 | ++sequenceCount; | ||
263 | } | ||
264 | break; | ||
265 | case "sequence": | ||
266 | sequence = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); | ||
267 | break; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | if (null == id) | ||
272 | { | ||
273 | throw new XmlException(); | ||
274 | } | ||
275 | |||
276 | if (int.MinValue == sequence) | ||
277 | { | ||
278 | throw new XmlException(); | ||
279 | } | ||
280 | else if (1 > sequence) | ||
281 | { | ||
282 | throw new XmlException(); | ||
283 | } | ||
284 | |||
285 | if (0 == sequenceCount) | ||
286 | { | ||
287 | throw new XmlException(); | ||
288 | } | ||
289 | |||
290 | if (!empty && reader.Read() && XmlNodeType.EndElement != reader.MoveToContent()) | ||
291 | { | ||
292 | throw new XmlException(); | ||
293 | } | ||
294 | |||
295 | // create the actions | ||
296 | WixActionRow[] actionRows = new WixActionRow[sequenceCount]; | ||
297 | for (int i = 0; i < sequenceCount; i++) | ||
298 | { | ||
299 | WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence); | ||
300 | actionRows[i] = actionRow; | ||
301 | } | ||
302 | |||
303 | return actionRows; | ||
304 | } | ||
305 | |||
306 | /// <summary> | ||
307 | /// Determines whether this ActionRow contains the specified ActionRow as a child in its dependency tree. | ||
308 | /// </summary> | ||
309 | /// <param name="actionRow">The possible child ActionRow.</param> | ||
310 | /// <returns>true if the ActionRow is a child of this ActionRow; false otherwise.</returns> | ||
311 | public bool ContainsChildActionRow(WixActionRow actionRow) | ||
312 | { | ||
313 | if (null != this.previousActionRows) | ||
314 | { | ||
315 | if (this.previousActionRows.Contains(actionRow.SequenceTable, actionRow.Action)) | ||
316 | { | ||
317 | return true; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | if (null != this.nextActionRows) | ||
322 | { | ||
323 | if (this.nextActionRows.Contains(actionRow.SequenceTable, actionRow.Action)) | ||
324 | { | ||
325 | return true; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | return false; | ||
330 | } | ||
331 | |||
332 | /// <summary> | ||
333 | /// Get all the actions scheduled before this one in a particular sequence table. | ||
334 | /// </summary> | ||
335 | /// <param name="sequenceTable">The sequence table.</param> | ||
336 | /// <param name="allPreviousActionRows">A RowCollection which will contain all the previous actions.</param> | ||
337 | public void GetAllPreviousActionRows(SequenceTable sequenceTable, IList<WixActionRow> allPreviousActionRows) | ||
338 | { | ||
339 | if (null != this.previousActionRows) | ||
340 | { | ||
341 | foreach (WixActionRow actionRow in this.previousActionRows) | ||
342 | { | ||
343 | if (sequenceTable == actionRow.SequenceTable) | ||
344 | { | ||
345 | actionRow.GetAllPreviousActionRows(sequenceTable, allPreviousActionRows); | ||
346 | allPreviousActionRows.Add(actionRow); | ||
347 | actionRow.GetAllNextActionRows(sequenceTable, allPreviousActionRows); | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | |||
353 | /// <summary> | ||
354 | /// Get all the actions scheduled after this one in a particular sequence table. | ||
355 | /// </summary> | ||
356 | /// <param name="sequenceTable">The sequence table.</param> | ||
357 | /// <param name="allNextActionRows">A RowCollection which will contain all the next actions.</param> | ||
358 | public void GetAllNextActionRows(SequenceTable sequenceTable, IList<WixActionRow> allNextActionRows) | ||
359 | { | ||
360 | if (null != this.nextActionRows) | ||
361 | { | ||
362 | foreach (WixActionRow actionRow in this.nextActionRows) | ||
363 | { | ||
364 | if (sequenceTable == actionRow.SequenceTable) | ||
365 | { | ||
366 | actionRow.GetAllPreviousActionRows(sequenceTable, allNextActionRows); | ||
367 | allNextActionRows.Add(actionRow); | ||
368 | actionRow.GetAllNextActionRows(sequenceTable, allNextActionRows); | ||
369 | } | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | } | ||