Example #1
0
        /// <summary>
        /// Executes the specified view
        /// </summary>
        public BisResultContext ExecuteView(BiViewDefinition viewDef, IDictionary <string, object> parameters, int offset, int?count)
        {
            viewDef = BiUtils.ResolveRefs(viewDef) as BiViewDefinition;
            var retVal = this.ExecuteQuery(viewDef.Query, parameters, viewDef.AggregationDefinitions?.ToArray(), offset, count);

            if (viewDef.Pivot != null)
            {
                retVal = ApplicationServiceContext.Current.GetService <IBiPivotProvider>().Pivot(retVal, viewDef.Pivot);
            }
            return(retVal);
        }
        /// <summary>
        /// Execute the specified view
        /// </summary>
        public BisResultContext ExecuteView(BiViewDefinition viewDef, IDictionary <string, object> parameters, int offset, int?count)
        {
            try
            {
                var parmDict = parameters.ToDictionary(o => o.Key, o => o.Value);

                if (!parmDict.ContainsKey("_count"))
                {
                    parmDict.Add("_count", count);
                }
                if (!parmDict.ContainsKey("_offset"))
                {
                    parmDict.Add("_offset", offset);
                }

                var startTime = DateTime.Now;
                using (var client = this.GetRestClient())
                {
                    var results = client.Get <IEnumerable <dynamic> >($"Query/{viewDef.Id}", parameters.ToArray());
                    return(new BisResultContext(viewDef.Query, parameters, this, results, startTime));
                }
            }
            catch (System.Net.WebException e)
            {
                var wr = e.Response as HttpWebResponse;
                this.m_tracer.TraceWarning("Remote service indicated failure: {0}", e);

                if (wr?.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new KeyNotFoundException($"Could not find definition with id {viewDef.Id}", e);
                }
                else
                {
                    throw new Exception($"Error fetching BIS definition {viewDef.Id }", e);
                }
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError($"Error executing BIS query {viewDef.Name} - {e}");
                throw new Exception($"Error executing BIS query {viewDef.Name}", e);
                throw;
            }
        }
        /// <summary>
        /// Hydrate the query
        /// </summary>
        /// <param name="queryId"></param>
        /// <returns></returns>
        private BisResultContext HydrateQuery(String queryId)
        {
            AuditData audit = new AuditData(DateTimeOffset.Now, ActionType.Execute, OutcomeIndicator.Success, EventIdentifierType.Query, AuditUtil.CreateAuditActionCode(EventTypeCodes.SecondaryUseQuery));

            try
            {
                // First we want to grab the appropriate source for this ID
                var viewDef = this.m_metadataRepository.Get <BiViewDefinition>(queryId);
                if (viewDef == null)
                {
                    var queryDef = this.m_metadataRepository.Get <BiQueryDefinition>(queryId);
                    if (queryDef == null) // Parameter value
                    {
                        var parmDef = this.m_metadataRepository.Get <BiParameterDefinition>(queryId);
                        if (parmDef == null)
                        {
                            throw new KeyNotFoundException($"Could not find a Parameter, Query or View to hydrate named {queryId}");
                        }
                        queryDef    = parmDef?.Values as BiQueryDefinition;
                        queryDef.Id = queryDef.Id ?? queryId;
                    }

                    viewDef = new BiViewDefinition()
                    {
                        Id    = queryDef.Id,
                        Query = queryDef
                    };
                }

                viewDef = SanteDB.BI.Util.BiUtils.ResolveRefs(viewDef) as BiViewDefinition;
                var dsource = viewDef.Query?.DataSources.FirstOrDefault(o => o.Name == "main") ?? viewDef.Query?.DataSources.FirstOrDefault();
                if (dsource == null)
                {
                    throw new KeyNotFoundException("Query does not contain a data source");
                }

                IBiDataSource providerImplementation = null;
                if (dsource.ProviderType != null && this.m_metadataRepository.IsLocal)
                {
                    providerImplementation = this.m_serviceManager.CreateInjected(dsource.ProviderType) as IBiDataSource;
                }
                else
                {
                    providerImplementation = ApplicationServiceContext.Current.GetService <IBiDataSource>(); // Global default
                }
                // Populate data about the query
                audit.AuditableObjects.Add(new AuditableObject()
                {
                    IDTypeCode    = AuditableObjectIdType.ReportNumber,
                    LifecycleType = AuditableObjectLifecycle.Report,
                    ObjectId      = queryId,
                    QueryData     = RestOperationContext.Current.IncomingRequest.Url.Query,
                    Role          = AuditableObjectRole.Query,
                    Type          = AuditableObjectType.SystemObject
                });

                var parameters = this.CreateParameterDictionary();

                // Aggregations and groups?
                if (RestOperationContext.Current.IncomingRequest.QueryString["_groupBy"] != null)
                {
                    var aggRx = new Regex(@"(\w*)\((.*?)\)");
                    viewDef.AggregationDefinitions = new List <BiAggregationDefinition>()
                    {
                        new BiAggregationDefinition()
                        {
                            Groupings = RestOperationContext.Current.IncomingRequest.QueryString.GetValues("_groupBy").Select(o => new BiSqlColumnReference()
                            {
                                ColumnSelector = o.Contains("::")  ? $"CAST({o.Substring(0, o.IndexOf(":"))} AS {o.Substring(o.IndexOf(":") + 2)})" : o,
                                Name           = o.Contains("::") ? o.Substring(0, o.IndexOf(":")) : o
                            }).ToList(),
                            Columns = RestOperationContext.Current.IncomingRequest.QueryString.GetValues("_select").Select(o => {
                                var match = aggRx.Match(o);
                                if (!match.Success)
                                {
                                    throw new InvalidOperationException("Aggregation function must be in format AGGREGATOR(COLUMN)");
                                }
                                return(new BiAggregateSqlColumnReference()
                                {
                                    Aggregation = (BiAggregateFunction)Enum.Parse(typeof(BiAggregateFunction), match.Groups[1].Value, true),
                                    ColumnSelector = match.Groups[2].Value,
                                    Name = match.Groups[2].Value
                                });
                            }).ToList()
                        }
                    };
                }

                int offset = 0, count = 100;
                if (!Int32.TryParse(RestOperationContext.Current.IncomingRequest.QueryString["_offset"] ?? "0", out offset))
                {
                    throw new FormatException("_offset is not in the correct format");
                }
                if (!Int32.TryParse(RestOperationContext.Current.IncomingRequest.QueryString["_count"] ?? "100", out count))
                {
                    throw new FormatException("_count is not in the correct format");
                }


                var queryData = providerImplementation.ExecuteView(viewDef, parameters, offset, count);
                return(queryData);
            }
            catch (KeyNotFoundException)
            {
                audit.Outcome = OutcomeIndicator.MinorFail;
                throw;
            }
            catch (Exception e)
            {
                audit.Outcome = OutcomeIndicator.MinorFail;
                this.m_tracer.TraceError("Error rendering query: {0}", e);
                throw new FaultException(500, $"Error rendering query {queryId}", e);
            }
            finally
            {
                AuditUtil.AddLocalDeviceActor(audit);
                AuditUtil.AddUserActor(audit);
                AuditUtil.SendAudit(audit);
            }
        }