#region License Information /* HeuristicLab * Copyright (C) 2002-2014 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.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.DataAnalysis.Symbolic { [StorableClass] public class Vertex : Item, IVertex { // use the same event to signal a change in the content, weight or label public event EventHandler Changed; protected virtual void OnChanged(object sender, EventArgs args) { var changed = Changed; if (changed != null) changed(sender, args); } public event EventHandler> ArcAdded; protected virtual void OnArcAdded(object sender, EventArgs args) { var added = ArcAdded; if (added != null) added(sender, args); } public event EventHandler> ArcRemoved; protected virtual void OnArcRemoved(object sender, EventArgs args) { var removed = ArcRemoved; if (removed != null) removed(sender, args); } [Storable] protected string label; public string Label { get { return label; } set { label = value; OnChanged(this, EventArgs.Empty); } } [Storable] protected double weight; public double Weight { get { return weight; } set { weight = value; OnChanged(this, EventArgs.Empty); } } [Storable] protected object content; public object Content { get { return content; } set { content = value; OnChanged(this, EventArgs.Empty); } } private List inArcs; public IEnumerable InArcs { get { return inArcs ?? Enumerable.Empty(); } } private List outArcs; public IEnumerable OutArcs { get { return outArcs ?? Enumerable.Empty(); } } [StorableConstructor] public Vertex(bool deserializing) : base(deserializing) { } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { } private Vertex() { } public Vertex(object content) : this() { this.content = content; } protected Vertex(Vertex original, Cloner cloner) : base(original, cloner) { content = original.content; label = original.Label; weight = original.Weight; inArcs = original.InArcs.Select(cloner.Clone).ToList(); outArcs = original.OutArcs.Select(cloner.Clone).ToList(); } public override IDeepCloneable Clone(Cloner cloner) { return new Vertex(this, cloner); } public void AddArc(IArc arc) { if (this != arc.Source && this != arc.Target) throw new InvalidOperationException("The current vertex must be either the arc source or the arc target."); if (this == arc.Source) { if (outArcs == null) outArcs = new List(); else if (outArcs.Contains(arc) || outArcs.Any(a => a.Target == arc.Target && a.Source == arc.Source)) throw new InvalidOperationException("Arc already added."); outArcs.Add(arc); } else if (this == arc.Target) { if (inArcs == null) inArcs = new List(); else if (inArcs.Contains(arc) || inArcs.Any(a => a.Target == arc.Target && a.Source == arc.Source)) throw new InvalidOperationException("Arc already added."); inArcs.Add(arc); } OnArcAdded(this, new EventArgs(arc)); } public void RemoveArc(IVertex vertex) { try { var arc = inArcs.Concat(outArcs).SingleOrDefault(x => x.Target == vertex || x.Source == vertex); RemoveArc(arc); } catch (Exception) { throw new InvalidOperationException("Only one arc allowed between two vertices"); } } public void RemoveArc(IArc arc) { if (this != arc.Source && this != arc.Target) throw new InvalidOperationException("The current vertex must be either the arc source or the arc target."); if (this == arc.Source && outArcs != null) { if (!outArcs.Remove(arc)) throw new InvalidOperationException("Arc is not present in this vertex' outgoing arcs."); } else if (this == arc.Target && inArcs != null) { if (!inArcs.Remove(arc)) throw new InvalidOperationException("Arc is not present in this vertex' incoming arcs."); } OnArcRemoved(this, new EventArgs(arc)); } public int InDegree { get { return InArcs.Count(); } } public int OutDegree { get { return OutArcs.Count(); } } public int Degree { get { return InDegree + OutDegree; } } } [StorableClass] public class Vertex : Vertex, IVertex where T : class,IItem { public new T Content { get { return (T)base.Content; } set { base.Content = value; } } [StorableConstructor] protected Vertex(bool deserializing) : base(deserializing) { } protected Vertex(Vertex original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new Vertex(this, cloner); } } }