Ejemplo n.º 1
0
 /// <summary>
 /// Evaluate processors on given value
 /// </summary>
 /// <param name="valueToProcess"></param>
 /// <param name="configurationWithEventualProcessors"></param>
 /// <param name="fusionPath"></param>
 /// <param name="contextObject"></param>
 /// <returns></returns>
 protected object EvaluateProcessors(object valueToProcess, FusionAst configurationWithEventualProcessors, string fusionPath, AbstractFusionObject contextObject)
 {
     if (configurationWithEventualProcessors["__meta"]["processors"] != null)
     {
         var processorConfiguration = (FusionAst)configurationWithEventualProcessors["__meta"]["processors"].Clone();
         // TODO sorting
         var sortedKeys = processorConfiguration.Children.Keys.Select(x => x.ToString());
         foreach (var key in sortedKeys)
         {
             var processorPath = fusionPath + "/__meta/process/" + key;
             if (!EvaluateIfCondition(processorConfiguration[key], processorPath, contextObject))
             {
                 continue;
             }
             if (processorConfiguration[key].Children.ContainsKey("expression"))
             {
                 processorPath += "/expression";
             }
             PushContext("value", valueToProcess);
             var result = EvaluateInternal(processorPath, FailureBehavior.Exception, contextObject);
             if (GetLastEvaluationStatus() != EvaluationStatus.Skipped)
             {
                 valueToProcess = result;
             }
             PopContext();
         }
     }
     return(valueToProcess);
 }
Ejemplo n.º 2
0
 public void Merge(FusionAst other)
 {
     if (Value == null)
     {
         Value = other.Value;
     }
     if (EelExpression == null || EelExpression.Length == 0)
     {
         EelExpression = other.EelExpression;
     }
     if (ObjectType == null || ObjectType.Length == 0)
     {
         ObjectType = other.ObjectType;
     }
     foreach (var keyValue in other.Children)
     {
         if (Children.ContainsKey(keyValue.Key))
         {
             Children[keyValue.Key].Merge(keyValue.Value);
         }
         else
         {
             Children.Add(keyValue.Key, keyValue.Value);
         }
     }
 }
Ejemplo n.º 3
0
        private FusionAst MergePrototypesWithConfigurationForPathSegment(FusionAst configuration, Dictionary <string, FusionAst> currentPrototypeDefinitions)
        {
            var currentPathSegmentType = configuration.ObjectType;

            if (currentPrototypeDefinitions.ContainsKey(currentPathSegmentType))
            {
                var prototypeMergingOrder = new List <string>()
                {
                    currentPathSegmentType
                };
                if (currentPrototypeDefinitions[currentPathSegmentType]["__prototypeChain"].Value != null)
                {
                    prototypeMergingOrder.AddRange((string[])currentPrototypeDefinitions[currentPathSegmentType]["__prototypeChain"].Value);
                }
                var currentPrototypeWithInheritanceTakenIntoAccount = new FusionAst();
                foreach (var prototypeName in prototypeMergingOrder)
                {
                    if (!currentPrototypeDefinitions.ContainsKey(prototypeName))
                    {
                        throw new FusionException($"The Fusion object `{prototypeName}` which you tried to inherit from does not exist. Maybe you have a typo on the right hand side of your inheritance statement for {currentPathSegmentType}");
                    }
                    currentPrototypeWithInheritanceTakenIntoAccount.Merge(currentPrototypeDefinitions[prototypeName]);
                }
                configuration.Merge(currentPrototypeWithInheritanceTakenIntoAccount);
            }
            return(configuration);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Possibly prepares a new "@apply" context for the current fusionPath and pushes it to the stack.
        /// Returns true to express that new properties were puwhed and have to be popped during finalizePathEvaluation.
        ///
        /// Since "@apply" are not inherited every call of this method leads to a completely new "@apply" context,
        /// which is null by default
        /// </summary>
        /// <param name="fusionPath"></param>
        /// <param name="fusionConfiguration"></param>
        /// <returns></returns>
        private bool PrepareApplyValuesForFusionPath(string fusionPath, FusionAst fusionConfiguration)
        {
            var spreadValues = EvaluateApplyValues(fusionConfiguration, fusionPath);

            PushApplyValues(spreadValues);
            return(true);
        }
Ejemplo n.º 5
0
 protected void Initialize()
 {
     currentLineNumber        = 0;
     currentBlockCommentState = false;
     currentObjectPathStack   = new Stack <string>();
     objectTree = new FusionAst();
 }
Ejemplo n.º 6
0
 public void SetValue(string[] objectPathArray, object value)
 {
     if (objectPathArray.Length == 0)
     {
         this.Value = value;
     }
     else if (objectPathArray.Length == 1)
     {
         var currentKey = objectPathArray.Last();
         objectPathArray = objectPathArray.Take(objectPathArray.Length - 1).ToArray();
         if (Children.ContainsKey(currentKey) && value == null)
         {
             Children.Remove(currentKey);
         }
         else if (Children.ContainsKey(currentKey))
         {
             if (value is FusionAst)
             {
                 var subTree = value as FusionAst;
                 Children[currentKey].Value         = subTree.Value;
                 Children[currentKey].EelExpression = subTree.EelExpression;
                 Children[currentKey].ObjectType    = subTree.ObjectType;
                 foreach (var keyValue in subTree.Children)
                 {
                     Children[currentKey].Children.Add(keyValue.Key, keyValue.Value);
                 }
             }
         }
         else
         {
             FusionAst newValue;
             if (value is FusionAst)
             {
                 newValue = value as FusionAst;
             }
             else
             {
                 newValue = new FusionAst(this)
                 {
                     Value = value
                 };
             }
             Children.Add(currentKey, newValue);
         }
     }
     else
     {
         if (!Children.ContainsKey(objectPathArray[0]))
         {
             Children.Add(objectPathArray[0], new FusionAst(this));
         }
         Children[objectPathArray[0]].SetValue(objectPathArray.Skip(1).ToArray(), value);
     }
 }
Ejemplo n.º 7
0
        private FusionAst MatchCurrentPathPart(string pathPart, FusionAst previousConfiguration, Dictionary <string, FusionAst> currentPrototypeDefinitions)
        {
            Match matches = Regex.Match(pathPart, @"^([^<]*)(<(.*?)>)?$");

            if (!matches.Success)
            {
                throw new FusionException($"Path part `{pathPart}` not well-formed");
            }
            var currentPathSegment = matches.Groups[1].Value;
            var configuration      = new FusionAst();

            if (previousConfiguration.Children.ContainsKey(currentPathSegment))
            {
                configuration = (FusionAst)previousConfiguration[currentPathSegment].Clone();
            }
            if (configuration["__prototypes"] != null)
            {
                currentPrototypeDefinitions = new Dictionary <string, FusionAst>(currentPrototypeDefinitions);
                foreach (var kv in configuration["__prototypes"].Children)
                {
                    if (!currentPrototypeDefinitions.ContainsKey(kv.Key))
                    {
                        currentPrototypeDefinitions.Add(kv.Key, kv.Value);
                    }
                    else
                    {
                        var clone = (FusionAst)currentPrototypeDefinitions[kv.Key].Clone();
                        clone.Merge(kv.Value);
                        currentPrototypeDefinitions[kv.Key] = clone;
                    }
                }
            }
            string currentPathSegmentType = null;

            if (configuration.ObjectType.Length > 0)
            {
                currentPathSegmentType = configuration.ObjectType;
            }
            if (matches.Groups[3].Value.Length > 0)
            {
                currentPathSegmentType = matches.Groups[3].Value;
            }

            if (currentPathSegmentType != null)
            {
                configuration.ObjectType = currentPathSegmentType;
                configuration            = MergePrototypesWithConfigurationForPathSegment(configuration, currentPrototypeDefinitions);
            }
            if (!HasExpressionOrValue(configuration) && configuration.ObjectType.Length == 0 && configuration["__meta"]["class"] == null && configuration["__meta"]["process"] == null)
            {
                configuration.Value = "";
            }
            return(configuration);
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Internal evaluation if given configuration is renderable
 /// </summary>
 /// <param name="fusionConfiguration"></param>
 /// <returns></returns>
 protected bool CanRenderWithConfiguration(FusionAst fusionConfiguration)
 {
     if (HasExpressionOrValue(fusionConfiguration))
     {
         return(true);
     }
     if (fusionConfiguration["__meta"]["class"].Value != null && fusionConfiguration.ObjectType.Length > 0)
     {
         return(true);
     }
     return(false);
 }
Ejemplo n.º 9
0
        private object EvaluateExpressionOrValueInternal(string fusionPath, FusionAst fusionConfiguration, Cache.EvaluationContext cacheContext, AbstractFusionObject contextObject)
        {
            if (!EvaluateIfCondition(fusionConfiguration, fusionPath, contextObject))
            {
                FinalizePathEvaluation(cacheContext);
                return(null);
            }
            var evaluatedExpression = EvaluateEelExpressionOrSimpleValueWithProcessor(fusionPath, fusionConfiguration, contextObject);

            FinalizePathEvaluation(cacheContext);
            return(evaluatedExpression);
        }
Ejemplo n.º 10
0
        public object Clone()
        {
            var clone = new FusionAst();

            clone.Value         = Value;
            clone.EelExpression = EelExpression;
            clone.ObjectType    = ObjectType;
            foreach (var child in Children)
            {
                clone.Children.Add(child.Key, (FusionAst)child.Value.Clone());
            }
            return(clone);
        }
Ejemplo n.º 11
0
 private void ThrowExceptionForUnrenderablePathIfNeeded(string fusionPath, FusionAst fusionConfiguration, FailureBehavior behaviorIfPathNotFound)
 {
     // System.Console.WriteLine("Could not render at path " + fusionPath);
     if (!string.IsNullOrEmpty(fusionConfiguration.ObjectType))
     {
         var objectType = fusionConfiguration.ObjectType;
         throw new FusionException($"The fusion object at path \"{fusionPath}\" could not be rendered:\n\t\tThe fusion object `{objectType}` is not completely defined (missing property `@class`). Most likely you didn't inherit from a basic object.");
     }
     if (behaviorIfPathNotFound == FailureBehavior.Exception)
     {
         throw new FusionException($"No fusion object found in path \"{fusionPath}\"\n\t\tPlease make sure to define one in your Fusion configuration.");
     }
 }
Ejemplo n.º 12
0
        protected AbstractFusionObject InstantiateFusionObject(string fusionPath, FusionAst fusionConfiguration)
        {
            var fusionObjectType      = fusionConfiguration.ObjectType;
            var fusionObjectClassName = (string)fusionConfiguration["__meta"]["class"].Value;

            if (fusionObjectClassName != null)
            {
                fusionObjectClassName = fusionObjectClassName.Replace("\\", ".");
            }
            if (!Regex.IsMatch(fusionPath, "<[^>]*>$"))
            {
                fusionPath += $"<{fusionObjectType}>";
            }

            Type fusionObjectClassType;

            try
            {
                fusionObjectClassType = Type.GetType(fusionObjectClassName);
            }
            catch (Exception)
            {
                throw new FusionException($"The implementation class `{fusionObjectClassName}` defined for Fusion object of type `{fusionObjectType}` does not exist. Maybe a typo in the @class property");
            }

            AbstractFusionObject fusionObject;

            try
            {
                fusionObject = (AbstractFusionObject)Activator.CreateInstance(fusionObjectClassType, new object[] { this, fusionPath, fusionObjectType });
            }
            catch (Exception)
            {
                throw new FusionException($"Could not invoke fusion object implementation class `{fusionObjectClassName}` defined for Fusion object of type `{fusionObjectType}`");
            }
            if (!(fusionObject is AbstractFusionObject))
            {
                throw new FusionException($"Fusion object implementation class `{fusionObjectClassName}` defined for Fusion object of type `{fusionObjectType}` does not extends AbstractFusionObject");
            }
            if (IsArrayFusionObject(fusionObject))
            {
                if (fusionConfiguration["__meta"]["ignoreProperties"] != null)
                {
                    var evaluatedIgnores = Evaluate(fusionPath + "/__meta/ignoreProperties", fusionObject);
                    ((AbstractArrayFusionObject)fusionObject).SetIgnoreProperties(evaluatedIgnores is string[] ? (string[])evaluatedIgnores : new string[] { });
                }
                SetPropertiesOnFusionObject((AbstractArrayFusionObject)fusionObject, fusionConfiguration);
            }
            return(fusionObject);
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Evaluate eventually existing meta "@if" conditionals inside the given configuration and path
 /// </summary>
 /// <param name="configurationWithEventualIf"></param>
 /// <param name="configurationPath"></param>
 /// <param name="contextObject"></param>
 /// <returns></returns>
 protected Boolean EvaluateIfCondition(FusionAst configurationWithEventualIf, string configurationPath, AbstractFusionObject contextObject = null)
 {
     if (configurationWithEventualIf["__meta"]["if"] != null)
     {
         foreach (var child in configurationWithEventualIf["__meta"]["if"].Children)
         {
             var conditionValue = EvaluateInternal(configurationPath + "/__meta/if/" + child.Key, FailureBehavior.Exception, contextObject);
             if (!(bool)conditionValue)
             {
                 return(false);
             }
         }
     }
     return(true);
 }
Ejemplo n.º 14
0
        public Runtime(FusionAst configuration, RuntimeConfiguration settings = null)
        {
            this.configuration = configuration;
            var emptyContext = new Dictionary <string, object>();

            contextStack = new Stack <Dictionary <string, object> >()
            {
            };
            contextStack.Push(emptyContext);
            var emptyApplyValues = new Dictionary <string, KeyValuePair <string, object> >();

            applyValueStack = new Stack <Dictionary <string, KeyValuePair <string, object> > >();
            applyValueStack.Push(emptyApplyValues);
            this.settings            = settings ?? new RuntimeConfiguration();
            exceptionHandlerFactory  = new ExceptionHandlerFactory();
            this.runtimeContentCache = new Cache.RuntimeContentCache(this);
        }
Ejemplo n.º 15
0
        protected FusionAst GetConfigurationForPath(string fusionPath)
        {
            var pathParts     = fusionPath.Split('/');
            var configuration = this.configuration;

            var pathUntilNow = "";
            Dictionary <string, FusionAst> currentPrototypeDefinitions = new Dictionary <string, FusionAst>();

            if (configuration["__prototypes"] != null)
            {
                currentPrototypeDefinitions = ((FusionAst)configuration["__prototypes"]).Children;
            }
            foreach (var pathPart in pathParts)
            {
                pathUntilNow += "/" + pathPart;
                // cache
                configuration = MatchCurrentPathPart(pathPart, configuration, currentPrototypeDefinitions);
            }
            return(configuration);
        }
Ejemplo n.º 16
0
 public FusionAst(FusionAst parent)
 {
     this.Children = new Dictionary <string, FusionAst>();
     this.Parent   = parent;
 }
Ejemplo n.º 17
0
        /// <summary>
        /// Evaluate "@apply" for the given fusion key.
        ///
        /// If apply-definitions are found they are evaluated and the returned keys are combined.
        /// The result is returnd as dict with the following structure:
        ///
        /// <pre>
        /// {
        ///     { "fuisonPath/key_1", { Key: "key_1", Value: "evaluated value 1"} },
        ///     { "fuisonPath/key_2", { Key: "key_2", Value: "evaluated value 2"} },
        /// }
        /// </pre>
        /// </summary>
        /// <param name="configurationWithEventualProperties"></param>
        /// <param name="fusionPath"></param>
        /// <returns></returns>
        private Dictionary <string, KeyValuePair <string, object> > EvaluateApplyValues(FusionAst configurationWithEventualProperties, string fusionPath)
        {
            var result = new Dictionary <string, KeyValuePair <string, object> >();

            if (!configurationWithEventualProperties["__meta"]["apply"].Equals(null))
            {
                var fusionObjectType = configurationWithEventualProperties.ObjectType;
                if (!Regex.IsMatch(fusionPath, @"<[^>]*>$"))
                {
                    fusionPath += $"<{fusionObjectType}>";
                }
                var propertiesConfiguration = configurationWithEventualProperties["__meta"]["apply"];
                // TODO sort
                var sortedKeys = propertiesConfiguration.Children.Keys.Select(x => x.ToString());
                foreach (var key in sortedKeys)
                {
                    if (key[0] == '_' && key[1] == '_' && Parser.ReservedKeys.Contains(key))
                    {
                        continue;
                    }
                    var singleAppyPath = fusionPath + "/__meta/apply/" + key;
                    if (!EvaluateIfCondition(propertiesConfiguration[key], singleAppyPath))
                    {
                        continue;
                    }
                    if (propertiesConfiguration.Children.ContainsKey("expression"))
                    {
                        singleAppyPath += "/expression";
                    }
                    var singleApplyValues = EvaluateInternal(singleAppyPath, FailureBehavior.Exception);
                    if (GetLastEvaluationStatus() != EvaluationStatus.Skipped && singleApplyValues is System.Collections.IDictionary)
                    {
                        foreach (KeyValuePair <string, object> kvp in (System.Collections.IDictionary)singleApplyValues)
                        {
                            if (kvp.Key[0] == '_' && kvp.Key[1] == '_' && Parser.ReservedKeys.Contains(kvp.Key))
                            {
                                continue;
                            }
                            result[fusionPath + '/' + kvp.Key] = kvp;
                        }
                    }
                }
            }
            return(result);
        }
Ejemplo n.º 18
0
        protected void SetPropertiesOnFusionObject(AbstractArrayFusionObject fusionObject, FusionAst fusionConfiguration)
        {
            var propertiesProperty = fusionObject
                                     .GetType()
                                     .GetField("properties", BindingFlags.Instance | BindingFlags.NonPublic);

            if (propertiesProperty != null)
            {
                propertiesProperty.SetValue(
                    fusionObject,
                    fusionConfiguration.Children.Keys
                    .Select(k => k.ToString())
                    .Where(k => !Parser.ReservedKeys.Contains(k))
                    .ToArray()
                    );
            }
            else
            {
                System.Console.WriteLine("no properties property");
                System.Console.WriteLine(fusionObject.GetType());
                System.Console.WriteLine(fusionObject.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic).Length);
            }
            // handle apply
        }
Ejemplo n.º 19
0
 /// <summary>
 /// Checks if the current fusionAst hold an Eel expression or a simple value.
 /// </summary>
 /// <param name="fusionConfiguration"></param>
 /// <returns></returns>
 private bool HasExpressionOrValue(FusionAst fusionConfiguration)
 {
     return(!string.IsNullOrEmpty(fusionConfiguration.EelExpression) || fusionConfiguration.Value != null);
 }
Ejemplo n.º 20
0
        private object EvaluateEelExpressionOrSimpleValueWithProcessor(string fusionPath, FusionAst valueConfiguration, AbstractFusionObject contextObject)
        {
            object evaluatedValue;

            if (valueConfiguration.EelExpression.Length > 0)
            {
                evaluatedValue = EvaluateEelExpression(valueConfiguration.EelExpression, contextObject);
            }
            else
            {
                evaluatedValue = valueConfiguration.Value;
            }
            evaluatedValue = EvaluateProcessors(evaluatedValue, valueConfiguration, fusionPath, contextObject);
            return(evaluatedValue);
        }
Ejemplo n.º 21
0
        private object EvaluateObjectOrRetrieveFromCache(AbstractFusionObject fusionObject, string fusionPath, FusionAst fusionConfiguration, Cache.EvaluationContext cacheContext)
        {
            object output           = null;
            var    evaluateObject   = true;
            var    evaluationStatus = EvaluationStatus.Skipped;

            if (runtimeContentCache.preEvaluate(cacheContext, fusionObject, out object cachedResult))
            {
                return(cachedResult);
            }
            if (!EvaluateIfCondition(fusionConfiguration, fusionPath, fusionObject))
            {
                evaluateObject = false;
            }
            if (evaluateObject)
            {
                output           = fusionObject.Evaluate();
                evaluationStatus = EvaluationStatus.Executed;
            }
            lastEvaluationStatus = evaluationStatus;
            if (evaluateObject)
            {
                output = EvaluateProcessors(output, fusionConfiguration, fusionPath, fusionObject);
            }
            // TODO
            // runtimeContentCache.postProcess(cacheContext, fusionObject, output);
            return(output);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Possibly prepares a new context for the current FusionObject and cache context and pushes it to the stack.
        /// Returns if a new context was pushed to the stack or not.
        /// </summary>
        /// <param name="fusionObject"></param>
        /// <param name="fusionPath"></param>
        /// <param name="fusionConfiguration"></param>
        /// <param name="cacheContext"></param>
        /// <returns></returns>
        private bool PrepareContextForFusionObject(AbstractFusionObject fusionObject, string fusionPath, FusionAst fusionConfiguration, object cacheContext)
        {
            var contextArray    = GetCurrentContext();
            var newContextArray = new Dictionary <string, object>(contextArray);

            if (fusionConfiguration["__meta"]["context"] != null)
            {
                foreach (var context in fusionConfiguration["__meta"]["context"].Children)
                {
                    var contextValue = EvaluateInternal(fusionPath + "/__meta/context/" + context.Key, FailureBehavior.Exception, fusionObject);
                    newContextArray.Add(context.Key, contextValue);
                }
                PushContextArray(newContextArray);
                return(true);
            }
            return(false);
        }