示例#1
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());
        }
        /// <summary>
        /// Creates a computation mock for the given transformation rule with the given input and the given context and adds the computation to the context
        /// </summary>
        /// <param name="transformationRule">The transformation rule for this computation mock</param>
        /// <param name="input">The input for this computation</param>
        /// <returns>The computation mock</returns>
        public MockComputation Add(GeneralTransformationRule transformationRule, object[] input)
        {
            var c = new MockComputation(input, transformationRule, CreateComputationContext());

            Add(c);
            return(c);
        }
        public MockComputation Add <TIn>(GeneralTransformationRule <TIn> transformationRule, TIn input)
            where TIn : class
        {
            var c = new MockComputation(new object[] { input }, transformationRule, CreateComputationContext());

            Add(c);
            return(c);
        }
示例#4
0
        protected TaskParallelComputationContext CreateComputationContext(GeneralTransformationRule rule)
        {
            var compCon = new TaskParallelComputationContext(this);

            compCon.DelayOutputAtLeast(rule.OutputDelayLevel);
            compCon.DelayTransformationAtLeast(rule.TransformationDelayLevel);
            return(compCon);
        }
        public MockComputation Add <TIn1, TIn2>(GeneralTransformationRule <TIn1, TIn2> transformationRule, TIn1 input1, TIn2 input2)
            where TIn1 : class
            where TIn2 : class
        {
            var c = new MockComputation(new object[] { input1, input2 }, transformationRule, CreateComputationContext());

            Add(c);
            return(c);
        }
示例#6
0
        public static TRule SyncRule <TRule>(this GeneralTransformationRule rule) where TRule : class
        {
            var synchronization = rule.Transformation as Synchronization;

            if (synchronization != null)
            {
                return(synchronization.GetSynchronizationRuleForType(typeof(TRule)) as TRule);
            }
            return(null);
        }
示例#7
0
 private static void CheckTransformationRule <TOut>(object[] input, GeneralTransformationRule startRule) where TOut : class
 {
     if (!(startRule is TransformationRuleBase <TOut>) && !startRule.OutputType.IsAssignableFrom(typeof(TOut)))
     {
         throw new InvalidOperationException("The output type of the specified start rule does not match the expected result type! Please provide a different start rule.");
     }
     if (!startRule.InputType.IsInstanceArrayOfType(input))
     {
         throw new InvalidOperationException("The input parameter types of the specified start rule do not match the given inputs. Please choose a different start rule.");
     }
 }
示例#8
0
        /// <summary>
        /// Trace the output of the computation that transformed the given input with the given transformation type
        /// </summary>
        /// <param name="rule">The rule that transformed the argument</param>
        /// <param name="input">The input arguments</param>
        /// <param name="trace">The trace component that is used as basis</param>
        /// <returns>The output of the computation with the specified input argument or null, if there is none such</returns>
        public static object ResolveIn(this ITransformationTrace trace, GeneralTransformationRule rule, object[] input)
        {
            if (trace == null)
            {
                throw new ArgumentNullException("trace");
            }

            var comp = trace.TraceIn(rule, input).FirstOrDefault();

            return(comp != null ? comp.Output : null);
        }
示例#9
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>());
            }
示例#10
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>
        /// <returns>The computation that handles this request</returns>
        public virtual Computation CallTransformation(GeneralTransformationRule transformationRule, object[] input, IEnumerable context)
        {
            if (transformationRule == null)
            {
                throw new ArgumentNullException("transformationRule");
            }

            var c = Trace.TraceIn(transformationRule, input).OfType <Computation>().FirstOrDefault();

            if (c == null)
            {
                c = transformationRule.CreateComputation(input, new ComputationContext(this));
                computations.Add(c);
            }
            return(c);
        }
示例#11
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>());
                }
            }
示例#12
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;
                }
            }
        }
示例#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 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);
            }
 /// <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.IsAssignableFrom(OutputType))
     {
         if (filter != null)
         {
             MarkInstantiatingFor(rule, (Computation c) => HasCompliantInput(c) && filter(c.CreateInputArray()));
         }
         else
         {
             MarkInstantiatingFor(rule);
         }
     }
     else
     {
         throw new InvalidOperationException(Resources.ErrMarkInstantiatingMustInherit);
     }
 }
 /// <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);
     }
 }
示例#16
0
 public RelationalPatternContext(INotifyEnumerable <TIn> relationalSource, GeneralTransformationRule <TIn> targetRule, ITransformationContext context)
 {
     this.Source     = relationalSource;
     this.Context    = context;
     this.TargetRule = targetRule;
 }
示例#17
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]);
                }
            }
        }
示例#18
0
 protected virtual string CreateId(object[] input, GeneralTransformationRule rule)
 {
     counter++;
     return("node" + counter.ToString());
 }
示例#19
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);
        }
 protected override ComputationContext CreateComputationContext(object[] input, GeneralTransformationRule rule)
 {
     return(new TaskParallelComputationContext(this));
 }
示例#21
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);
     }
 }
示例#22
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>();
                if (!computationsMade.TryAdd(input, computations))
                {
                    computations = computationsMade[input];
                }
            }

            var originalTransformationRule = transformationRule;

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

            Computation comp;
            TaskParallelComputationContext 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);
        }
示例#23
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;
 }
示例#24
0
        public static void ProcessMany <TIn>(IEnumerable <TIn> inputs, ITransformationEngineContext context, GeneralTransformationRule <TIn> startRule)
            where TIn : class
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            var transformation = context.Transformation;

            if (!transformation.IsInitialized)
            {
                transformation.Initialize();
            }
            if (startRule == null)
            {
                startRule = context.Transformation.GetRulesForInputTypes(new Type[] { typeof(TIn) }).FirstOrDefault() as GeneralTransformationRule <TIn>;
            }
            else
            {
                if (startRule.Transformation != context.Transformation)
                {
                    ThrowRuleNotPartOfTransformation();
                }
            }
            TransformationRunner.TransformMany(inputs.Select(item => new object[] { item }), null, startRule, context);
        }
示例#25
0
        /// <summary>
        /// Transforms the input argument into an output using the provided transformation
        /// </summary>
        /// <typeparam name="TOut">The desired output type</typeparam>
        /// <param name="inputs">The input parameters</param>
        /// <param name="types">The types of the elements within the collection refered to in the inputs parameter</param>
        /// <param name="startRule">The rule that should be started with. If this is null, an applicable rule is found.</param>
        /// <param name="context">The context that should be used (must not be null).</param>
        /// <returns>The output from the transformation</returns>
        public static IEnumerable <TOut> TransformMany <TOut>(IEnumerable <object[]> inputs, Type[] types, ITransformationEngineContext context, GeneralTransformationRule startRule)
            where TOut : class
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (types == null)
            {
                throw new ArgumentNullException("types");
            }
            var transformation = context.Transformation;

            if (!transformation.IsInitialized)
            {
                transformation.Initialize();
            }
            if (startRule == null)
            {
                startRule = context.Transformation.GetRuleForTypeSignature(types, typeof(TOut));
            }
            else
            {
                if (startRule.Transformation != context.Transformation)
                {
                    ThrowRuleNotPartOfTransformation();
                }
            }
            return(TransformationRunner.TransformMany(inputs.Select(item => new object[] { item }), null, startRule, context).Select(c => c.Output).OfType <TOut>());
        }
示例#26
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>
 /// <returns>The computation that handles this request</returns>
 public Computation CallTransformation(GeneralTransformationRule transformationRule, object[] input)
 {
     return(CallTransformation(transformationRule, null, input));
 }
示例#27
0
        public static void Process <TIn1, TIn2>(TIn1 input1, TIn2 input2, ITransformationEngineContext context, GeneralTransformationRule <TIn1, TIn2> startRule)
            where TIn1 : class
            where TIn2 : class
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            var transformation = context.Transformation;

            if (!transformation.IsInitialized)
            {
                transformation.Initialize();
            }
            if (startRule == null)
            {
                startRule = context.Transformation.GetRulesForInputTypes(new Type[] { typeof(TIn1), typeof(TIn2) }).FirstOrDefault() as GeneralTransformationRule <TIn1, TIn2>;
            }
            else
            {
                if (startRule.Transformation != context.Transformation)
                {
                    ThrowRuleNotPartOfTransformation();
                }
            }
            TransformationRunner.Transform(new object[] { input1, input2 }, null, startRule, context);
        }
示例#28
0
 /// <summary>
 /// Calls the given transformation with the specified input
 /// </summary>
 /// <typeparam name="TIn">The type of the first input parameter</typeparam>
 /// <param name="input">The input for the transformation rule</param>
 /// <param name="transformationRule">The rule that should be applied</param>
 /// <returns>The computation that handles this request</returns>
 public Computation CallTransformation <TIn>(GeneralTransformationRule <TIn> transformationRule, TIn input)
     where TIn : class
 {
     return(CallTransformation(transformationRule, null, new object[] { input }));
 }
示例#29
0
        /// <summary>
        /// Transforms the input argument into an output using the provided transformation
        /// </summary>
        /// <typeparam name="TOut">The desired output type</typeparam>
        /// <param name="input">The input parameter</param>
        /// <param name="startRule">The rule that should be started with. If this is null, an applicable rule is found.</param>
        /// <param name="context">The context that should be used (must not be null).</param>
        /// <returns>The output from the transformation</returns>
        public static TOut Transform <TOut>(object[] input, ITransformationEngineContext context, GeneralTransformationRule startRule)
            where TOut : class
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            var transformation = context.Transformation;

            if (!transformation.IsInitialized)
            {
                transformation.Initialize();
            }
            if (startRule == null)
            {
                startRule = context.Transformation.GetRuleForTypeSignature(input.GetTypes(), typeof(TOut));
            }
            else
            {
                if (startRule.Transformation != context.Transformation)
                {
                    ThrowRuleNotPartOfTransformation();
                }
                CheckTransformationRule <TOut>(input, startRule);
            }
            return(TransformationRunner.Transform(input, null, startRule, context).Output as TOut);
        }
示例#30
0
 /// <summary>
 /// Calls the given transformation with the specified input
 /// </summary>
 /// <typeparam name="TIn1">The type of the first input parameter</typeparam>
 /// <typeparam name="TIn2">The type of the second input parameter</typeparam>
 /// <param name="input1">The first input for the transformation rule</param>
 /// <param name="input2">The second input for the transformation rule</param>
 /// <param name="transformationRule">The rule that should be applied</param>
 /// <returns>The computation that handles this request</returns>
 public Computation CallTransformation <TIn1, TIn2>(GeneralTransformationRule <TIn1, TIn2> transformationRule, TIn1 input1, TIn2 input2)
     where TIn1 : class
     where TIn2 : class
 {
     return(CallTransformation(transformationRule, null, new object[] { input1, input2 }));
 }