/** * Get the non-voided members of the obs group, if this obs is a group. By default this method * only returns non-voided group members. To get all group members, use * {@link #getGroupMembers(boolean)} with value true. * <p> * If it's not a group (i.e. {@link #getConcept()}.{@link org.openmrs.Concept#getSet()} is not * true, then this returns null. * * @return a Set<Obs> of the members of this group. * @see #addGroupMember(Obs) * @see #hasGroupMembers() */ public Set<Obs> getGroupMembers() { //same as just returning groupMembers return getGroupMembers(false); }
/** * Convenience method that checks for nullity and length to determine if this obs has group * members. The parameter specifies if this method whether or not voided obs should be * considered. * * @param includeVoided determines if Voided members should be considered as group members. * @return true if this is the parent group of other Obs * @should return true if this obs has group members based on parameter */ public boolean hasGroupMembers(boolean includeVoided) { // ! symbol used because if it's not empty, we want true return !org.springframework.util.CollectionUtils.isEmpty(getGroupMembers(includeVoided)); }
/** * Convenience method to remove an Obs from this grouping This also removes the link in the * given <code>obs</code>object to this obs grouper * * @param member Obs to remove from this group * @see #setGroupMembers(Set) * @see #getGroupMembers() * @should return true when an obs is removed * @should return false when a non existent obs is removed */ public void removeGroupMember(Obs member) { if (member == null || getGroupMembers() == null) { return; } if (groupMembers.remove(member)) { member.setObsGroup(null); } }
/** * This method will add given Collection of obs and their group members to encounter * * @param obsToAdd Collection of obs that need to be added recursively * @param encounter the encounter to which the obs will be added */ private void addGivenObsAndTheirGroupMembersToEncounter(Collection<Obs> obsToAdd, Encounter encounter) { for (Obs o : obsToAdd) { encounter.addObs(o); Set<Obs> groupMembers = o.getGroupMembers(true); if (CollectionUtils.isNotEmpty(groupMembers)) { addGivenObsAndTheirGroupMembersToEncounter(groupMembers, encounter); } } }
/** * This method will remove given Collection of obs and their group members from encounter * * @param obsToRemove Collection of obs that need to be removed recursively * @param encounter the encounter from which the obs will be removed */ private void removeGivenObsAndTheirGroupMembersFromEncounter(Collection<Obs> obsToRemove, Encounter encounter) { for (Obs o : obsToRemove) { encounter.removeObs(o); Set<Obs> groupMembers = o.getGroupMembers(true); if (CollectionUtils.isNotEmpty(groupMembers)) { removeGivenObsAndTheirGroupMembersFromEncounter(groupMembers, encounter); } } }
private void saveObsGroup(Obs obs, String changeMessage){ if (obs.isObsGrouping()) { for (Obs o : obs.getGroupMembers(true)) { Context.getObsService().saveObs(o, changeMessage); } } }
private void evictObsAndChildren(Obs obs) { Context.evictFromSession(obs); if(obs.hasGroupMembers()) { for(Obs member : obs.getGroupMembers()) { evictObsAndChildren(member); } } }
/** * Convenience method to add the given <code>obs</code> to this grouping. Will implicitly make * this obs an ObsGroup. * * @param member Obs to add to this group * @see #setGroupMembers(Set) * @see #getGroupMembers() * @should return true when a new obs is added as a member * @should return false when a duplicate obs is added as a member */ public void addGroupMember(Obs member) { if (member == null) { return; } if (getGroupMembers() == null) { groupMembers = new HashSet<>(); } // a quick sanity check to make sure someone isn't adding // itself to the group if (member.equals(this)) { throw new APIException("Obs.error.groupCannotHaveItselfAsAMentor", new Object[] { this, member }); } member.setObsGroup(this); groupMembers.add(member); }
Set<Obs> ret = new HashSet<>(); if (this.isObsGrouping()) { ret.addAll(this.getGroupMembers()); Obs parentObs = this; while (parentObs.getObsGroup() != null) { for (Obs obsSibling : parentObs.getObsGroup().getGroupMembers()) { if (!obsSibling.isObsGrouping()) { ret.add(obsSibling); for (Obs obsSibling : this.getObsGroup().getGroupMembers()) { if (!obsSibling.isObsGrouping()) { ret.add(obsSibling);
/** * Convenience method to recursively get all leaf obs of this encounter. This method goes down * into each obs and adds all non-grouping obs to the return list * * @param obsParent current obs to loop over * @return list of leaf obs */ private List<Obs> getObsLeaves(Obs obsParent) { List<Obs> leaves = new ArrayList<>(); if (obsParent.hasGroupMembers()) { for (Obs child : obsParent.getGroupMembers()) { if (!child.getVoided()) { if (!child.isObsGrouping()) { leaves.add(child); } else { // recurse if this is a grouping obs leaves.addAll(getObsLeaves(child)); } } } } else if (!obsParent.getVoided()) { leaves.add(obsParent); } return leaves; }
/** * @see org.openmrs.api.db.ObsDAO#saveObs(org.openmrs.Obs) */ @Override public Obs saveObs(Obs obs) throws DAOException { if (obs.hasGroupMembers() && obs.getObsId() != null) { // hibernate has a problem updating child collections // if the parent object was already saved so we do it // explicitly here for (Obs member : obs.getGroupMembers()) { if (member.getObsId() == null) { saveObs(member); } } } sessionFactory.getCurrentSession().saveOrUpdate(obs); return obs; }
private Obs getNewVersionOfEditedObs(Obs parentObs, Obs originalObs){ for(Obs childObs: parentObs.getGroupMembers()){ if(originalObs.equals(childObs.getPreviousVersion())){ return childObs; } } return null; }
/** * @see Obs#getGroupMembers(boolean) */ @Test public void getGroupMembers_shouldGetAllGroupMembersIfPassedTrueAndNonvoidedIfPassedFalse() throws Exception { Obs parent = new Obs(1); Set<Obs> members = new HashSet<>(); members.add(new Obs(101)); members.add(new Obs(103)); Obs voided = new Obs(99); voided.setVoided(true); members.add(voided); parent.setGroupMembers(members); members = parent.getGroupMembers(true); assertEquals("set of all members should have length of 3", 3, members.size()); members = parent.getGroupMembers(false); assertEquals("set of non-voided should have length of 2", 2, members.size()); members = parent.getGroupMembers(); // should be same as false assertEquals("default should return non-voided with length of 2", 2, members.size()); }
@Test public void saveEncounter_shouldUpdateValueOfLeafObsAndNotDuplicateAtEncounterLevel() { executeDataSet(ENC_OBS_HIERARCHY_DATA_XML); Encounter encounter = Context.getEncounterService().getEncounter(100); assertEquals(1, encounter.getObsAtTopLevel(true).size()); Obs topLevelObs = encounter.getObsAtTopLevel(true).iterator().next(); topLevelObs.getGroupMembers().iterator().next().setValueText("editing first obs"); encounter.addObs(topLevelObs); Encounter savedEncounter = Context.getEncounterService().saveEncounter(encounter); assertEquals(1, savedEncounter.getObsAtTopLevel(true).size()); }
private Obs saveObsNotDirty(Obs obs, String changeMessage) { if(!obs.isObsGrouping()){ return obs; } ObsService os = Context.getObsService(); boolean refreshNeeded = false; for (Obs o : obs.getGroupMembers(true)) { if (o.getId() == null) { os.saveObs(o, null); } else { Obs newObs = os.saveObs(o, changeMessage); refreshNeeded = !newObs.equals(o) || refreshNeeded; } } if(refreshNeeded) { Context.refreshEntity(obs); } return obs; }
/** * @see ObsService#saveObs(Obs,String) */ @Test public void saveObs_shouldNotVoidAnObsWithNoChanges() { executeDataSet(ENCOUNTER_OBS_XML); ObsService os = Context.getObsService(); Obs obs = os.getObs(14); assertFalse(obs.getGroupMembers(true).isEmpty()); assertFalse(obs.getGroupMembers(false).isEmpty()); assertFalse(obs.isDirty()); Set<Obs> originalMembers = new HashSet<>(obs.getGroupMembers()); for (Obs o : originalMembers) { assertFalse(o.isDirty()); } Obs saveObs = os.saveObs(obs, "no change"); assertEquals(obs, saveObs); assertFalse(saveObs.getVoided()); Set<Obs> savedMembers = new HashSet<>(saveObs.getGroupMembers()); assertFalse(saveObs.isDirty()); for (Obs o : savedMembers) { assertFalse("obs"+o.getId(), o.isDirty()); } }
/** * This method gets the revision obs for voided obs * * @see ObsService#getRevisionObs(Obs) */ @Test public void shouldGetRevisedObs() { executeDataSet(INITIAL_OBS_XML); executeDataSet(REVISION_OBS_XML); ObsService os = Context.getObsService(); Obs initialObs = os.getObsByUuid("uuid14"); Obs revisedObs = os.getRevisionObs(initialObs); assertEquals(17, revisedObs.getId().intValue()); assertEquals(2, revisedObs.getGroupMembers(true).size()); }
Set<Obs> originalMembers = new HashSet<>(origParentObs.getGroupMembers(true)); assertEquals(3, originalMembers.size()); assertTrue(originalMembers.contains(obsService.getObs(9))); assertEquals(4, newParentObs.getGroupMembers(true).size()); assertTrue(newParentObs.getGroupMembers(true).contains(obsService.getObs(9))); assertTrue(newParentObs.getGroupMembers(true).contains(obsService.getObs(10))); assertTrue(newParentObs.getGroupMembers(true).contains(obsService.getObs(groupMember.getObsId())));
@Test public void saveEncounter_shouldSaveEncounterWhenTopLevelObsIsUpdatedByRemovingChildObs() { executeDataSet(ENC_OBS_HIERARCHY_DATA_XML); EncounterService es = Context.getEncounterService(); ObsService os = Context.getObsService(); Encounter enc = es.getEncounter(100); Obs oParent = os.getObs(100); Obs oChild = os.getObs(101); oParent.removeGroupMember(oChild); es.saveEncounter(enc); Context.flushSession(); Context.clearSession(); enc = es.getEncounter(100); Set<Obs> obsAtTopLevel = enc.getObsAtTopLevel(true); assertEquals(2,obsAtTopLevel.size()); //oChild's new version is still associated to encounter but not part of the oParent anymore assertTrue(obsAtTopLevel.contains(os.getObs(100))); Obs newObs = obsAtTopLevel.stream().filter(obs -> obs.getObsId() != 100 ).findFirst().get(); //Find the other top level obs which is not 100. i.e. the new obs which is a clone of 101 assertNotNull(newObs.getPreviousVersion()); assertEquals(oChild.getObsId(), newObs.getPreviousVersion().getObsId()); assertTrue(os.getObs(100).getGroupMembers(true).contains(os.getObs(102))); //The oChild will still be associated to the parent because when we save oChild, we create a new instance //and void the oChild using ObsServiceImpl.voidExistingObs(). We use Context.evictFromSession(obs); to get a fresh copy //there by losing the change we made to oChild. assertTrue(os.getObs(100).getGroupMembers(true).contains(os.getObs(101))); }
@Test public void saveEncounter_shouldUpdateExistingEncounterWhenAChildObsIsEdited() { executeDataSet(ENC_OBS_HIERARCHY_DATA_XML); EncounterService es = Context.getEncounterService(); ObsService os = Context.getObsService(); Encounter enc = es.getEncounter(100); Obs o = os.getObs(101); o.setValueText("Obs value updated"); es.saveEncounter(enc); Context.flushSession(); Context.clearSession(); updateSearchIndex(); enc = es.getEncounter(100); Set<Obs> obsAtTopLevelUpdated = enc.getObsAtTopLevel(true); Obs oParent = os.getObs(100); final Obs editedObs = os.getObs(101); Obs o2 = os.getObs(102); Obs o3 = getNewVersionOfEditedObs(oParent,editedObs); assertEquals(1,obsAtTopLevelUpdated.size()); assertEquals(3, oParent.getGroupMembers(true).size()); assertTrue(editedObs.getVoided()); assertFalse(oParent.getVoided()); assertFalse(o2.getVoided()); assertNotNull(o3); assertFalse(o3.getVoided()); assertEquals("Obs value updated", o3.getValueText()); }