// 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. namespace WixToolset.Core.WindowsInstaller.Rows { using System; using System.Collections; using System.Diagnostics; using System.Globalization; using System.Xml; using WixToolset.Data.Tuples; using WixToolset.Data.WindowsInstaller.Rows; /// /// A collection of action rows sorted by their sequence table and action name. /// // TODO: Remove this internal sealed class WixActionRowCollection : ICollection { private SortedList collection; /// /// Creates a new action table object. /// public WixActionRowCollection() { this.collection = new SortedList(); } /// /// Gets the number of items in the collection. /// /// Number of items in collection. public int Count { get { return this.collection.Count; } } /// /// Gets if the collection has been synchronized. /// /// True if the collection has been synchronized. public bool IsSynchronized { get { return this.collection.IsSynchronized; } } /// /// Gets the object used to synchronize the collection. /// /// Oject used the synchronize the collection. public object SyncRoot { get { return this; } } /// /// Get an ActionRow by its sequence table and action name. /// /// The sequence table of the ActionRow. /// The action name of the ActionRow. public WixActionRow this[SequenceTable sequenceTable, string action] { get { return (WixActionRow)this.collection[GetKey(sequenceTable, action)]; } } /// /// Add an ActionRow to the collection. /// /// The ActionRow to add. /// true to overwrite an existing ActionRow; false otherwise. public void Add(WixActionRow actionRow, bool overwrite) { string key = GetKey(actionRow.SequenceTable, actionRow.Action); if (overwrite) { this.collection[key] = actionRow; } else { this.collection.Add(key, actionRow); } } /// /// Add an ActionRow to the collection. /// /// The ActionRow to add. public void Add(WixActionRow actionRow) { this.Add(actionRow, false); } /// /// Determines if the collection contains an ActionRow with a specific sequence table and name. /// /// The sequence table of the ActionRow. /// The action name of the ActionRow. /// true if the ActionRow was found; false otherwise. public bool Contains(SequenceTable sequenceTable, string action) { return this.collection.Contains(GetKey(sequenceTable, action)); } /// /// Copies the collection into an array. /// /// Array to copy the collection into. /// Index to start copying from. public void CopyTo(System.Array array, int index) { this.collection.Values.CopyTo(array, index); } /// /// Gets the enumerator for the collection. /// /// The enumerator for the collection. public IEnumerator GetEnumerator() { return this.collection.Values.GetEnumerator(); } /// /// Remove an ActionRow from the collection. /// /// The sequence table of the ActionRow. /// The action name of the ActionRow. public void Remove(SequenceTable sequenceTable, string action) { this.collection.Remove(GetKey(sequenceTable, action)); } /// /// Load an action table from an XmlReader. /// /// Reader to get data from. /// The ActionRowCollection represented by the xml. internal static WixActionRowCollection Load(XmlReader reader) { reader.MoveToContent(); return Parse(reader); } /// /// Creates a new action table object and populates it from an Xml reader. /// /// Reader to get data from. /// The parsed ActionTable. private static WixActionRowCollection Parse(XmlReader reader) { if (!reader.LocalName.Equals("actions")) { throw new XmlException(); } WixActionRowCollection actionRows = new WixActionRowCollection(); bool empty = reader.IsEmptyElement; while (reader.MoveToNextAttribute()) { } if (!empty) { bool done = false; // loop through all the fields in a row while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "action": WixActionRow[] parsedActionRows = ParseActions(reader); foreach (WixActionRow actionRow in parsedActionRows) { actionRows.Add(actionRow); } break; default: throw new XmlException(); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new XmlException(); } } return actionRows; } /// /// Get the key for storing an ActionRow. /// /// The sequence table of the ActionRow. /// The action name of the ActionRow. /// The string key. private static string GetKey(SequenceTable sequenceTable, string action) { return GetKey(sequenceTable.ToString(), action); } /// /// Get the key for storing an ActionRow. /// /// The sequence table of the ActionRow. /// The action name of the ActionRow. /// The string key. private static string GetKey(string sequenceTable, string action) { return String.Concat(sequenceTable, '/', action); } /// /// Parses ActionRows from the Xml reader. /// /// Xml reader that contains serialized ActionRows. /// The parsed ActionRows. internal static WixActionRow[] ParseActions(XmlReader reader) { Debug.Assert("action" == reader.LocalName); string id = null; string condition = null; bool empty = reader.IsEmptyElement; int sequence = int.MinValue; int sequenceCount = 0; SequenceTable[] sequenceTables = new SequenceTable[Enum.GetValues(typeof(SequenceTable)).Length]; while (reader.MoveToNextAttribute()) { switch (reader.Name) { case "name": id = reader.Value; break; case "AdminExecuteSequence": if (reader.Value.Equals("yes")) { sequenceTables[sequenceCount] = SequenceTable.AdminExecuteSequence; ++sequenceCount; } break; case "AdminUISequence": if (reader.Value.Equals("yes")) { sequenceTables[sequenceCount] = SequenceTable.AdminUISequence; ++sequenceCount; } break; case "AdvtExecuteSequence": if (reader.Value.Equals("yes")) { sequenceTables[sequenceCount] = SequenceTable.AdvtExecuteSequence; ++sequenceCount; } break; case "condition": condition = reader.Value; break; case "InstallExecuteSequence": if (reader.Value.Equals("yes")) { sequenceTables[sequenceCount] = SequenceTable.InstallExecuteSequence; ++sequenceCount; } break; case "InstallUISequence": if (reader.Value.Equals("yes")) { sequenceTables[sequenceCount] = SequenceTable.InstallUISequence; ++sequenceCount; } break; case "sequence": sequence = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); break; } } if (null == id) { throw new XmlException(); } if (int.MinValue == sequence) { throw new XmlException(); } else if (1 > sequence) { throw new XmlException(); } if (0 == sequenceCount) { throw new XmlException(); } if (!empty && reader.Read() && XmlNodeType.EndElement != reader.MoveToContent()) { throw new XmlException(); } // create the actions WixActionRow[] actionRows = new WixActionRow[sequenceCount]; for (int i = 0; i < sequenceCount; i++) { //WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence); //actionRows[i] = actionRow; throw new NotImplementedException(); } return actionRows; } } }