| 380 | | * @see org.openmrs.api.db.ObsDAO#getObservations(org.openmrs.Person, org.openmrs.logic.Aggregation, org.openmrs.Concept, org.openmrs.logic.Constraint) |
|---|
| 381 | | */ |
|---|
| 382 | | @SuppressWarnings("unchecked") |
|---|
| 383 | | public List<Obs> getObservations(Person who, Aggregation aggregation, |
|---|
| 384 | | Concept question, Constraint constraint) { |
|---|
| 385 | | Session session = sessionFactory.getCurrentSession(); |
|---|
| 386 | | Criteria criteria = session.createCriteria(Obs.class); |
|---|
| 387 | | |
|---|
| 388 | | criteria.add(Restrictions.eq("person", who)); |
|---|
| 389 | | criteria.add(Restrictions.eq("concept", question)); |
|---|
| 390 | | criteria.add(Restrictions.eq("voided", false)); |
|---|
| 391 | | |
|---|
| 392 | | DateConstraint dateConstraint = (DateConstraint) constraint; |
|---|
| 393 | | final String OBS_DATETIME = "obsDatetime"; |
|---|
| 394 | | Criterion dateCriterion = null; |
|---|
| 395 | | GregorianCalendar d0, d1, d2; |
|---|
| 396 | | if (dateConstraint != null) { |
|---|
| 397 | | int dateComparison = dateConstraint.getComparison(); |
|---|
| 398 | | switch (dateComparison) { |
|---|
| 399 | | case DateConstraint.EQUAL: |
|---|
| 400 | | dateCriterion = Restrictions.eq(OBS_DATETIME, dateConstraint |
|---|
| 401 | | .getDate()); |
|---|
| 402 | | break; |
|---|
| 403 | | case DateConstraint.NOT_EQUAL: |
|---|
| 404 | | dateCriterion = Restrictions.ne(OBS_DATETIME, dateConstraint |
|---|
| 405 | | .getDate()); |
|---|
| 406 | | break; |
|---|
| 407 | | case DateConstraint.WITHIN: |
|---|
| 408 | | case DateConstraint.NOT_WITHIN: |
|---|
| 409 | | dateCriterion = Restrictions.between(OBS_DATETIME, |
|---|
| 410 | | dateConstraint.getDate(), dateConstraint |
|---|
| 411 | | .getSecondDate()); |
|---|
| 412 | | if (dateComparison == DateConstraint.NOT_WITHIN) |
|---|
| 413 | | dateCriterion = Restrictions.not(dateCriterion); |
|---|
| 414 | | break; |
|---|
| 415 | | case DateConstraint.WITHIN_PRECEDING: |
|---|
| 416 | | case DateConstraint.NOT_WITHIN_PRECEDING: |
|---|
| 417 | | d1 = new GregorianCalendar(); |
|---|
| 418 | | d2 = new GregorianCalendar(); |
|---|
| 419 | | d2.setTime(dateConstraint.getDate()); |
|---|
| 420 | | d1.setTimeInMillis(d2.getTimeInMillis() |
|---|
| 421 | | - dateConstraint.getDuration().getDurationInMillis()); |
|---|
| 422 | | dateCriterion = Restrictions.between(OBS_DATETIME, |
|---|
| 423 | | d1.getTime(), d2.getTime()); |
|---|
| 424 | | if (dateComparison == DateConstraint.NOT_WITHIN_PRECEDING) |
|---|
| 425 | | dateCriterion = Restrictions.not(dateCriterion); |
|---|
| 426 | | break; |
|---|
| 427 | | case DateConstraint.WITHIN_FOLLOWING: |
|---|
| 428 | | case DateConstraint.NOT_WITHIN_FOLLOWING: |
|---|
| 429 | | d1 = new GregorianCalendar(); |
|---|
| 430 | | d2 = new GregorianCalendar(); |
|---|
| 431 | | d1.setTime(dateConstraint.getDate()); |
|---|
| 432 | | d2.setTimeInMillis(d1.getTimeInMillis() |
|---|
| 433 | | + dateConstraint.getDuration().getDurationInMillis()); |
|---|
| 434 | | dateCriterion = Restrictions.between(OBS_DATETIME, |
|---|
| 435 | | d1.getTime(), d2.getTime()); |
|---|
| 436 | | if (dateComparison == DateConstraint.NOT_WITHIN_FOLLOWING) |
|---|
| 437 | | dateCriterion = Restrictions.not(dateCriterion); |
|---|
| 438 | | break; |
|---|
| 439 | | case DateConstraint.WITHIN_SURROUNDING: |
|---|
| 440 | | case DateConstraint.NOT_WITHIN_SURROUNDING: |
|---|
| 441 | | d0 = new GregorianCalendar(); |
|---|
| 442 | | d0.setTime(dateConstraint.getDate()); |
|---|
| 443 | | d1 = new GregorianCalendar(); |
|---|
| 444 | | d2 = new GregorianCalendar(); |
|---|
| 445 | | long delta = dateConstraint.getDuration().getDurationInMillis() / 2; |
|---|
| 446 | | d1.setTimeInMillis(d0.getTimeInMillis() - delta); |
|---|
| 447 | | d2.setTimeInMillis(d0.getTimeInMillis() + delta); |
|---|
| 448 | | dateCriterion = Restrictions.between(OBS_DATETIME, |
|---|
| 449 | | d1.getTime(), d2.getTime()); |
|---|
| 450 | | if (dateComparison == DateConstraint.NOT_WITHIN_SURROUNDING) |
|---|
| 451 | | dateCriterion = Restrictions.not(dateCriterion); |
|---|
| 452 | | break; |
|---|
| 453 | | case DateConstraint.WITHIN_PAST: |
|---|
| 454 | | case DateConstraint.NOT_WITHIN_PAST: |
|---|
| 455 | | d1 = new GregorianCalendar(); |
|---|
| 456 | | d2 = new GregorianCalendar(); |
|---|
| 457 | | d2.setTime(new Date()); |
|---|
| 458 | | d1.setTimeInMillis(d1.getTimeInMillis() |
|---|
| 459 | | - dateConstraint.getDuration().getDurationInMillis()); |
|---|
| 460 | | dateCriterion = Restrictions.between(OBS_DATETIME, |
|---|
| 461 | | d1.getTime(), d2.getTime()); |
|---|
| 462 | | if (dateComparison == DateConstraint.NOT_WITHIN_PAST) |
|---|
| 463 | | dateCriterion = Restrictions.not(dateCriterion); |
|---|
| 464 | | break; |
|---|
| 465 | | case DateConstraint.WITHIN_SAME_DAY_AS: |
|---|
| 466 | | case DateConstraint.NOT_WITHIN_SAME_DAY_AS: |
|---|
| 467 | | d0 = new GregorianCalendar(); |
|---|
| 468 | | d0.setTime(dateConstraint.getDate()); |
|---|
| 469 | | d0.set(d0.get(Calendar.YEAR), d0.get(Calendar.MONTH), d0 |
|---|
| 470 | | .get(Calendar.DATE), 0, 0, 0); |
|---|
| 471 | | d1 = new GregorianCalendar(); |
|---|
| 472 | | d2 = new GregorianCalendar(); |
|---|
| 473 | | d1.setTimeInMillis(d0.getTimeInMillis() - 1); |
|---|
| 474 | | d2.setTimeInMillis(d0.getTimeInMillis() + 1440000); |
|---|
| 475 | | dateCriterion = Restrictions.between(OBS_DATETIME, |
|---|
| 476 | | d1.getTime(), d2.getTime()); |
|---|
| 477 | | if (dateComparison == DateConstraint.NOT_WITHIN_SAME_DAY_AS) |
|---|
| 478 | | dateCriterion = Restrictions.not(dateCriterion); |
|---|
| 479 | | break; |
|---|
| 480 | | case DateConstraint.AFTER: |
|---|
| 481 | | dateCriterion = Restrictions.gt(OBS_DATETIME, dateConstraint |
|---|
| 482 | | .getDate()); |
|---|
| 483 | | break; |
|---|
| 484 | | case DateConstraint.NOT_AFTER: |
|---|
| 485 | | dateCriterion = Restrictions.le(OBS_DATETIME, dateConstraint |
|---|
| 486 | | .getDate()); |
|---|
| 487 | | break; |
|---|
| 488 | | case DateConstraint.BEFORE: |
|---|
| 489 | | dateCriterion = Restrictions.lt(OBS_DATETIME, dateConstraint |
|---|
| 490 | | .getDate()); |
|---|
| 491 | | break; |
|---|
| 492 | | case DateConstraint.NOT_BEFORE: |
|---|
| 493 | | dateCriterion = Restrictions.ge(OBS_DATETIME, dateConstraint |
|---|
| 494 | | .getDate()); |
|---|
| 495 | | break; |
|---|
| | 368 | * @see org.openmrs.api.ObsService#getObservations(java.util.List<org.openmrs.Concept>, java.util.Date, java.util.Data, boolean) |
|---|
| | 369 | */ |
|---|
| | 370 | @SuppressWarnings("unchecked") |
|---|
| | 371 | public List<Obs> getObservations(Cohort patients, List<Concept> concepts, Date fromDate, Date toDate) |
|---|
| | 372 | throws DAOException { |
|---|
| | 373 | Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Obs.class); |
|---|
| | 374 | if ( patients != null ) { |
|---|
| | 375 | if (patients.getMemberIds() != null) { |
|---|
| | 376 | criteria.add(Restrictions.in("person.personId", patients.getMemberIds())); |
|---|
| 498 | | |
|---|
| 499 | | // Aggregation.EXIST - true if any results found |
|---|
| 500 | | // Aggregation.MEDIAN |
|---|
| 501 | | // Aggregation.STDDEV |
|---|
| 502 | | // Aggregation.VARIANCE |
|---|
| 503 | | // Aggregation.ANY - true if any results true, false for empty list or if any results non-boolean |
|---|
| 504 | | // Aggregation.ALL - true if all results true, null if any results non-boolean, true for empty list |
|---|
| 505 | | // Aggregation.NO - true if all results false |
|---|
| 506 | | // Aggregation.N_MINIMUM |
|---|
| 507 | | // Aggregation.N_MAXIMUM |
|---|
| 508 | | |
|---|
| 509 | | // TODO: figure out a way to return average, count, sum as "pseudo" obs |
|---|
| 510 | | Projection projection = null; |
|---|
| 511 | | boolean singleNumericResult = false; |
|---|
| 512 | | if (aggregation != null) { |
|---|
| 513 | | switch (aggregation.getType()) { |
|---|
| 514 | | case Aggregation.ALL: |
|---|
| 515 | | break; |
|---|
| 516 | | case Aggregation.AVERAGE: |
|---|
| 517 | | projection = Projections.avg("valueNumeric"); |
|---|
| 518 | | singleNumericResult = true; |
|---|
| 519 | | break; |
|---|
| 520 | | case Aggregation.COUNT: |
|---|
| 521 | | projection = Projections.rowCount(); |
|---|
| 522 | | singleNumericResult = true; |
|---|
| 523 | | break; |
|---|
| 524 | | case Aggregation.MAXIMUM: |
|---|
| 525 | | DetachedCriteria maxObs = DetachedCriteria.forClass( |
|---|
| 526 | | Obs.class).add(Restrictions.eq("person", who)).add( |
|---|
| 527 | | Restrictions.eq("concept", question)); |
|---|
| 528 | | if (dateCriterion != null) |
|---|
| 529 | | maxObs = maxObs |
|---|
| 530 | | .add(dateCriterion); |
|---|
| 531 | | maxObs = maxObs.setProjection( |
|---|
| 532 | | Projections.max("valueNumeric")); |
|---|
| 533 | | if (dateCriterion != null) |
|---|
| 534 | | criteria.add(dateCriterion); |
|---|
| 535 | | criteria.add( |
|---|
| 536 | | Property.forName("valueNumeric").eq(maxObs)); |
|---|
| 537 | | dateCriterion = null; |
|---|
| 538 | | break; |
|---|
| 539 | | case Aggregation.MINIMUM: |
|---|
| 540 | | DetachedCriteria minObs = DetachedCriteria.forClass( |
|---|
| 541 | | Obs.class).add(Restrictions.eq("person", who)).add( |
|---|
| 542 | | Restrictions.eq("concept", question)); |
|---|
| 543 | | if (dateCriterion != null) |
|---|
| 544 | | minObs = minObs |
|---|
| 545 | | .add(dateCriterion); |
|---|
| 546 | | minObs = minObs.setProjection( |
|---|
| 547 | | Projections.min("valueNumeric")); |
|---|
| 548 | | if (dateCriterion != null) |
|---|
| 549 | | criteria.add(dateCriterion); |
|---|
| 550 | | criteria.add( |
|---|
| 551 | | Property.forName("valueNumeric").eq(minObs)); |
|---|
| 552 | | dateCriterion = null; |
|---|
| 553 | | break; |
|---|
| 554 | | case Aggregation.SUM: |
|---|
| 555 | | projection = Projections.sum("valueNumeric"); |
|---|
| 556 | | singleNumericResult = true; |
|---|
| 557 | | break; |
|---|
| 558 | | case Aggregation.LATEST: |
|---|
| 559 | | case Aggregation.LAST: |
|---|
| 560 | | DetachedCriteria latestObs = DetachedCriteria.forClass( |
|---|
| 561 | | Obs.class).add(Restrictions.eq("person", who)).add( |
|---|
| 562 | | Restrictions.eq("concept", question)); |
|---|
| 563 | | if (dateCriterion != null) |
|---|
| 564 | | latestObs = latestObs |
|---|
| 565 | | .add(dateCriterion); |
|---|
| 566 | | latestObs = latestObs.setProjection( |
|---|
| 567 | | Projections.max("obsDatetime")); |
|---|
| 568 | | if (dateCriterion != null) |
|---|
| 569 | | criteria.add(dateCriterion); |
|---|
| 570 | | criteria.add( |
|---|
| 571 | | Property.forName("obsDatetime").eq(latestObs)); |
|---|
| 572 | | dateCriterion = null; |
|---|
| 573 | | break; |
|---|
| 574 | | case Aggregation.EARLIEST: |
|---|
| 575 | | case Aggregation.FIRST: |
|---|
| 576 | | DetachedCriteria earliestObs = DetachedCriteria.forClass( |
|---|
| 577 | | Obs.class).add(Restrictions.eq("person", who)).add( |
|---|
| 578 | | Restrictions.eq("concept", question)); |
|---|
| 579 | | if (dateCriterion != null) |
|---|
| 580 | | earliestObs = earliestObs |
|---|
| 581 | | .add(dateCriterion); |
|---|
| 582 | | earliestObs = earliestObs.setProjection( |
|---|
| 583 | | Projections.min("obsDatetime")); |
|---|
| 584 | | if (dateCriterion != null) |
|---|
| 585 | | criteria.add(dateCriterion); |
|---|
| 586 | | criteria.add( |
|---|
| 587 | | Property.forName("obsDatetime").eq(earliestObs)); |
|---|
| 588 | | dateCriterion = null; |
|---|
| 589 | | } |
|---|
| 590 | | } |
|---|
| 591 | | |
|---|
| 592 | | if (dateCriterion != null) |
|---|
| 593 | | criteria.add(dateCriterion); |
|---|
| 594 | | criteria.addOrder(Order.asc(OBS_DATETIME)); |
|---|
| 595 | | if (projection != null) |
|---|
| 596 | | criteria.setProjection(projection); |
|---|
| 597 | | |
|---|
| 598 | | List<Obs> result; |
|---|
| 599 | | |
|---|
| 600 | | if (singleNumericResult) { |
|---|
| 601 | | Object numericResult = criteria.uniqueResult(); |
|---|
| 602 | | Double resultValue = Double.parseDouble(numericResult.toString()); |
|---|
| 603 | | result = new Vector<Obs>(); |
|---|
| 604 | | Obs obs = new Obs(); |
|---|
| 605 | | obs.setConcept(question); |
|---|
| 606 | | obs.setObsDatetime(new Date()); |
|---|
| 607 | | obs.setValueNumeric(resultValue); |
|---|
| 608 | | result.add(obs); |
|---|
| 609 | | } else { |
|---|
| 610 | | |
|---|
| 611 | | result = criteria.list(); |
|---|
| 612 | | |
|---|
| 613 | | if (aggregation != null) { |
|---|
| 614 | | switch (aggregation.getType()) { |
|---|
| 615 | | case Aggregation.N_LAST: |
|---|
| 616 | | case Aggregation.N_LATEST: |
|---|
| 617 | | if (result.size() > aggregation.getN()) { |
|---|
| 618 | | List<Obs> tail = new Vector<Obs>(); |
|---|
| 619 | | for (int i = result.size() - aggregation.getN(); i < result |
|---|
| 620 | | .size(); i++) { |
|---|
| 621 | | tail.add(result.get(i)); |
|---|
| 622 | | } |
|---|
| 623 | | result = tail; |
|---|
| 624 | | } |
|---|
| 625 | | break; |
|---|
| 626 | | case Aggregation.N_FIRST: |
|---|
| 627 | | case Aggregation.N_EARLIEST: |
|---|
| 628 | | if (result.size() > aggregation.getN()) { |
|---|
| 629 | | List<Obs> head = new Vector<Obs>(); |
|---|
| 630 | | for (int i = 0; i < aggregation.getN(); i++) { |
|---|
| 631 | | head.add(result.get(i)); |
|---|
| 632 | | } |
|---|
| 633 | | result = head; |
|---|
| 634 | | } |
|---|
| 635 | | break; |
|---|
| 636 | | } |
|---|
| 637 | | } |
|---|
| 638 | | |
|---|
| 639 | | } |
|---|
| 640 | | return result; |
|---|
| | 379 | if ( concepts != null ) { |
|---|
| | 380 | criteria.add(Restrictions.in("concept", concepts)); |
|---|
| | 381 | } |
|---|
| | 382 | if ( fromDate != null ) { |
|---|
| | 383 | criteria.add(Restrictions.gt("obsDatetime", fromDate)); |
|---|
| | 384 | } |
|---|
| | 385 | if ( toDate != null ) { |
|---|
| | 386 | criteria.add(Restrictions.lt("obsDatetime", toDate)); |
|---|
| | 387 | } |
|---|
| | 388 | criteria.addOrder(Order.desc("obsDatetime")); |
|---|
| | 389 | return (List<Obs>)criteria.list(); |
|---|