//Public Methods
        public IEvalResult[] EvalExpression(ref ConfiguratorSession configSession, string DatabindExpression)
        {
            try
            {
                if (!String.IsNullOrEmpty(DatabindExpression))
                {
                    ParserStatement rootStatement = ParseString(ref configSession, DatabindExpression);
                    return rootStatement.Eval();
                }
            }
            catch (ElementNotFoundException ex)
            {
            }
            catch (NullReferenceException ex)
            {
            }

            return null;
        }
        public JsonNetResult ValidateCustomRuleSyntax(int modelID, string customRule)
        {
            var sp = new StandardParser();
            var cs = new ConfiguratorSession(null, null, null);

            try
            {
                sp.ParseString(ref cs, customRule);
            }
            catch
            {
                return new JsonNetResult { Data = false };
            }

            return new JsonNetResult { Data = true };
        }
        //Private methods
        private bool VerifyAssumption(ConfiguratorSession configSession, string featureVarID, bool value)
        {
            //Add a new assumption to test for the "valueToTest" value
            bool assumptionValid = false;
            configSession.Context.AddValueAssumption(featureVarID, VariableDataTypes.Boolean, value);
            assumptionValid = configSession.Context.IsValid();

            //Clean up and return the value
            configSession.Context.RemoveValueAssumption(featureVarID);
            return assumptionValid;
        }
        private bool ApplyFeedbackAlgorithm(ref ConfiguratorSession configSession)
        {
            //Variables
            bool validity = true;

            //Loop through all FeatureSelections
            foreach (BLL.BusinessObjects.FeatureSelection fSelection in configSession.Configuration.FeatureSelections)
            {
                //Determine the state of each Feature - so as to keep the validity of the configuration
                if (fSelection.ToggledByUser == false)
                {
                    Feature feature = configSession.Model.GetFeatureByID(fSelection.FeatureID);
                    bool CanBeTrue = VerifyAssumption(configSession, feature.SlvMapIdentifier, true);
                    bool CanBeFalse = VerifyAssumption(configSession, feature.SlvMapIdentifier, false);

                    //Feature cannot be false nor true - configuration INVALID
                    if (!CanBeFalse && !CanBeTrue)
                    {
                        validity = false;
                    }
                    //Feature has to be false - disable and DESELECT
                    else if (!CanBeTrue)
                    {
                        fSelection.SelectionState = BusinessObjects.FeatureSelectionStates.Deselected;
                        fSelection.Disabled = true;
                    }
                    //Feature has to be true - disable and SELECT
                    else if (!CanBeFalse)
                    {
                        fSelection.SelectionState = BusinessObjects.FeatureSelectionStates.Selected;
                        fSelection.Disabled = true;
                    }
                    //Feature can be anything - enable and UNSELECT
                    else if (CanBeFalse && CanBeTrue)
                    {
                        fSelection.SelectionState = BusinessObjects.FeatureSelectionStates.Unselected;
                        fSelection.Disabled = false;
                    }
                }
            }

            //
            return validity;
        }
        public void UserToggleFeature(ref ConfiguratorSession configSession, int featureID, BLL.BusinessObjects.FeatureSelectionStates newState)
        {
            //Modify the selection state of the FeatureSelection matching the given featureID
            FeatureSelection fSelection = configSession.Configuration.GetFeatureSelectionByFeatureID(featureID);
            Feature feature = configSession.Model.GetFeatureByID(featureID);

            switch (newState)
            {
                //Assert-decision  :Selected
                case BusinessObjects.FeatureSelectionStates.Selected:
                    configSession.Context.AddOrModifyValueAssumption(feature.SlvMapIdentifier, VariableDataTypes.Boolean, true);
                    fSelection.SelectionState = BusinessObjects.FeatureSelectionStates.Selected;
                    fSelection.ToggledByUser = true;
                    break;

                //Assert-decision  :Deselected
                case BusinessObjects.FeatureSelectionStates.Deselected:
                    configSession.Context.AddOrModifyValueAssumption(feature.SlvMapIdentifier, VariableDataTypes.Boolean, false);
                    fSelection.SelectionState = BusinessObjects.FeatureSelectionStates.Deselected;
                    fSelection.ToggledByUser = true;
                    break;

                //Retract-decision  :Unselected
                case BusinessObjects.FeatureSelectionStates.Unselected:
                    configSession.Context.RemoveValueAssumption(feature.SlvMapIdentifier);
                    fSelection.SelectionState = BusinessObjects.FeatureSelectionStates.Unselected;
                    fSelection.ToggledByUser = false;
                    break;
            }

            //Call feedback algorithm
            bool decisionIsValid = ApplyFeedbackAlgorithm(ref configSession);
        }
        public object EvalExpression(ref ConfiguratorSession configSession, string expression)
        {
            //Variables
            List<object> resultSet = new List<object>();

            //Evaluate the expression
            IEvalResult[] expResult = _databindParser.EvalExpression(ref configSession, expression);
            if (expResult != null)
            {
                expResult.ToList().ForEach(returnResult =>
                {
                    object obj = returnResult.GetGenericReturnValue();
                    var resultEntry = new
                    {
                        BusinessObject = obj,
                        Type = obj.GetType().Name
                    };

                    resultSet.Add(resultEntry);
                });
            }

            //
            return resultSet;
        }
        private ParserStatement ParseString(ref ConfiguratorSession configSession, string str)
        {
            // trim before the identification, allowing spaces in the code
            str = str.Trim();

            // Identify the string and creating a corresponding ParserStatement
            Type StatementType = IdentifyString(str);
            ParserStatement instance = (ParserStatement)ExecuteStaticMethod(StatementType, "CreateInstance", (object)StatementType, configSession, (object)str);

            string[] subStrings = null;

            // if defined, split using the Split method
            var splitResult = ExecuteStaticMethod(StatementType, "Split", str);
            if (splitResult != null)
            {
                subStrings = (string[])splitResult;
            }
            else
            // else use the regex to split
            {
                var splitRegex = (string)GetStaticField(StatementType, "SplitRegex");
                if (splitRegex != null)
                {
                    // split the regex and only take none empty elements
                    subStrings = Regex.Split(str, splitRegex).Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
                }
            }

            // if the string was split, then parse inner statements and add them to the parent
            if (subStrings != null)
                foreach (string subString in subStrings)
                {
                    ParserStatement innerStatement = ParseString(ref configSession, subString);
                    instance.AddInnerStatement(innerStatement);
                }

            return instance;
        }
        public JsonNetResult LoadData(int configurationID)
        {
            //Data return wrapper
            JsonNetResult result = new JsonNetResult() { };

            //Load Configuration
            ConfigurationService _configurationService = new ConfigurationService(SessionData.LoggedInUser.ID);
            BLL.BusinessObjects.Configuration configuration = _configurationService.GetByID(configurationID);

            //Load Model
            ModelService _modelService = new ModelService(SessionData.LoggedInUser.ID);
            BLL.BusinessObjects.Model model = _modelService.GetByID(configuration.ModelID);

            //Load UITemplate
            UITemplateService _uiTemplatesService = new UITemplateService(SessionData.LoggedInUser.ID);
            BLL.BusinessObjects.UITemplate template = _uiTemplatesService.GetByID(configuration.UITemplateID);

            //Initialize the ConfiguratorSession
            ConfiguratorSession newSession = new ConfiguratorSession(model, configuration, SolverService.CreateNewContext(model));
            SetupFeatureSelections(ref newSession);
            SessionData.ConfiguratorSessions[configurationID] = newSession;

            //Return the data
            var innerObj = new
            {
                ConfigurationObj = configuration,
                ModelObj = model,
                TemplateObj = template
            };
            result.Data = innerObj;
            return result;
        }
        //Private methods
        private void SetupFeatureSelections(ref ConfiguratorSession configSession)
        {
            //Setup FeatureSelections----------------------------------------------------------------------------------------------------------------------------------
            //Create FeatureSelections for the first time
            if (configSession.Configuration.FeatureSelections.Count == 0)
            {
                //Create one instance for each Feature in the Model
                foreach (BLL.BusinessObjects.Feature feature in configSession.Model.Features)
                {
                    BLL.BusinessObjects.FeatureSelection newFeatureSelection = BLL.BusinessObjects.FeatureSelection.CreateDefault();
                    newFeatureSelection.FeatureID = feature.ID;
                    configSession.Configuration.FeatureSelections.Add(newFeatureSelection);

                    //Create default AttributeValues
                    foreach (BLL.BusinessObjects.Attribute attribute in feature.Attributes)
                    {
                        BLL.BusinessObjects.AttributeValue attrValue = BLL.BusinessObjects.AttributeValue.CreateDefault();
                        attrValue.Value = GetDefaultAttrVal(attribute.AttributeDataType);
                        attrValue.AttributeID = attribute.ID;
                        if (attribute.AttributeType == BLL.BusinessObjects.AttributeTypes.Constant)
                        {
                            attrValue.Value = attribute.ConstantValue;
                        }
                        newFeatureSelection.AttributeValues.Add(attrValue);
                    }
                }
            }
            //Create new FeatureSelections ONLY for newly created Features
            else if (configSession.Configuration.FeatureSelections.Count < configSession.Model.Features.Count)
            {
                //Create one instance for each Feature that is missing a FeatureSelection
                foreach (BLL.BusinessObjects.Feature feature in configSession.Model.Features)
                {
                    if (configSession.Configuration.FeatureSelections.FirstOrDefault(k => k.FeatureID == feature.ID) == null) //If the Feature has no corresponding FeatureSelection
                    {
                        BLL.BusinessObjects.FeatureSelection newFeatureSelection = BLL.BusinessObjects.FeatureSelection.CreateDefault();
                        newFeatureSelection.FeatureID = feature.ID;
                        configSession.Configuration.FeatureSelections.Add(newFeatureSelection);

                        //Create default AttributeValues
                        foreach (BLL.BusinessObjects.Attribute attribute in feature.Attributes)
                        {
                            BLL.BusinessObjects.AttributeValue attrValue = BLL.BusinessObjects.AttributeValue.CreateDefault();
                            attrValue.Value = GetDefaultAttrVal(attribute.AttributeDataType);
                            attrValue.AttributeID = attribute.ID;
                            if (attribute.AttributeType == BLL.BusinessObjects.AttributeTypes.Constant)
                            {
                                attrValue.Value = attribute.ConstantValue;
                            }
                            newFeatureSelection.AttributeValues.Add(attrValue);
                        }
                    }
                }
            }
            //---------------------------------------------------------------------------------------------------------------------------------------------------------
        }