예제 #1
0
 /// <summary>
 /// Send audit for querying
 /// </summary>
 protected virtual void SendAuditQuery(OutcomeIndicator success, IMessage message, IEnumerable <IdentifiedData> results)
 {
     AuditUtil.AuditQuery(Core.Auditing.OutcomeIndicator.Success, PipeParser.Encode(message.GetStructure("QPD") as ISegment, new EncodingCharacters('|', "^~\\&")), results?.OfType <IdentifiedData>().ToArray());
 }
예제 #2
0
        /// <summary>
        /// Handle message internally
        /// </summary>
        protected override IMessage HandleMessageInternal(Hl7MessageReceivedEventArgs e, Bundle parsed)
        {
            // First we want to get the map
            var msh     = e.Message.GetStructure("MSH") as MSH;
            var trigger = msh.MessageType.TriggerEvent.Value;
            var map     = this.GetMapping(trigger);
            var qpd     = e.Message.GetStructure("QPD") as QPD;

            try
            {
                if (map.ResponseType == null)
                {
                    throw new NotSupportedException($"Response type not found");
                }

                // First, process the query parameters
                var query = map.QueryHandler.ParseQuery(qpd, map);
                if (query.Count == 0)
                {
                    throw new InvalidOperationException("Query must provide at least one understood filter");
                }

                // Control?
                var  rcp = e.Message.GetStructure("RCP") as RCP;
                int? count = null, offset = 0;
                Guid queryId = Guid.NewGuid();
                if (!String.IsNullOrEmpty(rcp.QuantityLimitedRequest.Quantity.Value))
                {
                    count = Int32.Parse(rcp.QuantityLimitedRequest.Quantity.Value);
                }

                // Continuation?
                var dsc = e.Message.GetStructure("DSC") as DSC;
                if (!String.IsNullOrEmpty(dsc.ContinuationPointer.Value))
                {
                    if (!Guid.TryParse(dsc.ContinuationPointer.Value, out queryId))
                    {
                        throw new InvalidOperationException($"DSC^1 must be UUID provided by this service.");
                    }
                }

                // Get the query tag which is the current offset
                if (ApplicationServiceContext.Current.GetService <Core.Services.IQueryPersistenceService>()?.IsRegistered(queryId) == true)
                {
                    var tag = ApplicationServiceContext.Current.GetService <Core.Services.IQueryPersistenceService>().GetQueryTag(queryId);
                    if (tag is int)
                    {
                        offset = (int)tag;
                    }
                }

                // Next, we want to get the repository for the bound type
                var repoService = ApplicationServiceContext.Current.GetService(typeof(IRepositoryService <>).MakeGenericType(map.QueryTarget));
                if (repoService == null)
                {
                    throw new InvalidOperationException($"Cannot find repository service for {map.QueryTargetXml}");
                }

                // Build query
                int         totalResults = 0;
                IEnumerable results      = null;
                Expression  filterQuery  = null;

                if (query.ContainsKey("_id"))
                {
                    Guid   id     = Guid.Parse(query["_id"][0]);
                    object result = repoService.GetType().GetMethod("Get", new Type[] { typeof(Guid) }).Invoke(repoService, new object[] { id });
                    results = new List <IdentifiedData>();

                    if (result != null)
                    {
                        (results as IList).Add(result);
                        totalResults = 1;
                    }
                }
                else
                {
                    var queryMethod = typeof(QueryExpressionParser).GetGenericMethod(nameof(QueryExpressionParser.BuildLinqExpression),
                                                                                     new Type[] { map.QueryTarget },
                                                                                     new Type[] { typeof(NameValueCollection) });
                    filterQuery = queryMethod.Invoke(null, new object[] { query }) as Expression;

                    // Now we want to query
                    object[] parameters = { filterQuery, offset.Value, (int?)count ?? 100, null, queryId, null };
                    var      findMethod = repoService.GetType().GetMethod("Find", new Type[] { filterQuery.GetType(), typeof(int), typeof(int?), typeof(int).MakeByRefType(), typeof(Guid), typeof(ModelSort <>).MakeGenericType(map.QueryTarget).MakeArrayType() });
                    results      = findMethod.Invoke(repoService, parameters) as IEnumerable;
                    totalResults = (int)parameters[3];
                }
                // Save the tag
                if (dsc.ContinuationPointer.Value != queryId.ToString() &&
                    offset.Value + count.GetValueOrDefault() < totalResults)
                {
                    ApplicationServiceContext.Current.GetService <Core.Services.IQueryPersistenceService>()?.SetQueryTag(queryId, count);
                }

                AuditUtil.AuditQuery(Core.Auditing.OutcomeIndicator.Success, PipeParser.Encode(qpd, new EncodingCharacters('|', "^~\\&")), results.OfType <IdentifiedData>().ToArray());

                // Query basics
                return(this.CreateQueryResponse(e, filterQuery, map, results, queryId, offset.GetValueOrDefault(), count ?? 100, totalResults));
            }
            catch (Exception ex)
            {
                this.m_traceSource.TraceEvent(EventLevel.Error, "Error executing query: {0}", ex);
                AuditUtil.AuditQuery <IdentifiedData>(Core.Auditing.OutcomeIndicator.MinorFail, PipeParser.Encode(qpd, new EncodingCharacters('|', "^~\\&")));

                // Now we construct the response
                return(this.CreateNACK(map.ResponseType, e.Message, ex, e));
            }
        }
        public virtual IEnumerable <Object> Query(NameValueCollection queryParameters, int offset, int count, out int totalCount)
        {
            if ((this.Capabilities & ResourceCapabilityType.Search) == 0)
            {
                throw new NotSupportedException(this.m_localizationService.GetString("error.type.NotSupportedException"));
            }
            try
            {
                IEnumerable <TResource> retVal = null;

                // IS this a freetext search?
                if (queryParameters.ContainsKey("_any"))
                {
                    var fts = ApplicationServiceContext.Current.GetService <IFreetextSearchService>();
                    if (fts == null)
                    {
                        this.m_tracer.TraceError("Attempting to run a freetext search in a context which does not support freetext searches");
                        throw new InvalidOperationException(this.m_localizationService.GetString("error.rest.common.freetextNotSupported"));
                    }

                    // Order by
                    ModelSort <TResource>[] sortParameters = null;
                    if (queryParameters.TryGetValue("_orderBy", out List <String> orderBy))
                    {
                        sortParameters = QueryExpressionParser.BuildSort <TResource>(orderBy);
                    }

                    Guid queryId = Guid.Empty;
                    if (queryParameters.TryGetValue("_queryId", out List <String> query))
                    {
                        queryId = Guid.Parse(query.First());
                    }

                    retVal = fts.Search <TResource>(queryParameters["_any"].ToArray(), queryId, offset, count, out totalCount, sortParameters);
                }
                else
                {
                    var           queryExpression = QueryExpressionParser.BuildLinqExpression <TResource>(queryParameters, null, false);
                    List <String> query = null, id = null, orderBy = null;

                    // Order by
                    ModelSort <TResource>[] sortParameters = null;
                    if (queryParameters.TryGetValue("_orderBy", out orderBy))
                    {
                        sortParameters = QueryExpressionParser.BuildSort <TResource>(orderBy);
                    }

                    if (queryParameters.TryGetValue("_id", out id))
                    {
                        var obj = id.Select(o => this.GetRepository().Get(Guid.Parse(o)));
                        if (obj != null)
                        {
                            retVal = new List <TResource>(obj);
                        }
                        else
                        {
                            retVal = new List <TResource>();
                        }
                        totalCount = retVal.Count();
                    }
                    else if (queryParameters.TryGetValue("_queryId", out query) && this.GetRepository() is IPersistableQueryRepositoryService <TResource> )
                    {
                        Guid          queryId = Guid.Parse(query[0]);
                        List <String> data    = null;
                        if (queryParameters.TryGetValue("_subscription", out data))
                        { // subscription based query
                            totalCount = 0;
                            retVal     = ApplicationServiceContext.Current.GetService <ISubscriptionExecutor>()?.Execute(Guid.Parse(data.First()), queryParameters, offset, count, out totalCount, queryId).OfType <TResource>();
                        }
                        else if (queryParameters.TryGetValue("_lean", out data) && data[0] == "true" && this.GetRepository() is IFastQueryRepositoryService <TResource> )
                        {
                            retVal = (this.GetRepository() as IFastQueryRepositoryService <TResource>).FindFast(queryExpression, offset, count, out totalCount, queryId);
                        }
                        else
                        {
                            retVal = (this.GetRepository() as IPersistableQueryRepositoryService <TResource>).Find(queryExpression, offset, count, out totalCount, queryId, sortParameters);
                        }
                    }
                    else
                    {
                        List <String> lean = null;
                        if (queryParameters.TryGetValue("_lean", out lean) && lean[0] == "true" && this.GetRepository() is IFastQueryRepositoryService <TResource> )
                        {
                            retVal = (this.GetRepository() as IFastQueryRepositoryService <TResource>).FindFast(queryExpression, offset, count, out totalCount, Guid.Empty);
                        }
                        else
                        {
                            retVal = this.GetRepository().Find(queryExpression, offset, count, out totalCount, sortParameters);
                        }
                    }
                }
                if (typeof(Act).IsAssignableFrom(typeof(TResource)) || typeof(Entity).IsAssignableFrom(typeof(TResource)))
                {
                    AuditUtil.AuditQuery(Core.Auditing.OutcomeIndicator.Success, queryParameters.ToString(), retVal.ToArray());
                }
                return(retVal);
            }
            catch (Exception e)
            {
                AuditUtil.AuditQuery <TResource>(Core.Auditing.OutcomeIndicator.MinorFail, queryParameters.ToString());
                this.m_tracer.TraceError("Error querying underlying repository");
                throw new Exception(this.m_localizationService.GetString("error.rest.common.queryingRepository"), e);
            }
        }