/// <summary>
        /// Evaluate a formula
        /// </summary>
        /// <param name="formulaValue">
        /// The formula value
        /// </param>
        /// <param name="precision">
        /// The precision.
        /// </param>
        /// <param name="rounding">
        /// The rounding.
        /// </param>
        /// <param name="resultType">
        /// The intended result type TypeCode
        /// </param>
        /// <param name="replaceNull">
        /// If set to true, the value returned will be replaced with the default value.
        /// </param>
        /// <exception cref="InvalidEnumArgumentException">
        /// If the intended result type is not supported. 
        /// </exception>
        /// <returns>
        /// object as the evaluated result
        /// </returns>
        public object EvaluateFormula(string formulaValue, int precision, string rounding, TypeCode resultType,
                                      bool replaceNull)
        {
            object evaluatedFormula;
            var formulaBuilder = new FormulaBuilder();
            formulaBuilder.SetFormulaComponentsFromSerialisedFormula(formulaValue);
            List<FormulaComponentBase> components = formulaBuilder.FormulaComponents;

            switch (resultType)
            {
                case TypeCode.String:
                    evaluatedFormula = this.evaluatorEngine.Evaluate<string>(components);
                    break;
                case TypeCode.Int16:
                case TypeCode.Int32:
                    evaluatedFormula = this.evaluatorEngine.Evaluate<int?>(components);
                    break;
                case TypeCode.Double:
                    var actualCalcResult = this.evaluatorEngine.Evaluate<double?>(components);
                    evaluatedFormula = actualCalcResult != null 
                                        && !double.IsNaN(actualCalcResult.Value)
                                           ? RoundResult(actualCalcResult, rounding, precision)
                                           : null;
                    break;
                case TypeCode.DateTime:
                    evaluatedFormula = this.evaluatorEngine.Evaluate<DateTime?>(components);
                    break;
                case TypeCode.Boolean:
                    evaluatedFormula = this.evaluatorEngine.Evaluate<bool?>(components);
                    break;
                default:
                    throw new InvalidEnumArgumentException(
                        Resource.EvaluationHelper_EvaluateFormula_InvalidEnumArgumentException_resultType);
            }

            if (evaluatedFormula == null && replaceNull)
            {
                evaluatedFormula = GetDefaultValue(resultType, true);
            }

            return evaluatedFormula;
        }
 /// <summary>
 /// Replace Date Components in a given MetaDataFormula formula
 /// </summary>
 /// <param name="formula">The formula which needs to have its date components replaced with text component</param>
 /// <returns>MetaDataFormula object after replacing all Date components with Text components</returns>
 public MetaDataFormula ReplaceDateCompWithTextComp(MetaDataFormula formula)
 {
     var builder = new FormulaBuilder();
     builder.SetFormulaComponentsFromSerialisedFormula(formula.Formula);
     List<FormulaComponentBase> componentsList = ReplaceDateCompWithTextComp(builder.FormulaComponents);
     builder.FormulaComponents.Clear();
     builder.FormulaComponents.AddRange(componentsList);
     formula.Formula = builder.Formula;
     return formula;
 }
 /// <summary>
 /// Retrieves all the LookupFormulaComponents contained within the specified FormulaComponentBase List.
 /// </summary>
 /// <param name="metaDataFormula">
 /// The Formula to search
 /// </param>
 /// <returns>
 /// All LookupFormulaComponents found.
 /// </returns>
 public List<LookupFormulaComponent> FindLookupFormulaComponents(MetaDataFormula metaDataFormula)
 {
     var formulaBuilder = new FormulaBuilder();
     formulaBuilder.SetFormulaComponentsFromSerialisedFormula(metaDataFormula.Formula);
     return FormulaComponentProcessor.FindLookupFormulaComponents(formulaBuilder.FormulaComponents);
 }
 /// <summary>
 /// Matches LookupFormulaComponents in the specified components and lookupValues Key
 /// and substitutes in the relevant primitive FormulaComponent
 /// </summary>
 /// <param name="metaDataFormula">
 /// The Formula to search
 /// </param>
 /// <param name="lookupValues">The dictionary containing the resolved values.</param>
 /// <returns>The altered formula.</returns>
 public MetaDataFormula ReplaceLookupFormulaComponents(MetaDataFormula metaDataFormula,
                                                       Dictionary<LookupFormulaComponent, object> lookupValues)
 {
     var formulabuilder = new FormulaBuilder();
     formulabuilder.SetFormulaComponentsFromSerialisedFormula(metaDataFormula.Formula);
     var amendedFormulaComponents = new List<FormulaComponentBase>();
     amendedFormulaComponents.AddRange(
         FormulaComponentProcessor.ReplaceLookupFormulaComponents(formulabuilder.FormulaComponents, lookupValues));
     formulabuilder.FormulaComponents.Clear();
     formulabuilder.FormulaComponents.AddRange(amendedFormulaComponents);
     metaDataFormula.Formula = formulabuilder.Formula;
     return metaDataFormula;
 }
 /// <summary>
 /// Given a list of FQNs and their values this will replace the fqn formula components
 /// with primitive components containing the values provided.
 /// </summary>
 /// <param name="formula">
 /// The Target Formula.
 /// </param>
 /// <param name="fqnValues">
 /// The dictionary containing the resolved values.
 /// </param>
 /// <returns>
 /// MetaDataFormula instance with the formula updated
 /// </returns>
 public MetaDataFormula ReplaceFqnFormulaComponents(
     MetaDataFormula formula, Dictionary<FqnFormulaComponent, object> fqnValues)
 {
     var fb = new FormulaBuilder();
     fb.SetFormulaComponentsFromSerialisedFormula(formula.Formula);
     var newCmpList = new List<FormulaComponentBase>();
     newCmpList.AddRange(FormulaComponentProcessor.ReplaceFqnFormulaComponents(fb.FormulaComponents, fqnValues));
     fb.FormulaComponents.Clear();
     fb.FormulaComponents.AddRange(newCmpList);
     formula.Formula = fb.Formula;
     return formula;
 }