/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.coala.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Encapsulates a list of patients. Once the list is read the first time, it will be locked and
* cannot be modified anymore. You can also manually lock an instance by calling <code>lock()</code>
*
* @author kmaerz, mwiesner
*/
public class FindPatientResult implements Serializable, Iterable<Patient> {
private static final long serialVersionUID = 1L;
/**
* The internal list of query results
*/
private List<Patient> patientList = new ArrayList<Patient>();
/** The query that generated this result list */
private FindPatientQuery query;
/** if true, the result cannot be modified anymore */
private boolean locked = false;
/** this is the parameter the consents will be sorted by */
private PatientSortParameter sortBy;
/**
* Creates a new Query which can then be filled with results. Don't forget to lock the query
* when done filling in results.
*
* @param sortBy
* The sort criterion used for result list order.
* @param originalQuery the original query string that lead to these results.
*/
public FindPatientResult(FindPatientQuery originalQuery, PatientSortParameter sortBy) {
if ((originalQuery == null))
throw new IllegalArgumentException(
"Upon creation, one must specify the original query for this set of results");
if ((sortBy == null) || (sortBy.equals(PatientSortParameter.UNSORTED)))
{
sortBy = PatientSortParameter.getDefault();
}
this.sortBy = sortBy;
this.query = originalQuery;
}
/**
* Returns the original String that produces these results
* @return the original String that produces these results
*/
public FindPatientQuery getOriginalQuery() {
return query;
}
/**
* Adds a patient to the result. Adding patients can only happen while the result remains
* unlocked. Once it is read in anyway, the list will be locked and trying to add a patient
* results in an IllegalOperationExcaption.
*
* @param patient The patient to add.
*/
public void addPatient(Patient patient) {
if (locked)
throw new IllegalArgumentException(
"Cannot add a patient to a locked list. Has the list been accessd already?");
// insert sorted in place!
if (patientList.isEmpty()) {
patientList.add(patient);
return;
}
else
{
for (int i = 0; i < patientList.size(); i++) {
if (comparePatients(patient, patientList.get(i)) < 0) {
patientList.add(i, patient);
return; // exit, when added
}
}
}
patientList.add(patient); // if consent has never evaluated to "smaller", add to end of list
}
/**
* Adds a set of patients to the result. Adding patients can only happen while the result
* remains unlocked. Once it is read in anyway, the list will be locked and trying to add a
* patient results in an IllegalOperationExcaption.
*
* @param patients The set of patients to add.
*/
public void addAll(Collection<Patient> patients) {
if (locked)
throw new IllegalArgumentException(
"Cannot add a patient to a locked list. Has the list been accessd already?");
for (Patient p : patients) addPatient(p);
}
/**
* Compares two {@link Patient} instances and returns a negative number, if c1 before c2, 0
* if c1 ~ c2 and a positive number if c1 after c2. Comparison is ordinal.
* Do not use output to calculate anything else than sort order.
*
* @param c1
* First {@link Patient} to compare
* @param c2
* First {@link Patient} to compare
* @return returns a negative number, if c1 < c2, 0 if c1 ~ c2 and a
* positive number if c1 > c2. (Comparison is ordinal)
*/
private int comparePatients(Patient c1, Patient c2) {
if (sortBy == PatientSortParameter.UNSORTED)
return 0;
else if (sortBy == PatientSortParameter.BIRTHDATE_NEWEST_FIRST)
return c1.getBirthdate().compareTo(c2.getBirthdate());
else if (sortBy == PatientSortParameter.BIRTHDATE_OLDEST_FIRST)
return -1 * c1.getBirthdate().compareTo(c2.getBirthdate());
else if (sortBy == PatientSortParameter.GIVENNAME_ASCENDING)
return c1.getGivenName().compareTo(c2.getGivenName());
else if (sortBy == PatientSortParameter.GIVENNAME_DESCENDING)
return -1 * c1.getGivenName().compareTo(c2.getGivenName());
else if (sortBy == PatientSortParameter.LASTNAME_ASCENDING)
return c1.getLastName().compareTo(c2.getLastName());
else if (sortBy == PatientSortParameter.LASTNAME_DESCENDING)
return -1 * c1.getLastName().compareTo(c2.getLastName());
else if (sortBy == PatientSortParameter.PID_ASCENDING)
return new Long(c1.getPatientID()).compareTo(new Long(c2.getPatientID()));
else if (sortBy == PatientSortParameter.PID_DESCENDING)
return -1 * new Long(c1.getPatientID()).compareTo(new Long(c2.getPatientID()));
throw new RuntimeException(
"All possibilities checked. This line should never be reached, unless new sort Options have been introduced. Please update sorting algorithm.");
}
/**
* Returns the list of patients as an unmodifiable List.
* @return the list of patients as an unmodifiable List.
*/
public List<Patient> getPatients() {
return Collections.unmodifiableList(patientList);
}
/**
* Locks this result set. After locking it cannot be unlocked again.
*/
public void lock(){
locked = true;
}
// ===========================================================//
// INTERNAL LOGIC ENDS HERE, ITERATION CODE AHEAD //
// ===========================================================//
/**
* Returns an iterator to access all patients from the result
*/
public Iterator<Patient> iterator() {
return new PatientIterator();
}
/**
* Private inner iterator to safely iterate over all patients in the search result. It does not
* support removing patients.
*
* @author kmaerz
*/
private class PatientIterator implements Iterator<Patient> {
private int i = 0; // the next element to return
/**
* True, if the next() method can return another patient
*/
public boolean hasNext() {
return (i < patientList.size());
}
/**
* Returns the next patient
*/
public Patient next() {
locked = true; // lock list forever when it is being read.
Patient result = patientList.get(i);
i++;
return result;
}
/**
* Not supported for security reasons
*/
public void remove() {
throw new UnsupportedOperationException(
"Removing patients from a search result is not supported.");
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("FindPatientResult [patientList=");
builder.append(patientList);
builder.append(", query=");
builder.append(query);
builder.append(", locked=");
builder.append(locked);
builder.append("]");
return builder.toString();
}
}