#region License Information
/* HeuristicLab
* Copyright (C) 2002-2016 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.Drawing;
using System.Linq;
using System.Text;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data.PersistentDataStructures.Adaptations;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.Data {
[Item("ValueTypeArray", "An abstract base class for representing arrays of value types.")]
[StorableClass]
public abstract class ValueTypeArray : Item, IValueTypeArray where T : struct {
private const int maximumToStringLength = 100;
public static new Image StaticItemImage {
get { return HeuristicLab.Common.Resources.VSImageLibrary.Class; }
}
[Storable(AllowOneWay = true, Name = "array")]
protected T[] oldArrayValuePersistence { set { historyArray = new HistoryArray(value); } }
[Storable(AllowOneWay = true, Name = "elementNames")]
protected List oldElementNamesValuePersistence { set { historyElementNames = new HistoryList(value); } }
[Storable]
protected HistoryArray historyArray;
[Storable]
protected HistoryList historyElementNames;
public virtual IEnumerable ElementNames {
get { return this.historyElementNames; }
set {
if (ReadOnly) throw new NotSupportedException("ElementNames cannot be set. ValueTypeArray is read-only.");
if (value == null || !value.Any())
historyElementNames = new HistoryList();
else if (value.Count() > Length)
throw new ArgumentException("The number of element names must not exceed the array length.");
else
historyElementNames = new HistoryList(value);
OnElementNamesChanged();
}
}
public virtual int Length {
get { return historyArray.Length; }
#region Mono Compatibility
// this setter should be protected, but the Mono compiler couldn't handle it
set {
if (ReadOnly) throw new NotSupportedException("Length cannot be set. ValueTypeArray is read-only.");
if (value != Length) {
historyArray.Resize(value);
while (historyElementNames.Count > value)
historyElementNames.RemoveAt(historyElementNames.Count - 1);
OnElementNamesChanged();
OnReset();
}
}
#endregion
}
[Storable]
protected bool resizable = true;
public bool Resizable {
get { return resizable; }
set {
if (resizable != value) {
resizable = value;
OnResizableChanged();
}
}
}
public virtual T this[int index] {
get { return historyArray[index]; }
set {
if (ReadOnly) throw new NotSupportedException("Item cannot be set. ValueTypeArray is read-only.");
if (!value.Equals(historyArray[index])) {
historyArray[index] = value;
OnItemChanged(index);
}
}
}
[Storable]
protected bool readOnly;
public virtual bool ReadOnly {
get { return readOnly; }
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
if (historyElementNames == null) { historyElementNames = new HistoryList(); }
}
[StorableConstructor]
protected ValueTypeArray(bool deserializing) : base(deserializing) { }
protected ValueTypeArray(ValueTypeArray original, Cloner cloner)
: base(original, cloner) {
this.historyArray = (HistoryArray)original.historyArray.Clone();
this.readOnly = original.readOnly;
this.resizable = original.resizable;
this.historyElementNames = (HistoryList)original.historyElementNames.Clone();
}
protected ValueTypeArray() {
historyArray = new HistoryArray(0);
readOnly = false;
resizable = true;
historyElementNames = new HistoryList();
}
protected ValueTypeArray(int length) {
historyArray = new HistoryArray(length);
readOnly = false;
resizable = true;
historyElementNames = new HistoryList();
}
protected ValueTypeArray(T[] elements) {
if (elements == null) throw new ArgumentNullException();
historyArray = new HistoryArray(elements);
readOnly = false;
resizable = true;
historyElementNames = new HistoryList();
}
private ValueTypeArray(HistoryArray values, HistoryList historyElementNames) {
this.historyArray = values;
this.historyElementNames = historyElementNames;
}
public virtual IValueTypeArray AsReadOnly() {
ValueTypeArray readOnlyValueTypeArray = (ValueTypeArray)this.Clone();
readOnlyValueTypeArray.readOnly = true;
return readOnlyValueTypeArray;
}
public T[] CloneAsArray() {
return historyArray.ToArray();
}
public override string ToString() {
if (historyArray.Length == 0) return "[]";
StringBuilder sb = new StringBuilder();
sb.Append("[");
sb.Append(historyArray[0].ToString());
for (int i = 1; i < historyArray.Length; i++) {
sb.Append(";").Append(historyArray[i].ToString());
if (sb.Length > maximumToStringLength) {
sb.Append("...");
break;
}
}
sb.Append("]");
return sb.ToString();
}
public virtual IEnumerator GetEnumerator() {
return historyArray.Cast().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public event EventHandler ResizableChanged;
protected virtual void OnResizableChanged() {
EventHandler handler = ResizableChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
public event EventHandler ElementNamesChanged;
protected virtual void OnElementNamesChanged() {
EventHandler handler = ElementNamesChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
public event EventHandler> ItemChanged;
protected virtual void OnItemChanged(int index) {
if (ItemChanged != null)
ItemChanged(this, new EventArgs(index));
if (index < maximumToStringLength)
OnToStringChanged();
}
public event EventHandler Reset;
protected virtual void OnReset() {
if (Reset != null)
Reset(this, EventArgs.Empty);
OnToStringChanged();
}
public void CreateSnapshot() {
historyArray.CreateSnapshot();
historyElementNames.CreateSnapshot();
}
public IEnumerable> GetHistory() {
foreach (var vta in historyArray.GetHistory().Zip(historyElementNames.GetHistory(), (v, n) => new {v, n})) {
var clone = (ValueTypeArray)Clone();
clone.historyArray = vta.v;
clone.historyElementNames = vta.n;
yield return clone;
}
}
}
}