/// <summary>
 /// Saves tags associated with the specified object
 /// </summary>
 public object SaveTags(ExpandoObject obj)
 {
     try
     {
         var modelObj = JavascriptUtils.ToModel(obj) as ITaggable;
         if (modelObj != null)
         {
             var tags = modelObj.Tags;
             if (tags.Count() > 0)
             {
                 var tpi = ApplicationServiceContext.Current.GetService(typeof(ITagPersistenceService)) as ITagPersistenceService;
                 if (tpi == null)
                 {
                     return(obj);
                 }
                 foreach (var t in tags)
                 {
                     t.SourceEntityKey = (modelObj as IIdentifiedEntity).Key;
                     tpi.Save(t.SourceEntityKey.Value, t);
                 }
             }
         }
         return(obj);
     }
     catch (Exception e)
     {
         this.m_tracer.TraceError("Error saving tags: {0}", e);
         throw;
     }
 }
        /// <summary>
        /// Inserts the specified object
        /// </summary>
        public object Insert(object value)
        {
            try
            {
                var data = JavascriptUtils.ToModel(value);
                if (data == null)
                {
                    throw new ArgumentException("Could not parse value for insert");
                }

                var cacheKey = $"{data.Type}.{data.Key}";
                this.m_adhocCache?.Remove(cacheKey);

                var idp         = typeof(IRepositoryService <>).MakeGenericType(data.GetType());
                var idpInstance = ApplicationServiceContext.Current.GetService(idp) as IRepositoryService;
                if (idpInstance == null)
                {
                    throw new KeyNotFoundException($"The repository service for {data.GetType()} was not found. Ensure an IRepositoryService<{data.GetType()}> is registered");
                }

                return(JavascriptUtils.ToViewModel(idpInstance.Insert(data)));
            }
            catch (TargetInvocationException e)
            {
                this.m_tracer.TraceError("Persistence inserting in BRE: {0} - {1}", value, e.InnerException);
                throw new Exception($"Persistence inserting in  BRE : {value}", e.InnerException);
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error inserting in  BRE: {0} - {1}", value, e);
                throw new Exception($"Error inserting in  BRE: {value}", e);
            }
        }
        /// <summary>
        /// Executes the business rule
        /// </summary>
        public object ExecuteRule(String action, Object data)
        {
            var sData  = JavascriptUtils.ToModel(data);
            var retVal = this.m_owner.Invoke(action, sData);

            return(JavascriptUtils.ToViewModel(retVal));
        }
        /// <summary>
        /// Perform actual invokation on all objects
        /// </summary>
        public TBinding Invoke <TBinding>(string triggerName, TBinding data) where TBinding : IdentifiedData
        {
            lock (this.m_lock)
            {
                using (AuthenticationContext.EnterSystemContext())
                {
                    if (data == default(TBinding))
                    {
                        return(data);
                    }

                    var callList = this.GetCallList(data.GetType(), triggerName);
                    callList = callList.Union(this.GetCallList <TBinding>(triggerName), this.m_javascriptComparer).ToList();
                    var retVal = data;

                    if (callList.Count() > 0)
                    {
                        dynamic viewModel = JavascriptUtils.ToViewModel(retVal);
                        foreach (var c in callList)
                        {
                            try
                            {
                                // There is a guard so let's execute it
                                if (c.Guard == null || QueryExpressionParser.BuildLinqExpression <TBinding>(c.Guard).Compile()(data))
                                {
                                    viewModel = c.Callback.DynamicInvoke(viewModel);
                                }
                            }
                            catch (JavaScriptException e)
                            {
                                this.m_tracer.TraceError("JS ERROR: Error running {0} for {1} @ {2}:{3} \r\n Javascript Stack: {4} \r\n C# Stack: {5}",
                                                         triggerName, data, e.Location.Source, e.LineNumber, e.CallStack, e);
                                throw new JsBusinessRuleException($"Error running business rule {c.Id} - {triggerName} for {data}", e);
                            }
                            catch (TargetInvocationException e) when(e.InnerException is JavaScriptException je)
                            {
                                this.m_tracer.TraceError("JS ERROR: Error running {0} for {1} @ {2}:{3} \r\n Javascript Stack: {4} \r\n C# Stack: {5}",
                                                         triggerName, data, je.Location.Source, je.LineNumber, je.CallStack, e);
                                throw new JsBusinessRuleException($"Error running business rule {c.Id} - {triggerName} for {data}", je);
                            }
                            catch (Exception e)
                            {
                                this.m_tracer.TraceError("Error running {0} for {1} : {2}", triggerName, data, e);
                                throw new JsBusinessRuleException($"Error running business rule {c.Id} - {triggerName} for {data}", e);
                            }
                        }

                        retVal = (TBinding)JavascriptUtils.ToModel(viewModel).CopyAnnotations(retVal);
                    }

                    return(retVal);
                }
            }
        }