#region License Information /* HeuristicLab * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Xml; using HeuristicLab.Core; namespace HeuristicLab.Data { /// /// A class representing a list of elements /// (which are implementing the interface ) having some constraints. /// public class ConstrainedItemList : ConstrainedItemBase, IEnumerable, IEnumerable { private List list; private bool suspendConstraintCheck; /// /// Checks whether the test for the constraints is suspended. /// public bool ConstraintCheckSuspended { get { return suspendConstraintCheck; } } /// /// Initializes a new instance of with the constraint check enabled. /// public ConstrainedItemList() : base() { list = new List(); suspendConstraintCheck = false; } /// /// Creates a new instance of . /// /// The created instance as . public override IView CreateView() { return new ConstrainedItemListView(this); } #region Clone & Persistence /// /// Clones the current instance. /// /// The elements of the current instance are cloned with the /// method of the class . /// A dictionary of all already cloned objects. /// The cloned instance as . public override object Clone(IDictionary clonedObjects) { ConstrainedItemList clone = new ConstrainedItemList(); clonedObjects.Add(Guid, clone); foreach (IConstraint constraint in Constraints) clone.AddConstraint((IConstraint)Auxiliary.Clone(constraint, clonedObjects)); clone.suspendConstraintCheck = suspendConstraintCheck; foreach (IItem item in list) { clone.list.Add((IItem)Auxiliary.Clone(item, clonedObjects)); } return clone; } /// /// Saves the current instance as in the specified . /// /// The basic instance is saved through the call of /// of base class /// .
/// The list itself is saved as child node having the tag name ListItems /// and each element is saved as a child node of the ListItems node. /// The suspendConstraintCheck attribute is saved as an attribute of the list node /// having the tag name SuspendConstraintCheck.
/// The (tag)name of the . /// The where the data is saved. /// A dictionary of all already persisted objects. (Needed to avoid cycles.) /// The saved . public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary persistedObjects) { XmlNode node = base.GetXmlNode(name, document, persistedObjects); XmlNode listNode = document.CreateNode(XmlNodeType.Element, "ListItems", null); for (int i = 0; i < list.Count; i++) listNode.AppendChild(PersistenceManager.Persist(list[i], document, persistedObjects)); XmlAttribute sccAttrib = document.CreateAttribute("SuspendConstraintCheck"); sccAttrib.Value = suspendConstraintCheck.ToString(); listNode.Attributes.Append(sccAttrib); node.AppendChild(listNode); return node; } /// /// Loads the persisted int value from the specified . /// /// The elements of the list must be saved as child nodes of /// the node with the tag name ListItems, which itself is a child node of the current instance.
/// The suspendConstraintCheck must be saved as attribute of the list node /// with the tag name SuspendConstraintCheck (see ).
/// The where the int is saved. /// A dictionary of all already restored objects. (Needed to avoid cycles.) public override void Populate(XmlNode node, IDictionary restoredObjects) { base.Populate(node, restoredObjects); XmlNode listNode = node.SelectSingleNode("ListItems"); list = new List(); for (int i = 0; i < listNode.ChildNodes.Count; i++) list.Add((IItem)PersistenceManager.Restore(listNode.ChildNodes[i], restoredObjects)); suspendConstraintCheck = bool.Parse(listNode.Attributes["SuspendConstraintCheck"].Value); } #endregion /// /// The string representation of the current list instance. /// /// The current list as string, each element separated by a semicolon. /// "Empty List" if the list has no elements. public override string ToString() { if (list.Count > 0) { StringBuilder builder = new StringBuilder(); builder.Append(list[0].ToString()); for (int i = 1; i < list.Count; i++) { builder.Append(";"); builder.Append(list[i].ToString()); } return builder.ToString(); } else { return "Empty List"; } } /// public int IndexOf(IItem item) { return list.IndexOf(item); } /// /// Sets suspendConstraintCheck to true. /// public void BeginCombinedOperation() { suspendConstraintCheck = true; } /// /// Checks whether the current instance fulfills all constraints. /// /// Output parameter, /// contains all constraints that could not be fulfilled. /// true if all constraints could be fulfilled, false otherwise. public bool EndCombinedOperation(out ICollection violatedConstraints) { if (IsValid(out violatedConstraints)) suspendConstraintCheck = false; else suspendConstraintCheck = true; return !suspendConstraintCheck; } /// /// Adds a new at a specified to the current instance if all constraints are fulfilled. /// /// Calls if the insertion was successful. /// The position where to insert the new element. /// The new element to insert. /// Output parameter, all constraints that could not be fulfilled. /// true if the insertion was successful, false otherwise. public bool TryInsert(int index, IItem item, out ICollection violatedConstraints) { list.Insert(index, item); violatedConstraints = new List(); if (suspendConstraintCheck || IsValid(out violatedConstraints)) { OnItemAdded(item, index); return true; } else { list.RemoveAt(index); return false; } } /// /// Removes an element at the specified /// from the current instance if all constraints are fulfilled. /// /// Calls if the deletion was successful. /// The position where to remove the element. /// Output parameter, all constraints that could not be fulfilled. /// true if the element could be removed successfully, false otherwise. public bool TryRemoveAt(int index, out ICollection violatedConstraints) { IItem item = list[index]; list.RemoveAt(index); violatedConstraints = new List(); if (suspendConstraintCheck || IsValid(out violatedConstraints)) { OnItemRemoved(item, index); return true; } else { list.Insert(index, item); return false; } } /// /// Gets the element of the current instance at the specified . /// /// The position of the searched element. /// The searched element as . public IItem this[int index] { get { return list[index]; } } /// /// Changes the element at a specified position if all constraints are fulfilled. /// /// The position where to change the element. /// The element that replaces the current one. /// Output parameter, all constraints that could not be fulfilled. /// true if the substitution was successful, false otherwise. public bool TrySetAt(int index, IItem item, out ICollection violatedConstraints) { IItem backup = this[index]; list[index] = item; violatedConstraints = new List(); if (suspendConstraintCheck || IsValid(out violatedConstraints)) { return true; } else { list[index] = backup; return false; } } /// /// Adds a new to the current list if all constraints are fulfilled. /// /// Calls if the add was successful. /// The element to add. /// Output parameter, all constraints that could not be fulfilled. /// true if the element could be successfully added, false otherwise. public bool TryAdd(IItem item, out ICollection violatedConstraints) { list.Add(item); violatedConstraints = new List(); if (suspendConstraintCheck || IsValid(out violatedConstraints)) { OnItemAdded(item, list.Count - 1); return true; } else { list.RemoveAt(list.Count - 1); return false; } } /// /// Empties the current list. /// /// Calls . public void Clear() { list.Clear(); OnCleared(); } /// public bool Contains(IItem item) { return list.Contains(item); } /// public void CopyTo(IItem[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } /// public int Count { get { return list.Count; } } /// /// Checks whether the current instance is read-only. /// /// Always returns false. public bool IsReadOnly { get { return false; } } /// /// Removes a specified from the /// current instance if all constraints are fulfilled. /// /// The element to remove. /// Output parameter, all constraints that could not be fulfilled. /// true if the deletion was successful, false otherwise. public bool TryRemove(IItem item, out ICollection violatedConstraints) { int index = list.IndexOf(item); if (index >= 0) { return TryRemoveAt(index, out violatedConstraints); } else { violatedConstraints = new List(); return false; } } /// public IEnumerator GetEnumerator() { return list.GetEnumerator(); } /// IEnumerator IEnumerable.GetEnumerator() { return list.GetEnumerator(); } /// /// Occurs when a new item is added. /// public event EventHandler ItemAdded; /// /// Fires a new ItemAdded event. /// /// Calls . /// The element that was added. /// The position where the element was added. protected virtual void OnItemAdded(IItem item, int index) { if (ItemAdded != null) ItemAdded(this, new ItemIndexEventArgs(item, index)); OnChanged(); } /// /// Occurs when an element is removed from the current instance. /// public event EventHandler ItemRemoved; /// /// Fires a new ItemRemoved event. /// /// Calls . /// The element that has been removed. /// The position from where it has been removed. protected virtual void OnItemRemoved(IItem item, int index) { if (ItemRemoved != null) ItemRemoved(this, new ItemIndexEventArgs(item, index)); OnChanged(); } /// /// Occurs when the current list is emptied. /// public event EventHandler Cleared; /// /// Fires a new Cleared event. /// /// Calls . protected virtual void OnCleared() { if (Cleared != null) Cleared(this, new EventArgs()); OnChanged(); } } }