예제 #1
0
        /// <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>();
                computationsMade.Add(input, computations);
            }

            var originalTransformationRule = transformationRule;

            Computation comp;

            if (transformationRule.IsUnique)
            {
                comp = computations.OfType <Computation>().FirstOrDefault(cpt => cpt.TransformationRule == originalTransformationRule);
            }
            else
            {
                comp = null;
            }
            if (comp == null)
            {
                while (transformationRule.BaseRule != null)
                {
                    transformationRule = transformationRule.BaseRule;
                }
                var compCon = CreateComputationContextInternal(input, transformationRule);
                comp = transformationRule.CreateComputation(input, compCon);
                if (comp == null)
                {
                    return(null);
                }

                computations.Add(comp);
                AddTraceEntry(comp);

                compCon.DelayOutput(new OutputDelay());

                CallDependencies(comp, true);

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

                if (transformationRule != originalTransformationRule)
                {
                    comp = computations.OfType <Computation>().FirstOrDefault(cpt => cpt.TransformationRule == originalTransformationRule);
                }
            }
            return(comp);
        }
예제 #2
0
 protected virtual string CreateLabel(object[] input, GeneralTransformationRule rule)
 {
     var sb = new StringBuilder();
     sb.Append("[");
     if (input[0] != null)
     {
         sb.Append(input[0].ToString());
     }
     else
     {
         sb.Append("(null)");
     }
     for (int i = 1; i < input.Length; i++)
     {
         sb.Append(",");
         if (input[i] != null)
         {
             sb.Append(input[i].ToString());
         }
         else
         {
             sb.Append("(null)");
         }
     }
     sb.Append("], ");
     sb.Append(rule.ToString());
     return sb.ToString();
 }
 private void AddChild(GeneralTransformationRule rule)
 {
     if (Children == null)
     {
         Children = new List <GeneralTransformationRule>();
     }
     Children.Add(rule);
 }
        private ComputationContext CreateComputationContextInternal(object[] input, GeneralTransformationRule rule)
        {
            var compCon = CreateComputationContext(input, rule);

            compCon.DelayOutputAtLeast(rule.OutputDelayLevel);
            compCon.DelayTransformationAtLeast(rule.TransformationDelayLevel);
            return(compCon);
        }
예제 #5
0
        protected sealed override ComputationContext CreateComputationContext(object[] input, GeneralTransformationRule rule)
        {
            var context = new TracingComputationContext(CreateId(input, rule), this);

            nodes.AppendFormat("    <Node Id=\"{0}\" Label=\"{1}\"/>", context.Id, CreateLabel(input, rule));
            nodes.AppendLine();

            return context;
        }
        internal ITransformationRuleDependency CallForEachInternal(GeneralTransformationRule rule, Predicate <Computation> filter, Func <Computation, IEnumerable <object[]> > selector, Action <object, IEnumerable> persistor, bool needOutput)
        {
            if (rule == null)
            {
                throw new ArgumentNullException("rule");
            }

            return(rule.DependMany(filter, selector, this, persistor, false, needOutput));
        }
        private void HandleDelayedComputation(Computation computation, ITransformationContext context, OutputDelay delay)
        {
            var inCollection = Selector(computation);

            if (inCollection != null)
            {
                if (Persistor != null)
                {
                    Type  listType = (typeof(List <>)).MakeGenericType(DependencyTransformation.OutputType);
                    IList list     = System.Activator.CreateInstance(listType) as IList;

                    MultipleResultAwaitingPersistor delayPersistor = new MultipleResultAwaitingPersistor()
                    {
                        List      = list,
                        Persistor = Persistor
                    };
                    if (context.IsThreadSafe)
                    {
                        Parallel.ForEach(inCollection, dependencyInput =>
                        {
                            HandleDelayedDependencyInput(computation, context, list, delayPersistor, dependencyInput);
                        });
                    }
                    else
                    {
                        foreach (var dependencyInput in inCollection)
                        {
                            HandleDelayedDependencyInput(computation, context, list, delayPersistor, dependencyInput);
                        }
                    }
                    delay.Persistors.Add(delayPersistor);
                }
                else
                {
                    if (context.IsThreadSafe)
                    {
                        Parallel.ForEach(inCollection, dependencyInput =>
                        {
                            GeneralTransformationRule dependent = DependencyTransformation;
                            var comp2 = context.CallTransformation(dependent, dependencyInput);

                            computation.MarkRequireInternal(comp2, ExecuteBefore, this);
                        });
                    }
                    else
                    {
                        foreach (var dependencyInput in inCollection)
                        {
                            GeneralTransformationRule dependent = DependencyTransformation;
                            var comp2 = context.CallTransformation(dependent, dependencyInput);

                            computation.MarkRequireInternal(comp2, ExecuteBefore, this);
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Marks the current transformation rule instantiating for the specified rule
 /// </summary>
 /// <param name="rule">The base transformation rule</param>
 /// <param name="filter">A method that filters the possible computations</param>
 /// <remarks>Note that in this version, the filter method is also responsible for checking the types!</remarks>
 public void MarkInstantiatingFor(GeneralTransformationRule rule, Predicate <Computation> filter)
 {
     if (rule == null)
     {
         throw new ArgumentNullException("rule");
     }
     rule.AddChild(this);
     AddBase(rule, filter);
 }
예제 #9
0
        /// <summary>
        /// Creates a new computation for the given transformation rule with the given input arguments
        /// </summary>
        /// <param name="transformationRule">The transformation rule responsible for the transformation of the input data</param>
        /// <param name="context">The transformation context, in which the computation is done</param>
        protected Computation(GeneralTransformationRule transformationRule, IComputationContext context)
        {
            if (transformationRule == null) throw new ArgumentNullException("transformationRule");
            if (context == null) throw new ArgumentNullException("context");

            TransformationRule = transformationRule;
            Context = context;

            context.ConnectWith(this);
        }
예제 #10
0
파일: Trace.cs 프로젝트: FrederikP/NMF
        /// <summary>
        /// Traces the computation based upon the specified input with the specified transformation rule
        /// </summary>
        /// <param name="rule">The transformation rule the object was transformed with</param>
        /// <returns>The computation or null, if there was none</returns>
        /// <param name="input">The input arguments</param>
        public virtual IEnumerable<ITraceEntry> TraceIn(GeneralTransformationRule rule, params object[] input)
        {
            if (rule == null) throw new ArgumentNullException("rule");

            if (input == null || input.Length != rule.InputType.Length) return Enumerable.Empty<ITraceEntry>();

            return from ITraceEntry c in Computations
                   where c.TransformationRule == rule
                   && IsInputArray(c, input)
                   select c;
        }
예제 #11
0
        /// <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>();
                computationsMade.Add(input, computations);
            }

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

            Computation comp;
            if (transformationRule.IsUnique)
            {
                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);
                }
            }
            else
            {
                comp = null;
            }
            if (comp == null)
            {
                var compCon = CreateComputationContextInternal(input, transformationRule);
                comp = transformationRule.CreateComputation(input, compCon);

                if (comp == null) return null;

                computations.Add(comp);
                AddTraceEntry(comp);

                compCon.DelayOutput(new OutputDelay());

                CallDependencies(comp, true);

                HandleComputation(transformationRule, input, context, computations, originalTransformationRule, comp, compCon);
            }
            return comp;
        }
예제 #12
0
        /// <summary>
        /// Traces all computations with any inputs that math the given filters with the specified transformation rule
        /// </summary>
        /// <param name="rule">The transformation rule</param>
        /// <returns>A collection with all computations made under these circumstances</returns>
        public virtual IEnumerable <ITraceEntry> TraceAllIn(GeneralTransformationRule rule)
        {
            if (rule == null)
            {
                throw new ArgumentNullException("rule");
            }

            return(from ITraceEntry c in Computations
                   where c.TransformationRule == rule
                   select c);
        }
예제 #13
0
 /// <summary>
 /// Traces the computations of the specified inputs with the specified transformation rules
 /// </summary>
 /// <param name="rule">The transformation rules that transformed the specified inputs</param>
 /// <param name="inputs">A collection of input arguments</param>
 /// <returns>A collection of computations</returns>
 public virtual IEnumerable <ITraceEntry> TraceManyIn(GeneralTransformationRule rule, IEnumerable <object[]> inputs)
 {
     if (rule == null)
     {
         throw new ArgumentNullException("rule");
     }
     if (inputs.IsNullOrEmpty())
     {
         return(Enumerable.Empty <ITraceEntry>());
     }
     return(Computations.Where(c => c.TransformationRule == rule && inputs.Any(input => input != null && input.Length == rule.InputType.Length && IsInputArray(c, input))));
 }
 private void AddBase(GeneralTransformationRule rule, Predicate <Computation> filter)
 {
     if (BaseRule == null)
     {
         BaseRule   = rule;
         BaseFilter = filter;
     }
     else
     {
         throw new InvalidOperationException(Resources.ErrMarkInstantiatingForOneRuleAtMost);
     }
 }
            /// <summary>
            /// Traces the computation based upon the specified input with the specified transformation rule
            /// </summary>
            /// <param name="rule">The transformation rule the object was transformed with</param>
            /// <returns>The computation or null, if there was none</returns>
            /// <param name="input">The input arguments</param>
            public override IEnumerable <ITraceEntry> TraceIn(GeneralTransformationRule rule, params object[] input)
            {
                if (rule == null)
                {
                    throw new ArgumentNullException("rule");
                }
                List <ITraceEntry> comps;

                if (computationsMade.TryGetValue(input, out comps))
                {
                    return(comps.Where(c => c.TransformationRule == rule));
                }
                return(Enumerable.Empty <ITraceEntry>());
            }
 /// <summary>
 /// Marks the current transformation rule instantiating for the specified rule
 /// </summary>
 /// <param name="rule">The base transformation rule</param>
 public void MarkInstantiatingFor(GeneralTransformationRule rule)
 {
     if (rule == null)
     {
         throw new ArgumentNullException("rule");
     }
     if (rule.InputType.IsAssignableArrayFrom(InputType) && (rule.OutputType == OutputType || rule.OutputType.IsAssignableFrom(OutputType) || OutputType.IsInterface))
     {
         MarkInstantiatingFor(rule, null);
     }
     else
     {
         throw new InvalidOperationException(Resources.ErrMarkInstantiatingForMustInherit);
     }
 }
 /// <summary>
 /// Requires the given transformation rule
 /// </summary>
 /// <param name="rule">The transformation rule that should be required</param>
 /// <remarks>This version Always takes the input parameter as input for the dependent transformations. Thus, this method will throw an exception, if the types do not match</remarks>
 public void Call(GeneralTransformationRule rule)
 {
     if (rule == null)
     {
         throw new ArgumentNullException("rule");
     }
     if (rule.InputType.IsAssignableArrayFrom(InputType))
     {
         Depend(null, c => c.CreateInputArray(), rule, null, false, false);
     }
     else
     {
         throw new InvalidOperationException(Resources.ErrRequiresTransNoSelectorMustInherit);
     }
 }
예제 #18
0
        /// <summary>
        /// Creates a new computation for the given transformation rule with the given input arguments
        /// </summary>
        /// <param name="transformationRule">The transformation rule responsible for the transformation of the input data</param>
        /// <param name="context">The transformation context, in which the computation is done</param>
        protected Computation(GeneralTransformationRule transformationRule, IComputationContext context)
        {
            if (transformationRule == null)
            {
                throw new ArgumentNullException("transformationRule");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            TransformationRule = transformationRule;
            Context            = context;

            context.ConnectWith(this);
        }
예제 #19
0
        /// <summary>
        /// Traces the computation based upon the specified input with the specified transformation rule
        /// </summary>
        /// <param name="rule">The transformation rule the object was transformed with</param>
        /// <returns>The computation or null, if there was none</returns>
        /// <param name="input">The input arguments</param>
        public virtual IEnumerable <ITraceEntry> TraceIn(GeneralTransformationRule rule, params object[] input)
        {
            if (rule == null)
            {
                throw new ArgumentNullException("rule");
            }

            if (input == null || input.Length != rule.InputType.Length)
            {
                return(Enumerable.Empty <ITraceEntry>());
            }

            return(from ITraceEntry c in Computations
                   where c.TransformationRule == rule &&
                   IsInputArray(c, input)
                   select c);
        }
            /// <summary>
            /// Traces all computations with any inputs that math the given filters with the specified transformation rule
            /// </summary>
            /// <param name="rule">The transformation rule</param>
            /// <returns>A collection with all computations made under these circumstances</returns>
            public override IEnumerable <ITraceEntry> TraceAllIn(GeneralTransformationRule rule)
            {
                if (rule == null)
                {
                    throw new ArgumentNullException("rule");
                }
                List <ITraceEntry> comps;

                if (computationsByTransformationRule.TryGetValue(rule, out comps))
                {
                    return(comps.AsReadOnly());
                }
                else
                {
                    return(Enumerable.Empty <Computation>());
                }
            }
        private static void ReorderStack(GeneralTransformationRule originalTransformationRule, Computation comp, Stack <GeneralTransformationRule> ruleStack)
        {
            var testTransformationRule = originalTransformationRule;
            var missingStack           = new Stack <GeneralTransformationRule>();

            while (!ruleStack.Contains(testTransformationRule))
            {
                missingStack.Push(testTransformationRule);
                testTransformationRule = testTransformationRule.BaseRule;
            }
            while (ruleStack.Peek() != testTransformationRule)
            {
                ruleStack.Pop();
                if (ruleStack.Count == 0)
                {
                    throw new InvalidOperationException("The rule stack from the transformation rule did not contain the base rule of the computation");
                }
            }
            while (missingStack.Count > 0)
            {
                testTransformationRule = missingStack.Pop();
                ruleStack.Push(testTransformationRule);
            }
            while (!testTransformationRule.IsLeafTransformation)
            {
                var found = false;
                foreach (var next in testTransformationRule.Children)
                {
                    if (next.IsInstantiating(comp))
                    {
                        testTransformationRule = next;
                        ruleStack.Push(next);
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    break;
                }
            }
        }
 /// <summary>
 /// Marks the current transformation rule instantiating for the specified rule
 /// </summary>
 /// <param name="filter">The filter that should filter the inputs where this transformation rule is marked instantiating</param>
 /// <param name="rule">The transformation rule</param>
 public void MarkInstantiatingFor(GeneralTransformationRule rule, Predicate<object[]> filter)
 {
     if (rule == null) throw new ArgumentNullException("rule");
     if (rule.InputType.IsAssignableArrayFrom(InputType) && (rule.OutputType == typeof(void)))
     {
         Require(rule);
         if (filter != null)
         {
             MarkInstantiatingFor(rule, o => InputType.IsInstanceArrayOfType(o) && filter(o));
         }
         else
         {
             MarkInstantiatingFor(rule, InputType.IsInstanceArrayOfType);
         }
     }
     else
     {
         throw new InvalidOperationException(Resources.ErrMarkInstantiatingMustInherit);
     }
 }
            /// <summary>
            /// Traces the computations of the specified inputs with the specified transformation rules
            /// </summary>
            /// <param name="rule">The transformation rules that transformed the specified inputs</param>
            /// <param name="inputs">A collection of input arguments</param>
            /// <returns>A collection of computations</returns>
            public override IEnumerable <ITraceEntry> TraceManyIn(GeneralTransformationRule rule, IEnumerable <object[]> inputs)
            {
                if (rule == null)
                {
                    throw new ArgumentNullException("rule");
                }
                if (inputs == null)
                {
                    return(Enumerable.Empty <ITraceEntry>());
                }
                List <ITraceEntry> result = new List <ITraceEntry>();

                foreach (var input in inputs)
                {
                    List <ITraceEntry> comps;
                    if (computationsMade.TryGetValue(input, out comps))
                    {
                        result.AddRange(comps.Where(c => c.TransformationRule == rule));
                    }
                }
                return(result);
            }
예제 #24
0
 /// <summary>
 /// Transforms the input argument into an output using the provided transformation
 /// </summary>
 /// <param name="inputs">The input arguments as an array. This must not be null. The correct amount of parameters depends on the rule to start with.</param>
 /// <param name="inputContext">The context object in which the transformation is run</param>
 /// <param name="startRule">The start rule to begin with (must not be null)</param>
 /// <param name="context">The transformation context (must not be null)</param>
 /// <returns>The transformation computations</returns>
 public static IEnumerable<Computation> TransformMany(IEnumerable<object[]> inputs, IEnumerable inputContext, GeneralTransformationRule startRule, ITransformationEngineContext context)
 {
     if (context == null) throw new ArgumentNullException("context");
     if (inputs == null) throw new ArgumentNullException("inputs");
     if (startRule == null) throw new InvalidOperationException("Could not find transaction rule to start with.");
     if (!context.Transformation.IsInitialized) throw new InvalidOperationException("Could not initialize transformation");
     var patternObjects = new List<ITransformationPatternContext>();
     foreach (var pattern in context.Transformation.Patterns)
     {
         var obj = pattern.CreatePattern(context);
         if (obj != null) patternObjects.Add(obj);
     }
     var list = new List<Computation>();
     foreach (var input in inputs)
     {
         var comp = context.CallTransformation(startRule, input, inputContext);
         list.Add(comp);
         if (!comp.IsDelayed)
         {
             context.Outputs.Add(comp.Output);
         }
         else
         {
             comp.OutputInitialized += (o,e) => context.Outputs.Add(comp.Output);
         }
     }
     context.ExecutePending();
     foreach (var pattern in patternObjects)
     {
         pattern.Begin();
         context.ExecutePending();
     }
     foreach (var pattern in patternObjects)
     {
         pattern.Finish();
     }
     return list;
 }
        private void HandleDelayedDependencyInput(Computation computation, ITransformationContext context, IList list, MultipleResultAwaitingPersistor delayPersistor, object[] dependencyInput)
        {
            GeneralTransformationRule dependent = DependencyTransformation;
            var comp2 = context.CallTransformation(dependent, dependencyInput);

            if (!comp2.IsDelayed)
            {
                if (comp2.Output != null)
                {
                    if (context.IsThreadSafe)
                    {
                        lock (list)
                        {
                            list.Add(comp2.Output);
                        }
                    }
                    else
                    {
                        list.Add(comp2.Output);
                    }
                }
            }
            else
            {
                computation.DelayOutputAtLeast(comp2.Context.MinOutputDelayLevel);
                delayPersistor.WaitFor(comp2);
            }

            if (ExecuteBefore)
            {
                computation.DelayTransformationAtLeast(comp2.Context.MinTransformDelayLevel);
            }
            else
            {
                comp2.DelayTransformationAtLeast(computation.Context.MinTransformDelayLevel);
            }
        }
예제 #26
0
 private static void ReorderStack(GeneralTransformationRule originalTransformationRule, Computation comp, Stack<GeneralTransformationRule> ruleStack)
 {
     var testTransformationRule = originalTransformationRule;
     var missingStack = new Stack<GeneralTransformationRule>();
     while (!ruleStack.Contains(testTransformationRule))
     {
         missingStack.Push(testTransformationRule);
         testTransformationRule = testTransformationRule.BaseRule;
     }
     while (ruleStack.Peek() != testTransformationRule)
     {
         ruleStack.Pop();
         if (ruleStack.Count == 0) throw new InvalidOperationException("The rule stack from the transformation rule did not contain the base rule of the computation");
     }
     while (missingStack.Count > 0)
     {
         testTransformationRule = missingStack.Pop();
         ruleStack.Push(testTransformationRule);
     }
     while (!testTransformationRule.IsLeafTransformation)
     {
         var found = false;
         foreach (var next in testTransformationRule.Children)
         {
             if (next.IsInstantiating(comp))
             {
                 testTransformationRule = next;
                 ruleStack.Push(next);
                 found = true;
                 break;
             }
         }
         if (!found) break;
     }
 }
        /// <summary>
        /// Calls the transformation dependency for the given computation
        /// </summary>
        /// <param name="computation">The computation that this dependency is to be called</param>
        public override void HandleDependency(Computation computation)
        {
            if (computation == null)
            {
                throw new ArgumentNullException("computation");
            }

            if (computation.IsDelayed && NeedOutput)
            {
                computation.OutputInitialized += CallComputation;
                return;
            }

            if (Filter == null || Filter(computation))
            {
                var context = computation.TransformationContext;
                if (Selector != null)
                {
                    if (computation.IsDelayed)
                    {
                        //case delayed
                        var delay = computation.OutputDelay;
                        if (!NeedOutput)
                        {
                            object[] dependencyInput = Selector(computation);
                            if (dependencyInput != null)
                            {
                                GeneralTransformationRule dependent = DependencyTransformation;
                                var comp2 = context.CallTransformation(dependent, dependencyInput);
                                if (Persistor != null)
                                {
                                    if (!comp2.IsDelayed)
                                    {
                                        delay.Persistors.Add(new SingleItemPersistor()
                                        {
                                            Persistor = Persistor,
                                            Output    = comp2.Output
                                        });
                                    }
                                    else
                                    {
                                        computation.DelayOutputAtLeast(comp2.Context.MinOutputDelayLevel);
                                        var delayPersistor = new SingleResultAwaitingPersistor(Persistor);
                                        delayPersistor.WaitFor(comp2);
                                        delay.Persistors.Add(delayPersistor);
                                    }
                                }
                                else // persistor is null
                                {
                                    if (ExecuteBefore)
                                    {
                                        if (comp2.IsDelayed)
                                        {
                                            computation.DelayOutputAtLeast(comp2.Context.MinOutputDelayLevel);
                                        }
                                    }
                                }

                                computation.MarkRequireInternal(comp2, ExecuteBefore, this);
                            }
                        }
                    }
                    else // not delayed
                    {
                        // case output is already created
                        var      output          = computation.Output;
                        object[] dependencyInput = Selector(computation);
                        if (dependencyInput != null)
                        {
                            GeneralTransformationRule dependent = DependencyTransformation;
                            var comp2 = context.CallTransformation(dependent, dependencyInput);
                            if (Persistor != null)
                            {
                                if (!comp2.IsDelayed)
                                {
                                    Persistor(output, comp2.Output);
                                }
                                else
                                {
                                    var delay = new SingleResultAwaitingPersistor(Persistor, computation.Output);
                                    delay.WaitFor(comp2);
                                }
                            }

                            computation.MarkRequireInternal(comp2, ExecuteBefore, this);
                        }
                    }
                }
            }
        }
예제 #28
0
        /// <summary>
        /// Handles the computation internally, i.e. calls dependencies, creates output, manages delays, etc
        /// </summary>
        /// <param name="transformationRule">The transformation rule</param>
        /// <param name="input">The input elements for this computation</param>
        /// <param name="context">The transformation context</param>
        /// <param name="computations">The computations for the input</param>
        /// <param name="originalTransformationRule">The transformation rule of the original call</param>
        /// <param name="comp">The computation</param>
        /// <param name="compCon">The computation context</param>
        private void HandleComputation(GeneralTransformationRule transformationRule, object[] input, IEnumerable context, List<ITraceEntry> computations, GeneralTransformationRule originalTransformationRule, Computation comp, ComputationContext compCon)
        {
            // The transformation output is only generated when we are handling the base transformation rule,
            // because this is always required
            if (compCon.IsDelayed)
            {
                Stack<Computation> dependantComputes = new Stack<Computation>();
                var ruleStack = Transformation.ComputeInstantiatingTransformationRulePath(comp);
                if (transformationRule != originalTransformationRule)
                {
                    ReorderStack(originalTransformationRule, comp, ruleStack);
                }
                var delayLevel = comp.Context.MinOutputDelayLevel;

                var computes = new List<Computation>();
                Computation lastComp = null;

                while (ruleStack.Count > 0)
                {
                    var rule = ruleStack.Pop();
                    var comp2 = FindOrCreateDependentComputation(input, computations, comp, dependantComputes, rule);

                    // in case comp2 is not yet handled, a delay does not yet exist and thus
                    // DelayLevel < minDelayLevel
                    delayLevel = Math.Max(delayLevel, Math.Max(comp2.OutputDelayLevel, comp2.Context.MinOutputDelayLevel));
                    if (lastComp != null)
                    {
                        lastComp.SetBaseComputation(comp2);
                    }
                    lastComp = comp2;
                    computes.Add(comp2);
                }

                // delay the call of dependencies
                // this prevents the issue arising from computations calling their parents that come later in the stack
                foreach (var comp2 in dependantComputes)
                {
                    CallDependencies(comp2, true);
                }

                if (delayLevel <= currentOutputDelay)
                {
                    var createRule = computes[0];

                    // Generate the output
                    var output = createRule.CreateOutput(context);

                    for (int i = computes.Count - 1; i >= 0; i--)
                    {
                        computes[i].InitializeOutput(output);
                    }
                    if (callTransformations)
                    {
                        for (int i = computes.Count - 1; i >= 0; i--)
                        {
                            computes[i].Transform();
                        }
                    }
                }
                else
                {
                    //Save computations into Delay
                    Delay(delayLevel, computes, context);
                }

                if (!callTransformations)
                {
                    for (int i = computes.Count - 1; i >= 0; i--)
                    {
                        AddToComputationOrder(computes[i], currentTransformationDelay);
                    }
                }

                for (int i = computes.Count - 1; i >= 0; i--)
                {
                    dependencyCallQueue.Enqueue(computes[i]);
                }
            }
        }
예제 #29
0
 private ComputationContext CreateComputationContextInternal(object[] input, GeneralTransformationRule rule)
 {
     var compCon = CreateComputationContext(input, rule);
     compCon.DelayOutputAtLeast(rule.OutputDelayLevel);
     compCon.DelayTransformationAtLeast(rule.TransformationDelayLevel);
     return compCon;
 }
예제 #30
0
 /// <summary>
 /// Traces the computation based upon the specified input with the specified transformation rule
 /// </summary>
 /// <param name="rule">The transformation rule the object was transformed with</param>
 /// <returns>The computation or null, if there was none</returns>
 /// <param name="input">The input arguments</param>
 public override IEnumerable<ITraceEntry> TraceIn(GeneralTransformationRule rule, params object[] input)
 {
     if (rule == null) throw new ArgumentNullException("rule");
     List<ITraceEntry> comps;
     if (computationsMade.TryGetValue(input, out comps))
     {
         return comps.Where(c => c.TransformationRule == rule);
     }
     return Enumerable.Empty<ITraceEntry>();
 }
 protected virtual ComputationContext CreateComputationContext(object[] input, GeneralTransformationRule rule)
 {
     return(new ComputationContext(this));
 }
        /// <summary>
        /// Handles the computation internally, i.e. calls dependencies, creates output, manages delays, etc
        /// </summary>
        /// <param name="transformationRule">The transformation rule</param>
        /// <param name="input">The input elements for this computation</param>
        /// <param name="context">The transformation context</param>
        /// <param name="computations">The computations for the input</param>
        /// <param name="originalTransformationRule">The transformation rule of the original call</param>
        /// <param name="comp">The computation</param>
        /// <param name="compCon">The computation context</param>
        private void HandleComputation(GeneralTransformationRule transformationRule, object[] input, IEnumerable context, List <ITraceEntry> computations, GeneralTransformationRule originalTransformationRule, Computation comp, ComputationContext compCon)
        {
            // The transformation output is only generated when we are handling the base transformation rule,
            // because this is always required
            if (compCon.IsDelayed)
            {
                Stack <Computation> dependantComputes = new Stack <Computation>();
                var ruleStack = Transformation.ComputeInstantiatingTransformationRulePath(comp);
                if (transformationRule != originalTransformationRule)
                {
                    ReorderStack(originalTransformationRule, comp, ruleStack);
                }
                var delayLevel = comp.Context.MinOutputDelayLevel;

                var         computes = new List <Computation>();
                Computation lastComp = null;

                while (ruleStack.Count > 0)
                {
                    var rule  = ruleStack.Pop();
                    var comp2 = FindOrCreateDependentComputation(input, computations, comp, dependantComputes, rule);

                    // in case comp2 is not yet handled, a delay does not yet exist and thus
                    // DelayLevel < minDelayLevel
                    delayLevel = Math.Max(delayLevel, Math.Max(comp2.OutputDelayLevel, comp2.Context.MinOutputDelayLevel));
                    if (lastComp != null)
                    {
                        lastComp.SetBaseComputation(comp2);
                    }
                    lastComp = comp2;
                    computes.Add(comp2);
                }

                // delay the call of dependencies
                // this prevents the issue arising from computations calling their parents that come later in the stack
                foreach (var comp2 in dependantComputes)
                {
                    CallDependencies(comp2, true);
                }

                if (delayLevel <= currentOutputDelay)
                {
                    var createRule = computes[0];

                    // Generate the output
                    var output = createRule.CreateOutput(context);

                    for (int i = computes.Count - 1; i >= 0; i--)
                    {
                        computes[i].InitializeOutput(output);
                    }
                    if (callTransformations)
                    {
                        for (int i = computes.Count - 1; i >= 0; i--)
                        {
                            computes[i].Transform();
                        }
                    }
                }
                else
                {
                    //Save computations into Delay
                    Delay(delayLevel, computes, context);
                }

                if (!callTransformations)
                {
                    for (int i = computes.Count - 1; i >= 0; i--)
                    {
                        AddToComputationOrder(computes[i], currentTransformationDelay);
                    }
                }

                for (int i = computes.Count - 1; i >= 0; i--)
                {
                    dependencyCallQueue.Enqueue(computes[i]);
                }
            }
        }
예제 #33
0
        internal ITransformationRuleDependency DependMany(Predicate<Computation> filter, Func<Computation, IEnumerable<object[]>> selector, GeneralTransformationRule transformation, Action<object, IEnumerable> persistor, bool executeBefore, bool needOutput)
        {
            if (transformation == null) throw new ArgumentNullException("transformation");
            if (selector == null) throw new ArgumentNullException("selector");

            var dependency = new MultipleDependency()
            {
                Filter = filter,
                Selector = selector,
                Persistor = persistor,
                BaseTransformation = this,
                DependencyTransformation = transformation,
                ExecuteBefore = executeBefore,
                NeedOutput = needOutput
            };

            Dependencies.Add(dependency);

            return dependency;
        }
예제 #34
0
        /// <summary>
        /// Transforms the input argument into an output using the provided transformation
        /// </summary>
        /// <param name="inputs">The input arguments as an array. This must not be null. The correct amount of parameters depends on the rule to start with.</param>
        /// <param name="inputContext">The context object in which the transformation is run</param>
        /// <param name="startRule">The start rule to begin with (must not be null)</param>
        /// <param name="context">The transformation context (must not be null)</param>
        /// <returns>The transformation computations</returns>
        public static IEnumerable <Computation> TransformMany(IEnumerable <object[]> inputs, IEnumerable inputContext, GeneralTransformationRule startRule, ITransformationEngineContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (inputs == null)
            {
                throw new ArgumentNullException("inputs");
            }
            if (startRule == null)
            {
                throw new InvalidOperationException("Could not find transaction rule to start with.");
            }
            if (!context.Transformation.IsInitialized)
            {
                throw new InvalidOperationException("Could not initialize transformation");
            }
            var patternObjects = new List <ITransformationPatternContext>();

            foreach (var pattern in context.Transformation.Patterns)
            {
                var obj = pattern.CreatePattern(context);
                if (obj != null)
                {
                    patternObjects.Add(obj);
                }
            }
            var list = new List <Computation>();

            foreach (var input in inputs)
            {
                var comp = context.CallTransformation(startRule, input, inputContext);
                list.Add(comp);
                if (!comp.IsDelayed)
                {
                    context.Outputs.Add(comp.Output);
                }
                else
                {
                    comp.OutputInitialized += (o, e) => context.Outputs.Add(comp.Output);
                }
            }
            context.ExecutePending();
            foreach (var pattern in patternObjects)
            {
                pattern.Begin();
                context.ExecutePending();
            }
            foreach (var pattern in patternObjects)
            {
                pattern.Finish();
            }
            return(list);
        }
예제 #35
0
 /// <summary>
 /// Calls the given transformation with the specified input
 /// </summary>
 /// <param name="context">The current transformation context</param>
 /// <param name="transformationRule">The rule that should be applied</param>
 /// <param name="input">The input for the transformation rule</param>
 /// <returns>The computation that handles this request</returns>
 public static Computation CallTransformation(this ITransformationContext context, GeneralTransformationRule transformationRule, params object[] input)
 {
     return context.CallTransformation(transformationRule, input, null);
 }
예제 #36
0
파일: Trace.cs 프로젝트: FrederikP/NMF
        /// <summary>
        /// Traces all computations with any inputs that math the given filters with the specified transformation rule
        /// </summary>
        /// <param name="rule">The transformation rule</param>
        /// <returns>A collection with all computations made under these circumstances</returns>
        public virtual IEnumerable<ITraceEntry> TraceAllIn(GeneralTransformationRule rule)
        {
            if (rule == null) throw new ArgumentNullException("rule");

            return from ITraceEntry c in Computations
                   where c.TransformationRule == rule
                   select c;
        }
예제 #37
0
 protected virtual string CreateId(object[] input, GeneralTransformationRule rule)
 {
     counter++;
     return "node" + counter.ToString();
 }
예제 #38
0
파일: Trace.cs 프로젝트: FrederikP/NMF
 /// <summary>
 /// Traces the computations of the specified inputs with the specified transformation rules
 /// </summary>
 /// <param name="rule">The transformation rules that transformed the specified inputs</param>
 /// <param name="inputs">A collection of input arguments</param>
 /// <returns>A collection of computations</returns>
 public virtual IEnumerable<ITraceEntry> TraceManyIn(GeneralTransformationRule rule, IEnumerable<object[]> inputs)
 {
     if (rule == null) throw new ArgumentNullException("rule");
     if (inputs.IsNullOrEmpty()) return Enumerable.Empty<ITraceEntry>();
     return Computations.Where(c => c.TransformationRule == rule && inputs.Any(input => input != null && input.Length == rule.InputType.Length && IsInputArray(c, input)));
 }
예제 #39
0
 /// <summary>
 /// Creates a new mocked computation
 /// </summary>
 /// <param name="input">The input for the mocked computation</param>
 /// <param name="rule">The transformation rule for the mocked computation</param>
 /// <param name="context">The transformation context</param>
 public MockComputation(object[] input, GeneralTransformationRule rule, ITransformationContext context) : this(input, rule, new ComputationContext(context)) { }
예제 #40
0
 /// <summary>
 /// Creates a new mocked computation
 /// </summary>
 /// <param name="input">The input for the mocked computation</param>
 /// <param name="rule">The transformation rule for the mocked computation</param>
 /// <param name="context">The transformation context</param>
 public MockComputation(object[] input, GeneralTransformationRule rule, IComputationContext context) : base(rule, context) { inputs = input; }
예제 #41
0
        internal ITransformationRuleDependency CallForEachInternal(GeneralTransformationRule rule, Predicate<Computation> filter, Func<Computation, IEnumerable<object[]>> selector, Action<object, IEnumerable> persistor, bool needOutput)
        {
            if (rule == null) throw new ArgumentNullException("rule");

            return rule.DependMany(filter, selector, this, persistor, false, needOutput);
        }
예제 #42
0
 protected virtual ComputationContext CreateComputationContext(object[] input, GeneralTransformationRule rule)
 {
     return new ComputationContext(this);
 }
예제 #43
0
 private void AddBase(GeneralTransformationRule rule, Predicate<Computation> filter)
 {
     if (BaseRule == null)
     {
         BaseRule = rule;
         BaseFilter = filter;
     }
     else
     {
         throw new InvalidOperationException(Resources.ErrMarkInstantiatingForOneRuleAtMost);
     }
 }
        private Computation FindOrCreateDependentComputation(object[] input, List <ITraceEntry> computations, Computation comp, Stack <Computation> dependantComputes, GeneralTransformationRule rule)
        {
            var comp2 = computations.Where(cmp => cmp.TransformationRule == rule).OfType <Computation>().FirstOrDefault();

            if (comp2 == null)
            {
                comp2 = rule.CreateComputation(input, comp.Context);
                computations.Add(comp2);
                AddTraceEntry(comp2);
                dependantComputes.Push(comp2);
            }
            return(comp2);
        }
        private bool HandleNonDelayedPersistedDependencyInput(Computation computation, ITransformationContext context, IList list, MultipleResultAwaitingPersistor delayPersistor, GeneralTransformationRule dependent, object[] dependencyInput)
        {
            var needDelayedPersistor = false;
            var comp2 = context.CallTransformation(dependent, dependencyInput);

            if (!comp2.IsDelayed)
            {
                if (comp2.Output != null)
                {
                    var lockList = context.IsThreadSafe;
                    if (lockList)
                    {
                        lock (list)
                        {
                            list.Add(comp2.Output);
                        }
                    }
                    else
                    {
                        list.Add(comp2.Output);
                    }
                }
            }
            else
            {
                needDelayedPersistor = true;
                delayPersistor.WaitFor(comp2);
            }

            computation.MarkRequireInternal(comp2, ExecuteBefore, this);
            return(needDelayedPersistor);
        }
예제 #46
0
 /// <summary>
 /// Traces the computations of the specified inputs with the specified transformation rules
 /// </summary>
 /// <param name="rule">The transformation rules that transformed the specified inputs</param>
 /// <param name="inputs">A collection of input arguments</param>
 /// <returns>A collection of computations</returns>
 public override IEnumerable<ITraceEntry> TraceManyIn(GeneralTransformationRule rule, IEnumerable<object[]> inputs)
 {
     if (rule == null) throw new ArgumentNullException("rule");
     if (inputs == null) return Enumerable.Empty<ITraceEntry>();
     List<ITraceEntry> result = new List<ITraceEntry>();
     foreach (var input in inputs)
     {
         List<ITraceEntry> comps;
         if (computationsMade.TryGetValue(input, out comps))
         {
             result.AddRange(comps.Where(c => c.TransformationRule == rule));
         }
     }
     return result;
 }
예제 #47
0
 /// <summary>
 /// Traces all computations with any inputs that math the given filters with the specified transformation rule
 /// </summary>
 /// <param name="rule">The transformation rule</param>
 /// <returns>A collection with all computations made under these circumstances</returns>
 public override IEnumerable<ITraceEntry> TraceAllIn(GeneralTransformationRule rule)
 {
     if (rule == null) throw new ArgumentNullException("rule");
     List<ITraceEntry> comps;
     if (computationsByTransformationRule.TryGetValue(rule, out comps))
     {
         return comps.AsReadOnly();
     }
     else
     {
         return Enumerable.Empty<Computation>();
     }
 }
예제 #48
0
 private void AddChild(GeneralTransformationRule rule)
 {
     if (Children == null) Children = new List<GeneralTransformationRule>();
     Children.Add(rule);
 }
예제 #49
0
 protected ParallelComputationContext CreateComputationContext(GeneralTransformationRule rule)
 {
     var compCon = new ParallelComputationContext(this);
     compCon.DelayOutputAtLeast(rule.OutputDelayLevel);
     compCon.DelayTransformationAtLeast(rule.TransformationDelayLevel);
     return compCon;
 }
예제 #50
0
 /// <summary>
 /// Requires the given transformation rule
 /// </summary>
 /// <param name="rule">The transformation rule that should be required</param>
 /// <remarks>This version Always takes the input parameter as input for the dependent transformations. Thus, this method will throw an exception, if the types do not match</remarks>
 public void Call(GeneralTransformationRule rule)
 {
     if (rule == null) throw new ArgumentNullException("rule");
     if (rule.InputType.IsAssignableArrayFrom(InputType))
     {
         Depend(null, c => c.CreateInputArray(), rule, null, false, false);
     }
     else
     {
         throw new InvalidOperationException(Resources.ErrRequiresTransNoSelectorMustInherit);
     }
 }
예제 #51
0
 /// <summary>
 /// Marks the current transformation rule instantiating for the specified rule
 /// </summary>
 /// <param name="rule">The base transformation rule</param>
 public void MarkInstantiatingFor(GeneralTransformationRule rule)
 {
     if (rule == null) throw new ArgumentNullException("rule");
     if (rule.InputType.IsAssignableArrayFrom(InputType) && (rule.OutputType == OutputType || rule.OutputType.IsAssignableFrom(OutputType) || OutputType.IsInterface))
     {
         MarkInstantiatingFor(rule, null);
     }
     else
     {
         throw new InvalidOperationException(Resources.ErrMarkInstantiatingForMustInherit);
     }
 }
        private void HandleNonDelayedComputation(Computation computation, ITransformationContext context)
        {
            var output       = computation.Output;
            var inCollection = Selector(computation);

            if (inCollection != null)
            {
                if (Persistor != null)
                {
                    Type  listType = (typeof(List <>)).MakeGenericType(DependencyTransformation.OutputType);
                    IList list     = System.Activator.CreateInstance(listType) as IList;

                    MultipleResultAwaitingPersistor delayPersistor = new MultipleResultAwaitingPersistor()
                    {
                        List      = list,
                        Persistor = Persistor,
                        Target    = output
                    };
                    bool needDependencyPersistor        = false;
                    GeneralTransformationRule dependent = DependencyTransformation;
                    if (context.IsThreadSafe)
                    {
                        Parallel.ForEach(inCollection, dependencyInput =>
                        {
                            if (HandleNonDelayedPersistedDependencyInput(computation, context, list, delayPersistor, dependent, dependencyInput))
                            {
                                needDependencyPersistor = true;
                            }
                        });
                    }
                    else
                    {
                        foreach (var dependencyInput in inCollection)
                        {
                            if (HandleNonDelayedPersistedDependencyInput(computation, context, list, delayPersistor, dependent, dependencyInput))
                            {
                                needDependencyPersistor = true;
                            }
                        }
                    }
                    if (!needDependencyPersistor)
                    {
                        Persistor(output, list);
                    }
                }
                else
                {
                    GeneralTransformationRule dependent = DependencyTransformation;
                    if (context.IsThreadSafe)
                    {
                        Parallel.ForEach(inCollection, dependencyInput =>
                        {
                            var comp2 = context.CallTransformation(dependent, dependencyInput);
                            computation.MarkRequireInternal(comp2, ExecuteBefore, this);
                        });
                    }
                    else
                    {
                        foreach (var dependencyInput in inCollection)
                        {
                            var comp2 = context.CallTransformation(dependent, dependencyInput);
                            computation.MarkRequireInternal(comp2, ExecuteBefore, this);
                        }
                    }
                }
            }
        }
예제 #53
0
 /// <summary>
 /// Marks the current transformation rule instantiating for the specified rule
 /// </summary>
 /// <param name="rule">The base transformation rule</param>
 /// <param name="filter">A method that filters the possible computations</param>
 /// <remarks>Note that in this version, the filter method is also responsible for checking the types!</remarks>
 public void MarkInstantiatingFor(GeneralTransformationRule rule, Predicate<Computation> filter)
 {
     if (rule == null) throw new ArgumentNullException("rule");
     rule.AddChild(this);
     AddBase(rule, filter);
 }
예제 #54
0
 /// <summary>
 /// Calls the given transformation with the specified input
 /// </summary>
 /// <param name="context">The current transformation context</param>
 /// <param name="transformationRule">The rule that should be applied</param>
 /// <param name="input">The input for the transformation rule</param>
 /// <returns>The computation that handles this request</returns>
 public static Computation CallTransformation(this ITransformationContext context, GeneralTransformationRule transformationRule, params object[] input)
 {
     return(context.CallTransformation(transformationRule, input, null));
 }
예제 #55
0
 /// <summary>
 /// Creates a new mocked computation
 /// </summary>
 /// <param name="input">The input for the mocked computation</param>
 /// <param name="rule">The transformation rule for the mocked computation</param>
 /// <param name="context">The transformation context</param>
 /// <param name="output">The output for the transformation</param>
 public MockComputation(object[] input, GeneralTransformationRule rule, IComputationContext context, object output)
     : base(rule, context)
 {
     inputs = input;
     InitializeOutput(output);
 }
        internal ITransformationRuleDependency DependMany(Predicate <Computation> filter, Func <Computation, IEnumerable <object[]> > selector, GeneralTransformationRule transformation, Action <object, IEnumerable> persistor, bool executeBefore, bool needOutput)
        {
            if (transformation == null)
            {
                throw new ArgumentNullException("transformation");
            }
            if (selector == null)
            {
                throw new ArgumentNullException("selector");
            }

            var dependency = new MultipleDependency()
            {
                Filter                   = filter,
                Selector                 = selector,
                Persistor                = persistor,
                BaseTransformation       = this,
                DependencyTransformation = transformation,
                ExecuteBefore            = executeBefore,
                NeedOutput               = needOutput
            };

            Dependencies.Add(dependency);

            return(dependency);
        }
예제 #57
0
 private Computation FindOrCreateDependentComputation(object[] input, List<ITraceEntry> computations, Computation comp, Stack<Computation> dependantComputes, GeneralTransformationRule rule)
 {
     lock (computations)
     {
         var comp2 = computations.Where(cmp => cmp.TransformationRule == rule).OfType<Computation>().FirstOrDefault();
         if (comp2 == null)
         {
             comp2 = rule.CreateComputation(input, comp.Context);
             computations.Add(comp2);
             AddTraceEntry(comp2);
             dependantComputes.Push(comp2);
         }
         return comp2;
     }
 }