protected ParallelComputationContext CreateComputationContext(GeneralTransformationRule rule)
        {
            var compCon = new ParallelComputationContext(this);

            compCon.DelayOutputAtLeast(rule.OutputDelayLevel);
            compCon.DelayTransformationAtLeast(rule.TransformationDelayLevel);
            return(compCon);
        }
 protected ParallelComputationContext CreateComputationContext(GeneralTransformationRule rule)
 {
     var compCon = new ParallelComputationContext(this);
     compCon.DelayOutputAtLeast(rule.OutputDelayLevel);
     compCon.DelayTransformationAtLeast(rule.TransformationDelayLevel);
     return compCon;
 }
        /// <summary>
        /// Calls the given transformation with the specified input
        /// </summary>
        /// <param name="input">The input for the transformation rule</param>
        /// <param name="transformationRule">The rule that should be applied</param>
        /// <param name="context">The callers context</param>
        /// <returns>The computation that handles this request</returns>
        public Computation CallTransformation(GeneralTransformationRule transformationRule, object[] input, IEnumerable context)
        {
            if (transformationRule == null)
            {
                throw new ArgumentNullException("transformationRule");
            }
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            List <ITraceEntry> computations;

            if (!computationsMade.TryGetValue(input, out computations))
            {
                computations = new List <ITraceEntry>();
                if (!computationsMade.TryAdd(input, computations))
                {
                    computations = computationsMade[input];
                }
            }

            var originalTransformationRule = transformationRule;

            while (transformationRule.BaseRule != null)
            {
                transformationRule = transformationRule.BaseRule;
            }

            Computation comp;
            ParallelComputationContext compCon = null;
            bool handleComputation;

            if (transformationRule.IsUnique)
            {
                lock (computations)
                {
                    comp = computations.OfType <Computation>().FirstOrDefault(cpt => cpt.TransformationRule == transformationRule);
                    if (comp != null && transformationRule != originalTransformationRule)
                    {
                        transformationRule = originalTransformationRule;
                        while (computations.OfType <Computation>().FirstOrDefault(cpt => cpt.TransformationRule == transformationRule.BaseRule) == null)
                        {
                            transformationRule = transformationRule.BaseRule;
                        }
                        comp = computations.OfType <Computation>().FirstOrDefault(cpt => cpt.TransformationRule == transformationRule);
                    }

                    if (comp == null)
                    {
                        handleComputation = true;
                        compCon           = CreateComputationContext(transformationRule);
                        comp = transformationRule.CreateComputation(input, compCon);
                        computations.Add(comp);
                        compCon.DelayOutput(new OutputDelay());
                    }
                    else
                    {
                        handleComputation = false;
                    }
                }
            }
            else
            {
                lock (computations)
                {
                    handleComputation = true;
                    compCon           = CreateComputationContext(transformationRule);
                    comp = transformationRule.CreateComputation(input, compCon);
                    computations.Add(comp);
                    compCon.DelayOutput(new OutputDelay());
                }
            }
            if (handleComputation)
            {
                AddTraceEntry(comp);

                CallDependencies(comp, true);

                HandleComputation(transformationRule, input, context, computations, originalTransformationRule, comp, compCon);
            }
            return(comp);
        }