using System;
using System.Collections.Generic;
using System.Text;
using CategoryTheory;
using DiagramUI.Interfaces;
using DiagramUI;
using DataPerformer.Interfaces;
namespace DataPerformer
{
/// <summary>
/// Backup of time provider
/// </summary>
public class TimeProviderBackup : IDisposable
{
#region Fields
Dictionary<ITimeMeasureConsumer, IMeasure> dictionary = new Dictionary<ITimeMeasureConsumer, IMeasure>();
IDataConsumer consumer;
IComponentCollection collection;
IDataPerformerRuntime runtime;
IDifferentialEquationProcessor processor;
List<IMeasurements> measurements = null;
Dictionary<IBlocking, bool> block = new Dictionary<IBlocking, bool>();
#endregion
#region Ctor
/// <summary>
/// Constructor
/// </summary>
/// <param name="consumer">Data consumer</param>
/// <param name="provider">Time provider</param>
/// <param name="processor">Differential equation processor</param>
/// <param name="priority">Priority</param>
public TimeProviderBackup(IDataConsumer consumer, ITimeMeasureProvider provider, IDifferentialEquationProcessor processor, int priority)
{
this.consumer = consumer;
SetTimeProvider(consumer, provider, dictionary);
collection = consumer.GetDependentCollection(priority);
CrerateMeasurements(priority, null);
runtime = StaticExtensionDataPerformerBase.Factory.Create(collection, priority);
this.processor = processor;
processor.Set(collection);
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="collection">Collection</param>
/// <param name="provider">Time provider</param>
/// <param name="processor">Differential equation processor</param>
/// <param name="priority">Priority</param>
public TimeProviderBackup(IComponentCollection collection, ITimeMeasureProvider provider,
IDifferentialEquationProcessor processor, int priority, string reason)
{
this.collection = collection;
CrerateMeasurements(priority, reason);
runtime = StaticExtensionDataPerformerBase.Factory.Create(collection, priority);
SetTimeProvider(collection, provider, dictionary);
this.processor = processor;
processor.Set(collection);
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="collection">Collection</param>
/// <param name="priority">Priority</param>
public TimeProviderBackup(IComponentCollection collection, int priority, string reason)
{
this.collection = collection;
CrerateMeasurements(priority, reason);
runtime = StaticExtensionDataPerformerBase.Factory.Create(collection, priority);
SetTimeProvider(collection, StaticExtensionDataPerformerBase.Factory.TimeProvider, dictionary);
processor = DifferentialEquationProcessor.Processor;
processor.Set(collection);
}
#endregion
#region IDisposable Members
void IDisposable.Dispose()
{
foreach (IBlocking bl in block.Keys)
{
bl.Blocked = block[bl];
}
if (collection != null)
{
collection.ForEach<IStopped>((IStopped stop) => { stop.Stop(); });
Reset(collection);
dictionary.Clear();
return;
}
Reset(consumer);
dictionary.Clear();
if (runtime is IDisposable)
{
IDisposable d = runtime as IDisposable;
d.Dispose();
}
if (processor != null)
{
processor.Clear();
}
}
#endregion
#region Members
/// <summary>
/// Runtime
/// </summary>
public IDataPerformerRuntime Runtime
{
get
{
return runtime;
}
}
internal List<IMeasurements> Measurements
{
get
{
return measurements;
}
}
static void SetTimeProvider(object o, ITimeMeasureProvider provider, IDictionary<ITimeMeasureConsumer, IMeasure> dictionary)
{
ITimeMeasureConsumer tc = o.GetLabelObject<ITimeMeasureConsumer>();
if (tc != null)
{
if (dictionary.ContainsKey(tc))
{
if (tc.Time != provider.TimeMeasure)
{
dictionary[tc] = tc.Time;
tc.Time = provider.TimeMeasure;
}
}
else
{
dictionary[tc] = tc.Time;
tc.Time = provider.TimeMeasure;
}
}
IChildrenObject co = o.GetLabelObject<IChildrenObject>();
if (co != null)
{
IAssociatedObject[] ch = co.Children;
foreach (object ob in ch)
{
SetTimeProvider(ob, provider, dictionary);
}
}
}
private static void SetTimeProvider(IComponentCollection collection, ITimeMeasureProvider provider, IDictionary<ITimeMeasureConsumer, IMeasure> dictionary)
{
IEnumerable<object> c = collection.AllComponents;
foreach (object o in c)
{
SetTimeProvider(o, provider, dictionary);
}
}
private void Reset(object o)
{
if (o is ITimeMeasureConsumer)
{
ITimeMeasureConsumer tc = o as ITimeMeasureConsumer;
if (dictionary.ContainsKey(tc))
{
tc.Time = dictionary[tc];
}
}
if (o is IChildrenObject)
{
IChildrenObject co = o as IChildrenObject;
IAssociatedObject[] ch = co.Children;
foreach (object ob in ch)
{
Reset(ob);
}
}
}
private void Reset(IDesktop desktop)
{
IEnumerable<ICategoryObject> co = desktop.CategoryObjects;
foreach (object o in co)
{
Reset(o);
}
}
/// <summary>
/// Sets time provider to data consumer and all dependent objects
/// </summary>
/// <param name="consumer">Data consumer</param>
/// <param name="provider">Data provider</param>
/// <param name="dictionary">Backup dictionary</param>
private static void SetTimeProvider(IDataConsumer consumer, ITimeMeasureProvider provider, IDictionary<ITimeMeasureConsumer, IMeasure> dictionary)
{
if (consumer is ITimeMeasureConsumer)
{
ITimeMeasureConsumer tc = consumer as ITimeMeasureConsumer;
if (dictionary.ContainsKey(tc))
{
if (tc.Time != provider.TimeMeasure)
{
dictionary[tc] = tc.Time;
tc.Time = provider.TimeMeasure;
}
}
else
{
dictionary[tc] = tc.Time;
tc.Time = provider.TimeMeasure;
}
}
for (int i = 0; i < consumer.Count; i++)
{
IMeasurements m = consumer[i];
SetTimeProvider(m, provider, dictionary);
}
if (consumer is IChildrenObject)
{
IChildrenObject co = consumer as IChildrenObject;
SetTimeProvider(co, provider, dictionary);
}
}
static void SetTimeProvider(IChildrenObject co, ITimeMeasureProvider provider, IDictionary<ITimeMeasureConsumer, IMeasure> dictionary)
{
IAssociatedObject[] ao = co.Children;
foreach (object o in ao)
{
if (o is IDataConsumer)
{
IDataConsumer dc = o as IDataConsumer;
SetTimeProvider(dc, provider, dictionary);
}
else if (o is IMeasurements)
{
IMeasurements mea = o as IMeasurements;
SetTimeProvider(mea, provider, dictionary);
}
if (o is IChildrenObject)
{
IChildrenObject cho = o as IChildrenObject;
SetTimeProvider(cho, provider, dictionary);
}
}
}
static void SetTimeProvider(IMeasurements m, ITimeMeasureProvider provider, IDictionary<ITimeMeasureConsumer, IMeasure> dictionary)
{
if (m is ITimeMeasureConsumer)
{
ITimeMeasureConsumer mc = m as ITimeMeasureConsumer;
if (dictionary.ContainsKey(mc))
{
if (mc.Time != provider.TimeMeasure)
{
dictionary[mc] = mc.Time;
mc.Time = provider.TimeMeasure;
}
}
else
{
dictionary[mc] = mc.Time;
mc.Time = provider.TimeMeasure;
}
}
if (m is IDataConsumer)
{
IDataConsumer dc = m as IDataConsumer;
SetTimeProvider(dc, provider, dictionary);
}
if (m is MeasurementsWrapper)
{
MeasurementsWrapper mw = m as MeasurementsWrapper;
int n = mw.Count;
for (int i = 0; i < n; i++)
{
SetTimeProvider(mw[i], provider, dictionary);
}
}
}
private void Reset(IDataConsumer consumer)
{
if (consumer is ITimeMeasureConsumer)
{
ITimeMeasureConsumer tc = consumer as ITimeMeasureConsumer;
if (dictionary.ContainsKey(tc))
{
tc.Time = dictionary[tc];
}
}
for (int i = 0; i < consumer.Count; i++)
{
IMeasurements m = consumer[i];
if (m is ITimeMeasureConsumer)
{
ITimeMeasureConsumer mc = m as ITimeMeasureConsumer;
if (dictionary.ContainsKey(mc))
{
mc.Time = dictionary[mc];
}
}
if (m is IDataConsumer)
{
IDataConsumer dc = m as IDataConsumer;
Reset(dc);
}
}
}
private void CrerateMeasurements(int priority, string reason)
{
List<IMeasurements> proh = new List<IMeasurements>();
List<IMeasurements> l = new List<IMeasurements>();
collection.ForEach<IDataConsumer>((IDataConsumer c) =>
{
if (c.SatisfiesReason(reason))
{
for (int i = 0; i < c.Count; i++)
{
IMeasurements m = c[i];
if (!l.Contains(m))
{
l.Add(m);
}
}
}
});
collection.ForEach<IMeasurements>((IMeasurements m) =>
{
if (priority == 0)
{
if (!l.Contains(m))
{
l.Add(m);
}
}
else
{
int n = m.GetPriority();
if (n == 0)
{
l.Add(m);
}
else
{
if (n < priority)
{
l.Add(m);
}
else
{
if (m is IBlocking)
{
IBlocking bl = m as IBlocking;
block[bl] = bl.Blocked;
bl.Blocked = true;
}
proh.Add(m);
}
}
}
}
);
int count = 0;
List<IMeasurements> add = new List<IMeasurements>();
add.AddRange(proh);
while (true)
{
foreach (IMeasurements m in l)
{
if (m is IDataConsumer)
{
IDataConsumer dc = m as IDataConsumer;
for (int i = 0; i < dc.Count; i++)
{
IMeasurements mea = dc[i];
if (proh.Contains(mea))
{
if (!add.Contains(m) & !proh.Contains(m))
{
add.Add(m);
continue;
}
}
}
}
}
foreach (IMeasurements m in add)
{
if (!proh.Contains(m))
{
proh.Add(m);
}
}
if (proh.Count == count)
{
break;
}
count = proh.Count;
}
foreach (IMeasurements m in proh)
{
if (l.Contains(m))
{
l.Remove(m);
}
}
l.Sort(DiagramUI.StaticExtensionDiagramUI.ObjectComparer);
measurements = l;
}
#endregion
}
}