func (s *ServiceSuite) TestBundleToEventStreamUnsupportedEvent(c *C) { data, err := ioutil.ReadFile("fixtures/brad_bradworth_event_source_bundle.json") util.CheckErr(err) bundle := new(models.Bundle) json.Unmarshal(data, bundle) bundle.Entry = append(bundle.Entry, models.BundleEntryComponent{ Resource: &models.Encounter{}, Search: &models.BundleEntrySearchComponent{ Mode: "include", }, }) _, err = BundleToEventStream(bundle) c.Assert(err, NotNil) c.Assert(err.Error(), Equals, "Unsupported: Converting Encounter to Event") }
func (dal *mongoDataAccessLayer) Search(baseURL url.URL, searchQuery search.Query) (*models.Bundle, error) { searcher := search.NewMongoSearcher(dal.Database) var result interface{} var err error usesIncludes := len(searchQuery.Options().Include) > 0 usesRevIncludes := len(searchQuery.Options().RevInclude) > 0 // Only use (slower) pipeline if it is needed if usesIncludes || usesRevIncludes { result = models.NewSlicePlusForResourceName(searchQuery.Resource, 0, 0) err = searcher.CreatePipeline(searchQuery).All(result) } else { result = models.NewSliceForResourceName(searchQuery.Resource, 0, 0) err = searcher.CreateQuery(searchQuery).All(result) } if err != nil { return nil, convertMongoErr(err) } includesMap := make(map[string]interface{}) var entryList []models.BundleEntryComponent resultVal := reflect.ValueOf(result).Elem() for i := 0; i < resultVal.Len(); i++ { var entry models.BundleEntryComponent entry.Resource = resultVal.Index(i).Addr().Interface() entry.Search = &models.BundleEntrySearchComponent{Mode: "match"} entryList = append(entryList, entry) if usesIncludes || usesRevIncludes { rpi, ok := entry.Resource.(ResourcePlusRelatedResources) if ok { for k, v := range rpi.GetIncludedAndRevIncludedResources() { includesMap[k] = v } } } } for _, v := range includesMap { var entry models.BundleEntryComponent entry.Resource = v entry.Search = &models.BundleEntrySearchComponent{Mode: "include"} entryList = append(entryList, entry) } var bundle models.Bundle bundle.Id = bson.NewObjectId().Hex() bundle.Type = "searchset" bundle.Entry = entryList options := searchQuery.Options() // Need to get the true total (not just how many were returned in this response) var total uint32 if resultVal.Len() == options.Count || resultVal.Len() == 0 { // Need to get total count from the server, since there may be more or the offset was too high intTotal, err := searcher.CreateQueryWithoutOptions(searchQuery).Count() if err != nil { return nil, convertMongoErr(err) } total = uint32(intTotal) } else { // We can figure out the total by adding the offset and # results returned total = uint32(options.Offset + resultVal.Len()) } bundle.Total = &total // Add links for paging bundle.Link = generatePagingLinks(baseURL, searchQuery, total) return &bundle, nil }
func (s *ServiceSuite) TestEndToEndCalculationsWithNACHADS(c *C) { // Get the test data for Chad Chadworth (for the CHADS test -- get it?) data, err := os.Open("fixtures/chad_chadworth_bundle.json") util.CheckErr(err) defer data.Close() // Remove the AFib entry (index 5) so he is Not Applicable bundle := new(models.Bundle) decoder := json.NewDecoder(data) err = decoder.Decode(bundle) util.CheckErr(err) bundle.Entry = append(bundle.Entry[:5], bundle.Entry[6:]...) b, err := json.Marshal(bundle) util.CheckErr(err) // Store Chad Chadworth's modified information to Mongo res, err := http.Post(s.Server.URL+"/", "application/json", bytes.NewBuffer(b)) util.CheckErr(err) defer res.Body.Close() // Get the response so we can pull out the patient ID decoder = json.NewDecoder(res.Body) responseBundle := new(models.Bundle) err = decoder.Decode(responseBundle) util.CheckErr(err) patientID := responseBundle.Entry[0].Resource.(*models.Patient).Id // Confirm there are no risk assessments or pies raCollection := s.Database.C("riskassessments") count, err := raCollection.Count() util.CheckErr(err) c.Assert(count, Equals, 0) piesCollection := s.Database.C("pies") count, err = piesCollection.Count() util.CheckErr(err) c.Assert(count, Equals, 0) // Now register the plugins and request the calculation! s.Service.RegisterPlugin(assessments.NewCHA2DS2VAScPlugin()) s.Service.RegisterPlugin(assessments.NewSimplePlugin()) err = s.Service.Calculate(patientID, s.Server.URL, s.Server.URL+"/pies") util.CheckErr(err) count, err = raCollection.Find(bson.M{"method.coding.code": "CHADS"}).Count() util.CheckErr(err) c.Assert(count, Equals, 1) count, err = raCollection.Find(bson.M{"method.coding.code": "Simple"}).Count() util.CheckErr(err) c.Assert(count, Equals, 4) count, err = piesCollection.Count() util.CheckErr(err) c.Assert(count, Equals, 4) var ras []models.RiskAssessment err = raCollection.Find(bson.M{"method.coding.code": "CHADS"}).All(&ras) util.CheckErr(err) // Check that the CHADS is not applicable c.Assert(ras, HasLen, 1) ra := ras[0] c.Assert(ra.Subject.Reference, Equals, "Patient/"+patientID) c.Assert(ra.Method.MatchesCode("http://interventionengine.org/risk-assessments", "CHADS"), Equals, true) c.Assert(time.Now().Sub(ra.Date.Time) < time.Minute, Equals, true) c.Assert(ra.Prediction, HasLen, 1) c.Assert(ra.Prediction[0].Outcome.Text, Equals, "Stroke") c.Assert(ra.Prediction[0].ProbabilityCodeableConcept.Coding, HasLen, 1) c.Assert(ra.Prediction[0].ProbabilityCodeableConcept.Coding[0].System, Equals, "http://snomed.info/sct") c.Assert(ra.Prediction[0].ProbabilityCodeableConcept.Coding[0].Code, Equals, "385432009") c.Assert(ra.Prediction[0].ProbabilityCodeableConcept.Text, Equals, "Not applicable") c.Assert(ra.Basis, HasLen, 0) c.Assert(ra.Meta.Tag, HasLen, 1) c.Assert(ra.Meta.Tag[0], DeepEquals, models.Coding{System: "http://interventionengine.org/tags/", Code: "MOST_RECENT"}) // Simple should still be good ras = nil err = raCollection.Find(bson.M{"method.coding.code": "Simple"}).Sort("date.time").All(&ras) util.CheckErr(err) loc := time.FixedZone("-0500", -5*60*60) s.checkSimpleRiskAssessment(c, &ras[0], patientID, time.Date(2012, time.September, 20, 8, 0, 0, 0, loc), 1, false) s.checkSimplePie(c, &ras[0], patientID, 1, 0) s.checkSimpleRiskAssessment(c, &ras[1], patientID, time.Date(2013, time.September, 2, 10, 0, 0, 0, loc), 3, false) s.checkSimplePie(c, &ras[1], patientID, 2, 1) s.checkSimpleRiskAssessment(c, &ras[2], patientID, time.Date(2014, time.January, 17, 20, 35, 0, 0, loc), 4, false) s.checkSimplePie(c, &ras[2], patientID, 3, 1) s.checkSimpleRiskAssessment(c, &ras[3], patientID, time.Date(2014, time.January, 17, 20, 40, 0, 0, loc), 3, true) s.checkSimplePie(c, &ras[3], patientID, 2, 1) }
func (rc *ResourceController) IndexHandler(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { defer func() { if r := recover(); r != nil { rw.Header().Set("Content-Type", "application/json; charset=utf-8") switch x := r.(type) { case search.Error: rw.WriteHeader(x.HTTPStatus) json.NewEncoder(rw).Encode(x.OperationOutcome) return default: outcome := &models.OperationOutcome{ Issue: []models.OperationOutcomeIssueComponent{ models.OperationOutcomeIssueComponent{ Severity: "fatal", Code: "exception", }, }, } rw.WriteHeader(http.StatusInternalServerError) json.NewEncoder(rw).Encode(outcome) } } }() result := models.NewSliceForResourceName(rc.Name, 0, 0) // Create and execute the Mongo query based on the http query params searcher := search.NewMongoSearcher(Database) searchQuery := search.Query{Resource: rc.Name, Query: r.URL.RawQuery} mgoQuery := searcher.CreateQuery(searchQuery) // Horrible, horrible hack (for now) to ensure patients are sorted by name. This is needed by // the frontend, else paging won't work correctly. This should be removed when the general // sorting feature is implemented. if rc.Name == "Patient" { // To add insult to injury, mongo will not let us sort by family *and* given name: // Executor error: BadValue cannot sort with keys that are parallel arrays mgoQuery = mgoQuery.Sort("name.0.family.0" /*", name.0.given.0"*/, "_id") } err := mgoQuery.All(result) if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) } var entryList []models.BundleEntryComponent resultVal := reflect.ValueOf(result).Elem() for i := 0; i < resultVal.Len(); i++ { var entry models.BundleEntryComponent entry.Resource = resultVal.Index(i).Addr().Interface() entryList = append(entryList, entry) } var bundle models.Bundle bundle.Id = bson.NewObjectId().Hex() bundle.Type = "searchset" bundle.Entry = entryList options := searchQuery.Options() // Need to get the true total (not just how many were returned in this response) var total uint32 if resultVal.Len() == options.Count || resultVal.Len() == 0 { // Need to get total count from the server, since there may be more or the offset was too high intTotal, err := searcher.CreateQueryWithoutOptions(searchQuery).Count() if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) } total = uint32(intTotal) } else { // We can figure out the total by adding the offset and # results returned total = uint32(options.Offset + resultVal.Len()) } bundle.Total = &total // Add links for paging bundle.Link = generatePagingLinks(r, searchQuery, total) context.Set(r, rc.Name, reflect.ValueOf(result).Elem().Interface()) context.Set(r, "Resource", rc.Name) context.Set(r, "Action", "search") rw.Header().Set("Content-Type", "application/json; charset=utf-8") rw.Header().Set("Access-Control-Allow-Origin", "*") json.NewEncoder(rw).Encode(&bundle) }