// 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;
}
}
}