/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.api.ReportService;
import org.openmrs.cohort.CohortDefinition;
import org.openmrs.report.EvaluationContext;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
/**
* This class represents a list of patientIds. If it is generated from a CohortDefinition via
* {@link ReportService#evaluate(org.openmrs.report.ReportSchema, Cohort, EvaluationContext)} then
* it will contain a link back to the CohortDefinition it came from and the EvalutionContext that
* definition was evaluated in.
*
* @see org.openmrs.cohort.CohortDefinition
*/
@Root(strict = false)
public class Cohort extends BaseOpenmrsData implements Serializable {
public static final long serialVersionUID = 0L;
private transient Log log = LogFactory.getLog(this.getClass());
private Integer cohortId;
private String name;
private String description;
private Set<Integer> memberIds;
private CohortDefinition cohortDefinition;
private EvaluationContext evaluationContext;
public Cohort() {
memberIds = new TreeSet<Integer>();
}
/**
* Convenience constructor to create a Cohort object that has an primarykey/internal identifier
* of <code>cohortId</code>
*
* @param cohortId the internal identifier for this cohort
*/
public Cohort(Integer cohortId) {
this();
this.cohortId = cohortId;
}
/**
* This constructor does not check whether the database contains patients with the given ids,
* but
*
* @see CohortService.saveCohort(Cohort) will.
* @param name
* @param description optional description
* @param ids option array of Integer ids
*/
public Cohort(String name, String description, Integer[] ids) {
this();
this.name = name;
this.description = description;
if (ids != null)
memberIds.addAll(Arrays.asList(ids));
}
/**
* This constructor does not check whether the database contains patients with the given ids,
* but
*
* @see CohortService.saveCohort(Cohort) will.
* @param name
* @param description optional description
* @param patients optional array of patients
*/
public Cohort(String name, String description, Patient[] patients) {
this(name, description, (Integer[]) null);
if (patients != null)
for (Patient p : patients)
memberIds.add(p.getPatientId());
}
/**
* This constructor does not check whether the database contains patients with the given ids,
* but
*
* @see CohortService.saveCohort(Cohort) will.
* @param patientsOrIds optional collection which may contain Patients, or patientIds which may
* be Integers, Strings, or anything whose toString() can be parsed to an Integer.
*/
@SuppressWarnings("unchecked")
public Cohort(Collection patientsOrIds) {
this(null, null, patientsOrIds);
}
/**
* This constructor does not check whether the database contains patients with the given ids,
* but
*
* @see CohortService.saveCohort(Cohort) will.
* @param name
* @param description optional description
* @param patientsOrIds optional collection which may contain Patients, or patientIds which may
* be Integers, Strings, or anything whose toString() can be parsed to an Integer.
*/
@SuppressWarnings("unchecked")
public Cohort(String name, String description, Collection patientsOrIds) {
this(name, description, (Integer[]) null);
if (patientsOrIds != null) {
for (Object o : patientsOrIds) {
if (o instanceof Patient)
memberIds.add(((Patient) o).getPatientId());
else if (o instanceof Integer)
memberIds.add((Integer) o);
else
memberIds.add(Integer.valueOf(o.toString()));
}
}
}
/**
* Convenience contructor taking in a string that is a list of comma separated patient ids This
* constructor does not check whether the database contains patients with the given ids, but
*
* @see CohortService.saveCohort(Cohort) will.
* @param commaSeparatedIds
*/
public Cohort(String commaSeparatedIds) {
this();
for (StringTokenizer st = new StringTokenizer(commaSeparatedIds, ","); st.hasMoreTokens();) {
String id = st.nextToken();
memberIds.add(new Integer(id.trim()));
}
}
/**
* @return Returns a comma-separated list of patient ids in the cohort.
*/
public String getCommaSeparatedPatientIds() {
StringBuilder sb = new StringBuilder();
for (Iterator<Integer> i = getMemberIds().iterator(); i.hasNext();) {
sb.append(i.next());
if (i.hasNext()) {
sb.append(",");
}
}
return sb.toString();
}
public boolean contains(Patient patient) {
return getMemberIds() != null && getMemberIds().contains(patient.getPatientId());
}
public boolean contains(Integer patientId) {
return getMemberIds() != null && getMemberIds().contains(patientId);
}
public String toString() {
StringBuilder sb = new StringBuilder("Cohort id=" + getCohortId());
if (getName() != null)
sb.append(" name=" + getName());
if (getMemberIds() != null)
sb.append(" size=" + getMemberIds().size());
return sb.toString();
}
public boolean equals(Object obj) {
if (this.getCohortId() == null)
return false;
if (obj instanceof Cohort) {
Cohort c = (Cohort) obj;
return (this.getCohortId().equals(c.getCohortId()));
}
return false;
}
public int hashCode() {
if (this.getCohortId() == null)
return super.hashCode();
int hash = 8;
hash = 31 * this.getCohortId() + hash;
return hash;
}
public void addMember(Integer memberId) {
getMemberIds().add(memberId);
}
public void removeMember(Integer memberId) {
getMemberIds().remove(memberId);
}
public int size() {
return getMemberIds() == null ? 0 : getMemberIds().size();
}
public int getSize() {
return size();
}
public boolean isEmpty() {
return size() == 0;
}
// static utility methods
/**
* Returns the union of two cohorts
*
* @param a The first Cohort
* @param b The second Cohort
* @return Cohort
*/
public static Cohort union(Cohort a, Cohort b) {
Cohort ret = new Cohort();
ret.setName("(" + a.getName() + " + " + b.getName() + ")");
if (a != null)
ret.getMemberIds().addAll(a.getMemberIds());
if (b != null)
ret.getMemberIds().addAll(b.getMemberIds());
return ret;
}
/**
* Returns the intersection of two cohorts
*
* @param a The first Cohort
* @param b The second Cohort
* @return Cohort
*/
public static Cohort intersect(Cohort a, Cohort b) {
Cohort ret = new Cohort();
ret.setName("(" + (a == null ? "NULL" : a.getName()) + " * " + (b == null ? "NULL" : b.getName()) + ")");
if (a != null && b != null) {
ret.getMemberIds().addAll(a.getMemberIds());
ret.getMemberIds().retainAll(b.getMemberIds());
}
return ret;
}
/**
* Subtracts a cohort from a cohort
*
* @param a the original Cohort
* @param b the Cohort to subtract
* @return Cohort
*/
public static Cohort subtract(Cohort a, Cohort b) {
Cohort ret = new Cohort();
ret.setName("(" + a.getName() + " - " + b.getName() + ")");
if (a != null) {
ret.getMemberIds().addAll(a.getMemberIds());
if (b != null)
ret.getMemberIds().removeAll(b.getMemberIds());
}
return ret;
}
// getters and setters
@Attribute(required = false)
public Integer getCohortId() {
return cohortId;
}
@Attribute(required = false)
public void setCohortId(Integer cohortId) {
this.cohortId = cohortId;
}
@Element(required = false)
public String getDescription() {
return description;
}
@Element(required = false)
public void setDescription(String description) {
this.description = description;
}
@Element(required = false)
public String getName() {
return name;
}
@Element(required = false)
public void setName(String name) {
this.name = name;
}
@ElementList(required = true)
public Set<Integer> getMemberIds() {
return memberIds;
}
/**
* This method is only here for some backwards compatibility with the PatientSet object that
* this Cohort object replaced. Do not use this method.
*
* @deprecated use #getMemberIds()
* @return the memberIds
*/
public Set<Integer> getPatientIds() {
return getMemberIds();
}
@ElementList(required = true)
public void setMemberIds(Set<Integer> memberIds) {
this.memberIds = memberIds;
}
/**
* @return the cohortDefinition
*/
@Element(required = false)
@Deprecated
public CohortDefinition getCohortDefinition() {
return cohortDefinition;
}
/**
* @param cohortDefinition the cohortDefinition to set
*/
@Element(required = false)
@Deprecated
public void setCohortDefinition(CohortDefinition cohortDefinition) {
this.cohortDefinition = cohortDefinition;
}
/**
* @return the evaluationContext
*/
@Element(required = false)
@Deprecated
public EvaluationContext getEvaluationContext() {
return evaluationContext;
}
/**
* @param evaluationContext the evaluationContext to set
*/
@Element(required = false)
@Deprecated
public void setEvaluationContext(EvaluationContext evaluationContext) {
this.evaluationContext = evaluationContext;
}
/**
* @since 1.5
* @see org.openmrs.OpenmrsObject#getId()
*/
public Integer getId() {
return getCohortId();
}
/**
* @since 1.5
* @see org.openmrs.OpenmrsObject#setId(java.lang.Integer)
*/
public void setId(Integer id) {
setCohortId(id);
}
}