#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.Generic;
using System.Text;
using System.Xml;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Common;
namespace HeuristicLab.Core {
///
/// Hierarchical container of variables (and of subscopes).
///
public class Scope : ItemBase, IScope {
[Storable]
private IScope parent;
[Storable]
private string myName;
///
/// Gets the name of the current scope.
///
public string Name {
get { return myName; }
}
private IDictionary myVariables;
///
public ICollection Variables {
get { return myVariables.Values; }
}
[Storable(Name="Variables")]
private List VariablePersistence {
get { return new List(myVariables.Values); }
set {
myVariables.Clear();
foreach (IVariable var in value) {
AddVariable(var);
}
}
}
[Storable]
private IDictionary myAliases;
///
public IEnumerable> Aliases {
get { return myAliases; }
}
[Storable]
private List mySubScopes;
///
/// Gets all subscopes of the current instance.
/// The subscopes are returned as read-only.
///
public IList SubScopes {
get { return mySubScopes.AsReadOnly(); }
}
///
/// Initializes a new instance of having "Anonymous" as default name.
///
public Scope() {
myName = "Anonymous";
myVariables = new Dictionary();
myAliases = new Dictionary();
mySubScopes = new List();
}
///
/// Initializes a new instance of with the given .
///
/// The name of the scope.
public Scope(string name)
: this() {
if (name != null) myName = name;
}
///
public void SetParent(IScope scope) {
parent = scope;
}
///
/// Creates a new instance of to represent the current instance visually.
///
/// The created view as .
public override IView CreateView() {
return new ScopeView(this);
}
///
public IVariable GetVariable(string name) {
IVariable variable;
if (myVariables.TryGetValue(name, out variable))
return variable;
else
return null;
}
///
public void AddVariable(IVariable variable) {
myVariables.Add(variable.Name, variable);
variable.NameChanging += new EventHandler>(Variable_NameChanging);
variable.NameChanged += new EventHandler(Variable_NameChanged);
OnVariableAdded(variable);
}
///
public void RemoveVariable(string name) {
IVariable variable;
if (myVariables.TryGetValue(name, out variable)) {
variable.NameChanging -= new EventHandler>(Variable_NameChanging);
variable.NameChanged -= new EventHandler(Variable_NameChanged);
myVariables.Remove(name);
OnVariableRemoved(variable);
}
}
private void Variable_NameChanging(object sender, CancelEventArgs e) {
e.Cancel = myVariables.ContainsKey(e.Value);
}
private void Variable_NameChanged(object sender, EventArgs e) {
IVariable variable = (IVariable)sender;
string oldName = null;
foreach (KeyValuePair element in myVariables) {
if (element.Value == variable)
oldName = element.Key;
}
myVariables.Remove(oldName);
myVariables.Add(variable.Name, variable);
}
///
public T GetVariableValue(string name, bool recursiveLookup) where T : class, IItem {
return GetVariableValue(name, recursiveLookup, true);
}
///
public T GetVariableValue(string name, bool recursiveLookup, bool throwOnError) where T : class, IItem {
return (T)GetVariableValue(name, recursiveLookup, throwOnError);
}
///
public IItem GetVariableValue(string name, bool recursiveLookup) {
return GetVariableValue(name, recursiveLookup, true);
}
///
public IItem GetVariableValue(string name, bool recursiveLookup, bool throwOnError) {
IVariable variable;
name = TranslateName(name);
if (myVariables.TryGetValue(name, out variable)) {
return variable.Value;
} else {
if (recursiveLookup && (parent != null))
return parent.GetVariableValue(name, recursiveLookup, throwOnError);
else {
if (throwOnError)
throw new ArgumentException("Variable " + name + " not found");
else
return null;
}
}
}
///
public string TranslateName(string name) {
while (myAliases.ContainsKey(name))
name = myAliases[name];
if (parent != null)
name = parent.TranslateName(name);
return name;
}
///
public void AddAlias(string alias, string name) {
RemoveAlias(alias);
if (alias != name) {
myAliases.Add(alias, name);
OnAliasAdded(alias);
}
}
///
public void RemoveAlias(string alias) {
if (myAliases.ContainsKey(alias)) {
myAliases.Remove(alias);
OnAliasRemoved(alias);
}
}
///
public void AddSubScope(IScope scope) {
scope.SetParent(this);
mySubScopes.Add(scope);
OnSubScopeAdded(scope, mySubScopes.Count - 1);
}
///
public void RemoveSubScope(IScope scope) {
int index = mySubScopes.IndexOf(scope);
if (mySubScopes.Remove(scope)) {
scope.SetParent(null);
OnSubScopeRemoved(scope, index);
}
}
///
public void ReorderSubScopes(int[] sequence) {
IScope[] scopes = mySubScopes.ToArray();
mySubScopes.Clear();
for (int i = 0; i < scopes.Length; i++)
mySubScopes.Add(scopes[sequence[i]]);
OnSubScopesReordered();
}
///
public IScope GetScope(Guid guid) {
if (Guid == guid) return this;
else {
for (int i = 0; i < mySubScopes.Count; i++) {
IScope s = mySubScopes[i].GetScope(guid);
if (s != null) return s;
}
}
return null;
}
///
public IScope GetScope(string name) {
if (Name == name) return this;
else {
for (int i = 0; i < mySubScopes.Count; i++) {
IScope s = mySubScopes[i].GetScope(name);
if (s != null) return s;
}
}
return null;
}
///
public void Clear() {
string[] variableNames = new string[Variables.Count];
int i = 0;
foreach (IVariable variable in Variables) {
variableNames[i] = variable.Name;
i++;
}
for (int j = 0; j < variableNames.Length; j++)
RemoveVariable(variableNames[j]);
KeyValuePair[] aliases = new KeyValuePair[myAliases.Count];
myAliases.CopyTo(aliases, 0);
for (int j = 0; j < aliases.Length; j++)
RemoveAlias(aliases[j].Key);
while (SubScopes.Count > 0)
RemoveSubScope(SubScopes[0]);
}
///
public override object Clone(IDictionary clonedObjects) {
Scope clone = (Scope)base.Clone(clonedObjects);
clone.myName = Name;
foreach (IVariable variable in myVariables.Values)
clone.AddVariable((IVariable)Auxiliary.Clone(variable, clonedObjects));
foreach (KeyValuePair alias in myAliases)
clone.AddAlias(alias.Key, alias.Value);
for (int i = 0; i < SubScopes.Count; i++)
clone.AddSubScope((IScope)Auxiliary.Clone(SubScopes[i], clonedObjects));
return clone;
}
///
public event EventHandler> VariableAdded;
///
/// Fires a new VariableAdded event.
///
/// The variable that has been added.
protected virtual void OnVariableAdded(IVariable variable) {
if (VariableAdded != null)
VariableAdded(this, new EventArgs(variable));
}
///
public event EventHandler> VariableRemoved;
///
/// Fires a new VariableRemoved.
///
/// The variable that has been deleted.
protected virtual void OnVariableRemoved(IVariable variable) {
if (VariableRemoved != null)
VariableRemoved(this, new EventArgs(variable));
}
///
public event EventHandler> AliasAdded;
///
/// Fires a new AliasAdded event.
///
/// The alias that has been added.
protected virtual void OnAliasAdded(string alias) {
if (AliasAdded != null)
AliasAdded(this, new EventArgs(alias));
}
///
public event EventHandler> AliasRemoved;
///
/// Fires a new AliasRemoved event.
///
/// The alias that has been deleted.
protected virtual void OnAliasRemoved(string alias) {
if (AliasRemoved != null)
AliasRemoved(this, new EventArgs(alias));
}
///
public event EventHandler> SubScopeAdded;
///
/// Fires a new SubScopeAdded event.
///
/// The sub scope that has been added.
/// The index where the scope has been added.
protected virtual void OnSubScopeAdded(IScope scope, int index) {
if (SubScopeAdded != null)
SubScopeAdded(this, new EventArgs(scope, index));
}
///
public event EventHandler> SubScopeRemoved;
///
/// Fires a new SubScopeRemoved event.
///
/// The sub scope that has been deleted.
/// The position of the sub scope.
protected virtual void OnSubScopeRemoved(IScope scope, int index) {
if (SubScopeRemoved != null)
SubScopeRemoved(this, new EventArgs(scope, index));
}
///
public event EventHandler SubScopesReordered;
///
/// Fires a new SubScopesReordered event
///
protected virtual void OnSubScopesReordered() {
if (SubScopesReordered != null)
SubScopesReordered(this, new EventArgs());
}
}
}