/*****************************************************************************
 *                                                                           *
 *  Copyright (c) 2010 by SANTEC/TUDOR www.santec.tudor.lu                   *
 *                                                                           *
 *                                                                           *
 *  This library is free software; you can redistribute it and/or modify it  *
 *  under the terms of the GNU Lesser General Public License as published    *
 *  by the Free Software Foundation; either version 2 of the License, or     *
 *  (at your option) any later version.                                      *
 *                                                                           *
 *  This software is distributed in the hope that it will be useful, but     *
 *  WITHOUT ANY WARRANTY; without even the implied warranty of               *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        *
 *  Lesser General Public License for more details.                          *
 *                                                                           *
 *  You should have received a copy of the GNU Lesser General Public         *
 *  License along with this library; if not, write to the Free Software      *
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  *
 *                                                                           *
 *****************************************************************************/
package lu.tudor.santec.gecamed.patient.ejb.session.beans;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import lu.tudor.santec.gecamed.core.utils.FileUtils;
import lu.tudor.santec.gecamed.core.utils.IncidentFileInfo;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.core.utils.ServerConfig;
import lu.tudor.santec.gecamed.esante.utils.GecamedToPdfConverterServer;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Incident;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntry;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntryType;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.MeasurementType;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.MeasurementValue;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager;
import lu.tudor.santec.gecamed.prescription.ejb.entity.beans.Prescription;
import lu.tudor.santec.gecamed.usermanagement.ejb.entity.beans.GecamedUser;
import lu.tudor.santec.gecamed.usermanagement.ejb.session.interfaces.LoginInterface;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

/**
 * Incident Manager Session Bean
 * 
 * @author martin.heinemann@tudor.lu
 * 
 * 
 * @version <br>
 *          $Log: IncidentManagerBean.java,v $
 *          Revision 1.87  2014-02-11 12:32:28  ferring
 *          Only logging when incidents have been found
 *
 *          Revision 1.86  2013-12-20 15:56:20  ferring
 *          Letters are replaced and copied correctly again
 *
 *          Revision 1.85  2013-12-13 15:26:27  troth
 *          *** empty log message ***
 *
 *          Revision 1.84  2013-11-25 13:16:40  ferring
 *          preventing log message "Could not find a matching IncidentEntryType object"
 *
 *          Revision 1.83  2013-11-18 15:37:03  ferring
 *          Restructured methods with SoapSender and DocumentWorker restructured.
 *          Checking the IPID, if it changes and refreshing the data.
 *
 *          Revision 1.82  2013-11-15 08:46:42  ferring
 *          deleting empty incidents in delete statement instead of getting them via select and removing them one by one
 *
 *          Revision 1.81  2013-11-14 18:17:17  donak
 *          Fixed versioning issue between JODConverter (Java 1.6) and JBOSS (Java 1.5). Server-side PDF ==> PDF/A conversion should work now.
 *          Fixed IncidentEntry getBinaryContent(). Now a call to this functions always provides the binary content of an incident entry, if any. function works on client and server side.
 *          Implemented function to update incident entry upload status w/o updating all bean properties.
 *          Fixed issue with retrieving default user inactivity logout delay from database
 *
 *          Revision 1.80  2013-11-12 12:48:23  donak
 *          Document upload:
 *          * conversion to pdf/a using open office has been moved to the server. OpenOffice 4 has to be located in the jboss work directory. ATTENTION: it still has to be evaluated if the license agreement dialog occurs when instance is started the first time on the server.
 *          * If document contains a description, the first forty characters of the description followed by three dots will be used as title instead of the filename
 *          * Upload of incident type letters has been fixed
 *          * upload for docx files has been added
 *
 *          Upload parameters:
 *          * database does now support storage of user dependent properties
 *          * The system will automatically remember the last chosen values for confidentiality, facility type, and speciality and propose them as default when the next document will be uploaded.
 *
 *          Inactivity Monitor:
 *          * the event mouse wheel scrolling is now taken into account for resetting the logoff timer
 *          * the logoff delay is now stored in the database. If the database does not contain this parameter, it will be created
 *
 *          General:
 *          * Optimized incident entry bean handling. Caching will now avoid copying the binary content and the generated pdf content of an incident entry as these elements should only be loaded when needed. Now it should be save to re-implement a proper getBinaryContent() handling.
 *
 *          Revision 1.79  2013-10-29 09:45:27  troth
 *          The new consultation view with more entries and the sickleave version 3 fix several bugs.
 *
 *          Revision 1.78  2013-10-23 13:19:31  ferring
 *          FileOpening fixed
 *
 *          Revision 1.77  2013-10-10 13:30:51  ferring
 *          java 1.6 method replaced by java 1.5 method
 *
 *          Revision 1.76  2013-10-10 13:08:56  donak
 *          Upload of prescriptions to eSanté DSP
 *
 *          Revision 1.75  2013-10-10 11:28:50  donak
 *          Integration of cda unique document id is now persistent context menu now adapts to the upload status of a document
 *
 *          Revision 1.74  2013-09-19 12:24:43  ferring
 *          eSante bugs fixed and documents stored in database
 *
 *          Revision 1.73  2013-07-15 06:18:35  ferring
 *          logging changed
 *
 *          Revision 1.72  2013-06-26 15:30:16  troth
 *          Add function to load xsl-fo template form server.
 *
 *          Revision 1.71  2013-06-11 08:52:21  troth
 *          There is a mistake in the database the filename and original filename are reversed by the entry type letter so the function loadBinary(IncidentEntry entry) get a if case.
 *
 *          Revision 1.70  2013-06-10 08:22:14  ferring
 *          eSante POC
 *
 *          Revision 1.69  2013-04-11 14:09:56  troth
 *          Add warring if patients files not found to logger.
 *
 *          Revision 1.68  2013-02-12 16:56:07  troth
 *          Fix ticket #1149 - Can't delete a measurement group in the history.
 *
 *          Revision 1.67  2013-02-08 15:27:17  ferring
 *          Option added for files and letters to attach them to another incident
 *
 *          Revision 1.66  2012-06-04 06:03:01  ferring
 *          file overview added in tools
 *
 *          Revision 1.65  2012-05-14 11:56:22  ferring
 *          query changed wrong exidently
 *
 *          Revision 1.64  2012-04-24 14:01:55  troth
 *          Add logger info when deleting incident.
 *
 *          Revision 1.63  2012-01-24 10:20:58  ferring
 *          Native Queries to Named Queries
 *
 *          Revision 1.62.2.1  2012-01-20 09:13:53  ferring
 *          BRANCHED VERSION
 *
 *          Revision 1.62  2011-03-21 14:18:56  troth
 *          Add one step to the database clear up script which try to fix incident entries where the incident id is null (over the incident id of there childs).
 *
 *          Revision 1.61  2010-11-05 15:06:29  troth
 *          sub the new dialog to the main menu bar for delete the incidents how have no incident entries. The function of the dialog is now implement in the function 'create Incidententries for Prescription how have one together'.
 *
 *          Revision 1.60  2010-11-03 17:45:06  troth
 *          expansion of the function that "create Incident Entries for Prescription how have one together" now it also
 *          1. sync the incidentIds of Prescriptions and there Incident Entry
 *          2. deletes Incidents how have no Incident Entries and no back link from a Prescription
 *
 *          Revision 1.59  2010-10-15 14:57:42  troth
 *          add function to create Incidententries for Prescription how have one together
 *
 *          Revision 1.58  2010-10-13 15:02:53  troth
 *          Add new dialog to the main menu bar for delete the incidents how have no incident entries.
 *
 *          Revision 1.57  2010-10-13 07:28:00  hermen
 *          changed query for deleteNullIncident
 *
 *          Revision 1.56  2010-10-13 07:22:15  hermen
 *          added time logging
 *
 *          Revision 1.55  2010-10-12 08:12:19  troth
 *          Bug fix - edit select query form function deleteNullIncident
 *
 *          Revision 1.54  2010-10-12 07:56:17  troth
 *          Bug fix - add where clause how check the patient id to deleteNullIncident function in IncidentManager
 *
 *          Revision 1.53  2010-09-30 07:02:41  ferring
 *          Method added to get an incident between 2 dates
 *
 *          Revision 1.52  2010-09-28 16:12:29  troth
 *          Complete - # 663: Accident entry can not be individually deleted from the history view.
 *          http://santec.tudor.lu/trac/gecamed/ticket/663
 *
 *          Revision 1.51  2010-09-20 13:38:37  troth
 *          add delete function on (right-click) history popupmenu for S.O.A.P. entries and measurements
 *
 *          Revision 1.50  2010-09-17 09:04:35  troth
 *          Ticket # 634: Letztes Measurement Feld kann nicht gel�scht werden
 *          http://santec.tudor.lu/trac/gecamed/ticket/634
 *
 *          Revision 1.49  2010-09-15 13:12:45  troth
 *          Complete - # 633: Letzter S.O.A.P. Eintrag kann nicht gelo�scht werden
 *          http://santec.tudor.lu/trac/gecamed/ticket/633
 *
 *          Revision 1.48  2010-09-13 13:35:22  troth
 *          code-cleanup
 *          bug fix add some if conditions to catch Null-Pointer-Exceptions
 *
 *          Revision 1.47  2010-09-10 16:28:04  troth
 *          Ticket #632: Fehler beim Speichern des Patienten
 *          http://santec.tudor.lu/trac/gecamed/ticket/632
 *
 *          Ticket #634: Letztes Measurement Feld kann nicht gel�scht werden
 *          http://santec.tudor.lu/trac/gecamed/ticket/633
 *
 *          Revision 1.46  2010-09-09 15:57:39  troth
 *          1. Now all S.O.A.P entries can be deleted
 *          2. Now measurements can be deleted
 *          3. Bug fix that create a empty entry form type prescription when saving the consultation
 *
 *          Revision 1.45  2010-09-06 16:18:03  troth
 *          Fix Bug - Now the parent_accident_incident_id of accident child can be deleted
 *
 *          Revision 1.44  2010-05-27 14:42:00  troth
 *          add logger
 *
 *          Revision 1.43  2010-05-26 16:33:34  troth
 *          bugfix - change the way to get a new and create a incident. rename the method getRecentIncident() in class PatientPanel to getCurrentIncident()
 *
 *          Revision 1.42  2009-05-06 16:00:05  heinemann
 *          added method to generate printable output of the incident entrys
 *
 *          Revision 1.41  2009-02-27 15:25:56  hermen
 *          added button to create an empty incident for a patient visit
 *
 *          Revision 1.40  2008-11-12 17:16:33  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.39  2008-09-25 09:43:06  heinemann
 *          fixed copyrights
 *
 *          Revision 1.38  2008-09-17 14:07:13  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.37  2008-07-10 10:14:32  hermen
 *          added delete incidentEntry by ID
 *
 *          Revision 1.36  2008-05-27 14:13:08  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.35  2008-05-16 14:21:30  mack
 *          Added name of missing type for logging
 *
 *          Revision 1.34  2008-05-15 09:47:50  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.33  2008-04-11 14:47:41  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.32  2008-04-11 13:01:14  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.31  2008-04-11 09:56:45  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.30  2008-04-10 14:19:30  heinemann
 *          added original filename o the IncidentEntry table.
 *          differs to filename which is the generated name of the timestamp+originalfilename
 *
 *          Revision 1.29  2008-04-10 14:07:25  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.28  2008-04-10 12:25:42  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.27  2008-04-09 14:47:05  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.26  2008-04-09 09:39:43  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.25  2008-04-08 13:15:32  hermen
 *          added dicom entry to medical history
 *
 *          Revision 1.24  2008-03-28 15:55:20  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.23  2008-03-28 14:56:36  heinemann
 *          *** empty log message ***
 *
 *          Revision 1.22  2008-03-27 13:48:59  weitz
 *          *** empty log message ***
 * <br>
 *          Revision 1.21 2008-03-27 12:35:53 weitz <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.20 2008-03-20 16:08:14 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.19 2008-03-11 17:17:11 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.18 2008-03-10 12:37:52 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.17 2008-03-06 15:34:26 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.16 2007-12-17 14:59:59 heinemann <br>
 *          plugins and file store and open <br>
 *          <br>
 *          Revision 1.15 2007-11-26 10:13:21 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.14 2007-11-21 15:17:23 heinemann <br>
 *          checkin without warranty!! <br>
 *          <br>
 *          Revision 1.13 2007-11-20 08:06:36 heinemann <br>
 *          Prepare file storage <br>
 *          <br>
 *          Revision 1.12 2007-10-22 09:58:14 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.11 2007-10-16 08:23:26 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.11 2007/08/30 06:41:57 heinemann <br>
 *          fixed TransientObjectException in saveIncident method occuring while
 *          persiting an incident with attached MeasurementValue that have a
 *          different Incident object. Fix can be found in the method
 *          measurementChecker <br>
 *          <br>
 *          Revision 1.10 2007/07/31 05:51:49 hermen <br>
 *          findbugs code cleanup <br>
 *          <br>
 *          Revision 1.9 2007/06/18 11:31:36 hermen <br>
 *          cleanup of old stuff and moved some beans <br>
 *          <br>
 *          Revision 1.8 2007/04/26 07:19:14 heinemann <br>
 *          sysout removed <br>
 *          <br>
 *          Revision 1.7 2007/04/24 13:48:43 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.6 2007/04/11 07:38:46 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.5 2007/03/02 08:28:44 hermen <br>
 *          initial checkin after the merge of PatientModuleRebuild with the
 *          main HEAD <br>
 *          <br>
 *          Revision 1.3.2.6 2007/02/22 12:01:23 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.3.2.5 2007/02/08 16:45:11 heinemann <br>
 *          many changes <br>
 *          <br>
 *          Revision 1.3.2.4 2007/01/24 12:48:56 heinemann <br>
 *          consultation and prescription update control. <br>
 *          Modifications are displayed. <br>
 *          And Incidents are not created if nothing has been entered in
 *          consultation, accident and prescription <br>
 *          <br>
 *          Revision 1.3.2.3 2006/12/14 10:41:17 hermen <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.3.2.2 2006/12/13 15:57:59 heinemann <br>
 *          many changes <br>
 *          <br>
 *          Revision 1.3.2.1 2006/12/06 07:49:18 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.3 2006/12/01 14:50:42 heinemann <br>
 *          initial checkin <br>
 */
@Stateless
public class IncidentManagerBean implements IncidentManager {
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(IncidentManagerBean.class.getName());

	@PersistenceContext(unitName = "gecam")
	EntityManager em;

	@EJB
	LoginInterface login;

	// @EJB
	// PrescriptionManager prescriptionManager;

	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager#getMeasurementTypes()
	 */
	@SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
	public List<MeasurementType> getMeasurementTypes() {
		/* ============================================= */
		List<MeasurementType> result = em.createNamedQuery(
				MeasurementType.FIND_ALL).getResultList();
		return result;
		/* ============================================= */
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager#saveIncident(lu.tudor.santec.gecamed.patient.ejb.entity.beans.v1.Incident)
	 */
	// @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
	public Incident saveIncident(Incident incident) {
		/* ============================================= */
		if (incident == null)
			return null;

		
		Integer userId = login.getCurrentUserID();
		// if new incident
		if (!incident.isPersistent()) {
			// set date and creator
			if (incident.getIncidentDate() == null) {
				incident.setIncidentDate(new Date());
			}
			incident.setCreatedBy(userId);
			incident.setCreated(new Date());
		} else {
			// modified entry
			incident.setModified(new Date());
			incident.setModifiedBy(userId);
		}

		/* ------------------------------------------------------- */
		// load already persisted IncidentEntries to attach them
		// to the list of the incident.
		// Otherwise they would loose their reference to this incident
		/* ------------------------------------------------------- */
		if (incident.isPersistent()) {
			/* ------------------------------------------------------- */
			Incident persistedIncident = getIncident(incident.getId());
			// the incident entries
			if (incident.getIncidentEntries() != null
					&& persistedIncident.getIncidentEntries() != null) {
				
				List<IncidentEntry> currentEntries = incident.getIncidentEntries();
				
				List<IncidentEntry> dbEntries = persistedIncident.getIncidentEntries();

				// add entries that exist in the db to the incident
				for (IncidentEntry dbEntry : dbEntries) {
					if (!currentEntries.contains(dbEntry))
						currentEntries.add(dbEntry);
				}

				// delete entries that have been deleted on the db from the incident
				List<IncidentEntry> removeItems = new ArrayList<IncidentEntry>();
				for (IncidentEntry currentEntry : currentEntries) {
					if (currentEntry.isPersistent()
							&& !dbEntries.contains(currentEntry))
						removeItems.add(currentEntry);
				}
				if (currentEntries != null && currentEntries.size() > 0) currentEntries.removeAll(removeItems);

				incident.setIncidentEntries(currentEntries);
			}
			/* ------------------------------------------------------- */
		}

		deleteEmptyMeasurements(incident);
		
		createOrDeleteIncidentEntryForMeasurement(incident);

		deleteEmptyIncidentEntries(incident);

		/* ------------------------------------------------------- */
		if (incident.getIncidentEntries() != null) {
			/* ------------------------------------------------------- */
			for (IncidentEntry en : incident.getIncidentEntries()) {
				/* ------------------------------------------------------- */
				en.setIncident(incident);
				/* ------------------------------------------------------- */
				// find the matching type
				/* ------------------------------------------------------- */
				if (!en.getEntryType().isPersistent()) {
					/* ------------------------------------------------------- */
					IncidentEntryType type = getTypeByName(en.getEntryType()
							.getName(), "");
					if (type == null) {
						en.setEntryType(em.merge(en.getEntryType()));
					} else {
						en.setEntryType(type);
					}
					en.setEntryTypeId(en.getEntryType().getId());
					/* ------------------------------------------------------- */
				}

				// just to be sure that we have a date.
				if (en.getCreated() == null) {
					en.setCreated(new Date());
				}
				if (en.getEntryDate() == null) {
					en.setEntryDate(en.getCreated());
				}
				// just to be sure that we have a creator.
				if (en.getCreatedBy() == null) {
					en.setCreatedBy(userId);
				}
				
				if (en.isPersistent()) {
					// modification date
					en.setModified(new Date());
					en.setModifiedBy(userId);
				}
				/* ------------------------------------------------------- */
			}
			/* ------------------------------------------------------- */
		}

		incident = em.merge(incident);

		deleteOrphanMeasurements();
		
		deleteOrphanEntries();
		
		return incident;
	}
	
	/**
	 * Checks if there are Measurements entries that have incident_id null and deletes them.
	 * 
	 */
	private void deleteOrphanMeasurements() {
//		List<MeasurementValue> values = em.createQuery("SELECT OBJECT(o) FROM MeasurementValue o WHERE o.incidentId IS NULL").getResultList();
		List<?> values = em.createNamedQuery(MeasurementType.DELETE_ORPHAN_MEASUREMENTS).getResultList();
		
		if (values != null) {
			for (Object measurementValue : values) {
				em.remove((MeasurementValue)measurementValue);
			}			
		}
	}
	
	/**
	 * Checks if there are IncidentEntry entries that have incident_id null and deletes them.
	 * 
	 */
	public void deleteOrphanEntries() {
//		List<IncidentEntry> incidentEntries = em.createQuery("SELECT OBJECT(o) FROM IncidentEntry o WHERE o.incidentId IS NULL").getResultList();
		List<?> incidentEntries = em.createNamedQuery(IncidentEntry.DELETE_ORPHAN_ENTRIES).getResultList();
		
		if (incidentEntries != null) {
			for (Object entryValue : incidentEntries) {
				em.remove((IncidentEntry)entryValue);
			}
		}
	}
	
	
	/**
	 * Get all patient id's how have Incident with no IncidentEntry and is no accident.
	 * 
	 * @return a Integer list of patient id's
	 */
	public List<Integer> getNullIncident()
	{
//		logger.info("searching Incidents without Entries or Accidents....");
		
		@SuppressWarnings("unchecked")
		List<Integer> patientIds = em.createQuery(
				"SELECT DISTINCT incident.patientId " +
				"FROM Incident incident " +
				"LEFT JOIN incident.incidentEntries as entries " +
				"WHERE entries.incidentId is null " +
				"AND incident.isAccident = false "// +
				//"AND incident.id NOT IN (select incidentId from Prescription)"
				).getResultList();
		
		if (patientIds != null && !patientIds.isEmpty())
			logger.info("there are dd " + patientIds.size() + " Patients with Incidents without Entries or Accidents !!!");
		
		return patientIds;
	}

	
	/**
	 * Checks if there is any Incident from a patient how have no IncidentEntry and is no accident and deletes them.
	 * 
	 * @param patientId the patient id
	 */
	public Integer deleteNullIncident(Integer patientId) {
	    
//	    logger.info("searching Incidents without Entries or Accidents....");
	    long start = System.currentTimeMillis();
		
	    int deleted = em.createNamedQuery(
	    		Incident.DELETE_NULL_INCIDENTS_OF_PATIENT)
	    		.setParameter("patientId", patientId)
	    		.executeUpdate();
	    
	    if (deleted > 0)
	    	logger.info("deleting " + deleted + " empty incidents took " + (System.currentTimeMillis()-start)/1000 + " sec.");
	    
	    return deleted;
	    
//		List<Incident> incidents = em.createNamedQuery(Incident.DELETE_NULL_INCIDENTS_OF_PATIENT).setParameter("patientId", patientId).getResultList();
//		
//		logger.info("searching Incidents took " + (System.currentTimeMillis()-start)/1000 + " sec.");
//		if (incidents != null) {
//		    logger.info("deleting " + incidents.size() + " Incidents without Entries or Accidents....");
//			for (Incident incidentValue : incidents) {
//				logger.info("deleting incident id:" + incidentValue.getId() + " without Entries or Accidents....");
//				em.remove(incidentValue);
//			}
//			return Integer.valueOf(incidents.size());
//		}else
//			return Integer.valueOf(0);
	}

	/**
	 * Checks if there are entries witch empty from type S.O.A.P and deletes them.
	 * 
	 * @param incident
	 */
	private void deleteEmptyIncidentEntries(Incident incident) {
		/* ====================================================== */
		if (incident == null)
			return;
		
		if (incident.getIncidentEntries() == null)
			return;
		
		/* ------------------------------------------------------ */
		List<IncidentEntry> vTemp = new ArrayList<IncidentEntry>();
		/* ------------------------------------------------------ */
		for (IncidentEntry v : incident.getIncidentEntries()) {
			
			if(v.getEntryType().getName().equals(IncidentEntryType.TYPE_S) || 
				v.getEntryType().getName().equals(IncidentEntryType.TYPE_O) || 
				v.getEntryType().getName().equals(IncidentEntryType.TYPE_A) || 
				v.getEntryType().getName().equals(IncidentEntryType.TYPE_P) ||
				v.getEntryType().getName().equals(IncidentEntryType.TYPE_CONS_1) ||
				v.getEntryType().getName().equals(IncidentEntryType.TYPE_CONS_2) ||
				v.getEntryType().getName().equals(IncidentEntryType.TYPE_CONS_3) ||
				v.getEntryType().getName().equals(IncidentEntryType.TYPE_SICK_LEAVE)
			) {
				
				// if no data in incident entry, delete it
				if ( (v.getTextContent() == null || "".equals(v.getTextContent())) && 
						(v.getCode() == null || "".equals(v.getCode()))) 
				{
					continue;				
				}
			}

			vTemp.add(v);
			v.setIncident(incident);
		}
		incident.setIncidentEntries(vTemp);
		/* ====================================================== */
	}

	private void createOrDeleteIncidentEntryForMeasurement(Incident incident) {
		/* ------------------------------------------------------- */
		// create an IncidentEntry for the measurement
		/* ------------------------------------------------------- */
		if (incident.getMeasurementValues() != null
				&& incident.getMeasurementValues().size() > 0) {
			/* ------------------------------------------------------- */
			IncidentEntry measEntry = new IncidentEntry();
			measEntry.setEntryType(getTypeByName("measurement", null));
			if (measEntry.getEntryType() != null)
				measEntry.setEntryTypeId(measEntry.getEntryType().getId());
			/* ------------------------------------------------------- */
			// check if a value does already have an entry
			/* ------------------------------------------------------- */
			for (MeasurementValue mesVal : incident.getMeasurementValues()) {
				/* ------------------------------------------------------- */
				if (mesVal.getIncidentEntry() != null) {
					measEntry = mesVal.getIncidentEntry();
					break;
				}
				/* ------------------------------------------------------- */
			}
			/* ------------------------------------------------------- */
			// set the entry to all measurementvalues
			/* ------------------------------------------------------- */
			for (MeasurementValue mesVal : incident.getMeasurementValues()) {
				/* ------------------------------------------------------- */
				mesVal.setIncidentEntry(measEntry);
				/* ------------------------------------------------------- */
			}
			if (incident.getIncidentEntries() == null)
				incident.setIncidentEntries(new ArrayList<IncidentEntry>());
			incident.getIncidentEntries().add(measEntry);
			/* ------------------------------------------------------- */
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager#getIncident(java.lang.Integer)
	 */
	public Incident getIncident(Integer id) {
		/* ================================================== */
		try {
			/* ------------------------------------------------------- */
			Incident in = (Incident) em.createNamedQuery(
					Incident.GET_INCIDENT_BY_ID).setParameter("id", id)
					.getSingleResult();
			if (in != null) {
				/* ------------------------------------------------------- */
				if (in.getIncidentEntries() != null)
					for (IncidentEntry e : in.getIncidentEntries())
						e.getId();
				/* ------------------------------------------------------- */
			}
			return in;
			/* ------------------------------------------------------- */
		} catch (Exception e) {
		}
		return null;
		/* ================================================== */
	}

	/**
	 * Checks if there are measurenments that have null values. and deletes them
	 * 
	 * @param incident
	 */
	private void deleteEmptyMeasurements(Incident incident) {
		/* ====================================================== */
		if (incident == null)
			return;
		
		if (incident.getMeasurementValues() == null)
			return;
		
		List<IncidentEntry> currentIncidentEntries = incident.getIncidentEntries();
		List<IncidentEntry> removeItems = new ArrayList<IncidentEntry>();
		/* ------------------------------------------------------ */
		Set<MeasurementValue> vTemp = new HashSet<MeasurementValue>();
		/* ------------------------------------------------------ */
		for (MeasurementValue v : incident.getMeasurementValues()) {

			// if no data in measurement, delete it
			if ((v.getValueString() == null || "".equals(v.getValueString()))
					&& (v.getValueNumeric() == null)) {
				
				// add the measurement incident entries to the delete-entries-list
				IncidentEntry deleteIncidentEntry = v.getIncidentEntry();
				
				if (currentIncidentEntries != null
						&& currentIncidentEntries.size() > 0) {
					removeItems.add(deleteIncidentEntry);
				}
				continue;
			}

			vTemp.add(v);
			v.setIncident(incident);
		}
		incident.setMeasurementValues(vTemp);
		
		// delete the measurement incident entries
		if(currentIncidentEntries != null && currentIncidentEntries.size() > 0) currentIncidentEntries.removeAll(removeItems);
		// set new incident entries list
		incident.setIncidentEntries(currentIncidentEntries);
		/* ====================================================== */
	}
	
	
	/**
	 * Returns all measurement values that belong to the incident
	 * 
	 * @param incidentId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<MeasurementValue> getMeasurementsByIncidentEntry(Integer incidentEntryId) {
		/* ================================================== */
		if (incidentEntryId == null)
			return null;
		/* ------------------------------------------------------- */
		Query q = em.createNamedQuery(MeasurementType.GET_MEASUREMENTS_BY_INCIDENT_ENTRY);
		q.setParameter("entryId", incidentEntryId);
		try {
			/* --------------------------------------------- */
			return q.getResultList();
			/* --------------------------------------------- */
		} catch (Exception e) {
			/* --------------------------------------------- */
			e.printStackTrace();
			return null;
			/* --------------------------------------------- */
		}
		/* ================================================== */
	}
	
	@SuppressWarnings("unchecked")
	public List<MeasurementValue> getMeasurments(Integer patientId) {
		/* ================================================== */
		if (patientId == null)
			return null;
		/* ------------------------------------------------------- */
		Query q = em.createNamedQuery(MeasurementType.GET_MEASUREMENTS_FOR_PATIENT);
		q.setParameter("patientId", patientId);
		try {
			/* --------------------------------------------- */
			return q.getResultList();
			/* --------------------------------------------- */
		} catch (Exception e) {
			/* --------------------------------------------- */
			e.printStackTrace();
			return null;
			/* --------------------------------------------- */
		}
		/* ================================================== */
	}

	public void saveMeasurementType(MeasurementType type) {
		/* ====================================================== */
		if (type == null)
			return;
		/* ------------------------------------------------------- */
		// try to find a type matching the name
		if (!"".equals(type.getName()) && type.getName() != null) {
			/* ------------------------------------------------------- */
			MeasurementType t = getMeasurementType(type.getName());
			/* ------------------------------------------------------- */
			if (t == null)
				t = new MeasurementType();
			/* ------------------------------------------------------- */
			// copy new data to t
			t.setAlias(type.getAlias());
			t.setDefault(false);
			t.setName(type.getName());
			t.setNumericType(type.isNumericType());
			t.setUnit(type.getUnit());
			/* ------------------------------------------------------- */
			// save
			em.merge(t);
			/* ------------------------------------------------------- */
		}
		/* ====================================================== */
	}

	public MeasurementType getMeasurementType(String name) {
		/* ====================================================== */
		// make a query
		Query q = em.createNamedQuery(MeasurementType.GET_MEASUREMENT_TYPE_BY_NAME);
		q.setParameter("name", name);
		try {
			MeasurementType t = (MeasurementType) q.getSingleResult();
			return t;

		} catch (Exception e) {
			logger.error("Error fetching Measurement Type " + name + " "
					+ e.getLocalizedMessage());
			return null;
		}

		/* ====================================================== */
	}

	@SuppressWarnings("unchecked")
	public List<Incident> getAccidents(Integer patientId) {
		/* ====================================================== */
		if (patientId == null)
			return null;
		/* ------------------------------------------------------- */
		Query q = em.createNamedQuery(Incident.GET_ACCIDENTS_FOR_PATIENT);
		q.setParameter("patientId", patientId);
		try {
			return q.getResultList();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		/* ====================================================== */
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager#getChildAccidentIncidents(java.lang.Integer)
	 */
	public Long getChildAccidentIncidentAmount(Integer incidentId) {
		/* ====================================================== */
		if (incidentId == null)
			return Long.valueOf(0);
		/* ------------------------------------------------------- */
		Query q = em.createNamedQuery(Incident.GET_CHILD_ACCIDENT_INCIDENT_AMOUNT);
		q.setParameter("incId", incidentId);
		try {
			return (Long) q.getSingleResult();
		} catch (Exception e) {
			e.printStackTrace();
			return Long.valueOf(0);
		}
		/* ====================================================== */
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager#setNewAccidentDataForNestedIncidents(lu.tudor.santec.gecamed.patient.ejb.entity.beans.v1.Incident)
	 */
	@SuppressWarnings("unchecked")
	public Incident setNewAccidentDataForNestedIncidents(Incident incident) {
		/* ================================================== */
		if (incident == null)
			return null;
		/* ------------------------------------------------------- */
		// check if the incident is a parent
		Incident parent = null;
		if (incident.getParentAccidentIncidentId() == null)
			parent = incident;
		else {
			parent = getIncident(incident.getParentAccidentIncidentId());
			// set the accident data
			parent.setAccidentDate(incident.getAccidentDate());
			parent.setAccidentNr(incident.getAccidentNr());
			if(!incident.getIsAccident()) incident.setParentAccidentIncidentId(null);
			parent = em.merge(parent);
		}
		/* ------------------------------------------------------- */
		// get all children
		Query q = em.createNamedQuery(Incident.GET_INCIDENTS_BY_PARENT)
				.setParameter("parentId", parent.getId());
//				.setParameter("incidentId", incident.getId());
		try {
			/* ------------------------------------------------------- */
			List<Incident> result = q.getResultList();
			if (result != null) {
				/* ------------------------------------------------------- */
				for (Incident i : result) {
					i.setAccidentDate(parent.getAccidentDate());
					i.setAccidentNr(parent.getAccidentNr());
					if(!incident.getIsAccident()) i.setParentAccidentIncidentId(null);
					em.merge(i);
				}
				/* ------------------------------------------------------- */
			}
			/* ------------------------------------------------------- */
		} catch (Exception e) {
			e.printStackTrace();
		}
		return incident;
		/* ================================================== */
	}

	@SuppressWarnings("unchecked")
	public Incident removeIncidentFromAccidentList(Incident incident) {
		/* ================================================== */
		if (incident == null)
			return null;
		/* ------------------------------------------------------- */
		// if the incident is a child accident, delete the parent
		if (incident.getParentAccidentIncidentId() != null) {
			incident.setParentAccidentIncidentId(null);
			return incident;
		}
		/* ------------------------------------------------------- */
		// if the incident is a parent, find all children and make the first one
		// a parent for the rest
		// get all children
		Query q = em.createNamedQuery(Incident.GET_INCIDENTS_BY_ID_AND_PARENT)
				.setParameter("incidentId", incident.getId());
		try {
			/* ------------------------------------------------------- */
			List<Incident> result = q.getResultList();
			if (result != null) {
				/* ------------------------------------------------------- */
				Incident first = null;
				// take the first
				/* ------------------------------------------------------- */
				if (result.size() > 0) {
					first = result.get(0);
					first.setParentAccidentIncidentId(null);
					first = em.merge(first);
					result.remove(0);

					/* ------------------------------------------------------- */
					for (Incident i : result) {
						// i.setAccidentDate(first.getAccidentDate());
						// i.setAccidentNr(first.getAccidentNr());
						i.setParentAccidentIncidentId(first.getId());
						em.merge(i);
					}
				}
				/* ------------------------------------------------------- */
			}
			/* ------------------------------------------------------- */
		} catch (Exception e) {
			e.printStackTrace();
		}
		return incident;
		/* ================================================== */
	}

//	@SuppressWarnings("unchecked")
//	public void convertIncident(Integer incidentId) {
//		/* ================================================== */
//		Query q = em.createQuery("SELECT OBJECT(o) FROM Incident o "
//				+ "WHERE o.id = :id");
//		q.setParameter("id", incidentId);
//		try {
//			/* ------------------------------------------------------- */
//			List<Incident> inc = q.getResultList();
//			if (inc == null)
//				return;
//			/* ------------------------------------------------------- */
//			for (Incident i : inc)
//				convertConsultations(i);
//			/* ------------------------------------------------------- */
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		/* ================================================== */
//	}

	/**
	 * Converts an old-style consultation to new IncidentEntry
	 * 
	 * @param incidentId
	 * @return
	 */
//	@Deprecated
//	private boolean convertConsultations(Incident inc) {
//		/* ================================================== */
//		if (inc == null)
//			return false;
//		/* ------------------------------------------------------- */
//		// get the incident
//		// Incident inc = this.getIncident(incidentId);
//		// if there is no consultation attached, we do nothing
//		if (inc.getConsultations() == null || inc.getConsultations().size() < 1)
//			return true;
//		logger.info("Converting consultation for incident " + inc.getId());
//		/* ------------------------------------------------------- */
//		// else, convert each consultation
//		List<IncidentEntry> newEntries = new ArrayList<IncidentEntry>(0);
//		/* ------------------------------------------------------- */
//		// iterate over all attached consultations
//		for (Consultation cons : inc.getConsultations()) {
//			/* ------------------------------------------------------- */
//			// ======================================================
//			// Anamnesis S
//			// ======================================================
//			if ((cons.getAnanmesis() != null && !"".equals(cons.getAnanmesis()))
//					|| (cons.getAnamnesisCodes() != null && !"".equals(cons
//							.getAnamnesisCodes()))) {
//				/* ------------------------------------------------------- */
//				// create an IncidentEntry for anamnesis
//				IncidentEntry aEntry = new IncidentEntry();
//				aEntry.setEntryTypeId(getTypeByName(IncidentEntryType.TYPE_S, null).getId());
//				// set general data
//				setGeneralData(aEntry, cons, inc);
//
//				// set anamnesis specific data
//				aEntry.setTextContent(cons.getAnanmesis());
//				aEntry.setCode(cons.getAnamnesisCodes());
//
//				newEntries.add(aEntry);
//				/* ------------------------------------------------------- */
//			}
//			// ====================================================
//			// Findings O
//			// ====================================================
//			if (cons.getFinding() != null && !"".equals(cons.getFinding())) {
//				/* ------------------------------------------------------- */
//				// create an IncidentEntry for Findings
//				IncidentEntry aEntry = new IncidentEntry();
//				aEntry.setEntryTypeId(getTypeByName(IncidentEntryType.TYPE_O, null).getId());
//				// set general data
//				setGeneralData(aEntry, cons, inc);
//
//				// set anamnesis specific data
//				aEntry.setTextContent(cons.getFinding());
//
//				newEntries.add(aEntry);
//				/* ------------------------------------------------------- */
//			}
//			// =======================================================
//			// Diagnosis A
//			// =======================================================
//			if ((cons.getDiagnosis() != null && !"".equals(cons.getDiagnosis()))
//					|| (cons.getDiagnosisCode() != null && !"".equals(cons
//							.getDiagnosisCode()))) {
//				/* ------------------------------------------------------- */
//				// create an IncidentEntry for diagnosis
//				IncidentEntry aEntry = new IncidentEntry();
//				aEntry.setEntryTypeId(getTypeByName(IncidentEntryType.TYPE_A, null).getId());
//				// set general data
//				setGeneralData(aEntry, cons, inc);
//
//				// set anamnesis specific data
//				aEntry.setTextContent(cons.getDiagnosis());
//				aEntry.setCode(cons.getDiagnosisCode());
//
//				newEntries.add(aEntry);
//				/* ------------------------------------------------------- */
//			}
//			// ====================================================
//			// Treatment P
//			// ====================================================
//			if (cons.getTreatment() != null && !"".equals(cons.getTreatment())) {
//				/* ------------------------------------------------------- */
//				// create an IncidentEntry for treatments
//				IncidentEntry aEntry = new IncidentEntry();
//				aEntry.setEntryTypeId(getTypeByName(IncidentEntryType.TYPE_P, null).getId());
//				// set general data
//				setGeneralData(aEntry, cons, inc);
//
//				// set anamnesis specific data
//				aEntry.setTextContent(cons.getTreatment());
//
//				newEntries.add(aEntry);
//				/* ------------------------------------------------------- */
//			}
//			/* ------------------------------------------------------- */
//		}
//		/* ------------------------------------------------------- */
//		// save the new incident entries
//		for (IncidentEntry e : newEntries) {
//			em.merge(e);
//		}
//		return true;
//		/* ================================================== */
//	}

	/**
	 * @param entry
	 * @param consultation
	 * @param incidentId
	 */
//	private void setGeneralData(IncidentEntry entry, Consultation cons,
//			Incident inc) {
//		/* ================================================== */
//		entry.setIncident(inc);
//		entry.setCreated(cons.getCreated());
//		entry.setCreatedBy(cons.getCreatedBy());
//		entry.setEntryDate(cons.getConsultationDate());
//		entry.setModified(cons.getModified());
//		entry.setModifiedBy(cons.getModifiedBy());
//		/* ================================================== */
//	}

	/**
	 * Adds an IncidentEntry object to MeasurementValues. Must be done only once
	 * per installation and only if the installation was made before the switch
	 * to flexi IncidentEntry.
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public boolean convertMeasurementValues() {
		/* ================================================== */
		// get all MeasurementValues without an IncidentEntry
		/* ------------------------------------------------------- */
		Query q = em.createNamedQuery(MeasurementType.GET_MEASUREMENTS_WITHOUT_INCIDENT_ENTRIES);
		try {
			/* --------------------------------------------- */
			List<MeasurementValue> values = q.getResultList();
			if (values == null || values.size() < 1)
				return true;
			/* ------------------------------------------------------- */
			// Create a HashMap to store the Entrys by the incident id
			/* ------------------------------------------------------- */
			HashMap<Integer, IncidentEntry> entries = new HashMap<Integer, IncidentEntry>();

			for (MeasurementValue mesVal : values) {
				/* ------------------------------------------------------- */
				IncidentEntry currEntry = entries.get(mesVal.getIncidentId());
				/* ------------------------------------------------------- */
				// if null, we create a new one
				/* ------------------------------------------------------- */
				if (currEntry == null) {
					/* ------------------------------------------------------- */
					// create a new IncidentEntry
					/* ------------------------------------------------------- */
					currEntry = getEntryForInsert(mesVal.getIncidentId(),
							"measurement");
					Incident incident = mesVal.getIncident();
					currEntry.setCreated(mesVal.getMeasurementDate());
					currEntry.setCreatedBy(incident.getCreatedBy());
					currEntry.setEntryDate(mesVal.getMeasurementDate());
					/* ------------------------------------------------------- */
					// save in the hashmap
					/* ------------------------------------------------------- */
					currEntry = em.merge(currEntry);
					entries.put(mesVal.getIncidentId(), currEntry);
					/* ------------------------------------------------------- */
				}
				/* ------------------------------------------------------- */
				// set the entry to the measuremnt value
				/* ------------------------------------------------------- */
				mesVal.setIncidentEntry(currEntry);
				em.merge(mesVal);
				/* ------------------------------------------------------- */
			}
			/* --------------------------------------------- */
		} catch (Exception e) {
			/* --------------------------------------------- */
			e.printStackTrace();
			return false;
			/* --------------------------------------------- */
		}

		return true;
		/* ================================================== */
	}
	
	
	public List<Integer> getPrescriptionIdsToConvert() {
		/* ============================================== */
		// get all MeasurementValues without an IncidentEntry
		/* ------------------------------------------------------- */
		Query q = em.createNamedQuery(Prescription.GET_PRESCRIPTION_WITHOUT_INCIDENT_ENTRIES);
		try {
			/* --------------------------------------------- */
			List<Prescription> values = q.getResultList();
			List<Integer> idList = new ArrayList<Integer>();
			for (Prescription p : values) {
				/* ============================================== */
				idList.add(p.getId());
				/* ============================================== */
			}
			return idList;
			/* ---------------------------------------------------- */
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
		/* ============================================== */
	}
	

	/**
	 * Adds an IncidentEntry object to Prescriprion. Must be done only once per
	 * installation and only if the installation was made before the switch to
	 * flexi IncidentEntry.
	 * 
	 * @return
	 */
//	@SuppressWarnings("unchecked")
	public boolean convertPrescription(Integer prescId) {
		/* ================================================== */
		// get all MeasurementValues without an IncidentEntry
		/* ------------------------------------------------------- */
//		Query q = em.createQuery("SELECT OBJECT(o) FROM Prescription o "
//				+ "WHERE o.id = :id");
//		q.setParameter("id", prescId);
		try {
			/* --------------------------------------------- */
//			Prescription prescription = (Prescription) q.getSingleResult();
			Prescription prescription = em.find(Prescription.class, prescId);
//			if (values == null || values.size() < 1)
//				return true;
			/* ------------------------------------------------------- */
			// Create a HashMap to store the Entrys by the incident id
			/* ------------------------------------------------------- */
//			HashMap<Integer, IncidentEntry> entries = new HashMap<Integer, IncidentEntry>();
			
			
			
//			for (Prescription mesVal : values) {
				/* ------------------------------------------------------- */
				IncidentEntry currEntry = null;
				/* ------------------------------------------------------- */
				// if null, we create a new one
				/* ------------------------------------------------------- */
				if (currEntry == null) {
					/* ------------------------------------------------------- */
					// create a new IncidentEntry
					/* ------------------------------------------------------- */
					currEntry = getEntryForInsert(prescription.getIncidentId(),
							"prescription");
					Incident incident = getIncident(prescription.getIncidentId());

					currEntry.setCreated(prescription.getCreationDate());
					currEntry.setCreatedBy(incident.getCreatedBy());
					currEntry.setEntryDate(prescription.getPrescriptionDate());
					/* ------------------------------------------------------- */
					// save in the hashmap
					/* ------------------------------------------------------- */
					currEntry = em.merge(currEntry);
//					entries.put(mesVal.getIncidentId(), currEntry);
					/* ------------------------------------------------------- */
				}
				/* ------------------------------------------------------- */
				// set the entry to the measuremnt value
				/* ------------------------------------------------------- */
				prescription.setIncidentEntry(currEntry);
				em.merge(prescription);
				/* ------------------------------------------------------- */
//			}
			/* --------------------------------------------- */
		} catch (Exception e) {
			/* --------------------------------------------- */
			e.printStackTrace();
			return false;
			/* --------------------------------------------- */
		}

		return true;
		/* ================================================== */
	}
	
	
	
//	
//	/**
//	 * Adds an IncidentEntry object to Prescriprion. Must be done only once per
//	 * installation and only if the installation was made before the switch to
//	 * flexi IncidentEntry.
//	 * 
//	 * @return
//	 */
//	@SuppressWarnings("unchecked")
//	public boolean convertPrescriptions() {
//		/* ================================================== */
//		// get all MeasurementValues without an IncidentEntry
//		/* ------------------------------------------------------- */
//		Query q = em.createQuery("SELECT OBJECT(o) FROM Prescription o "
//				+ "WHERE o.incidentEntryId = null ORDER BY o.incidentId ASC");
//		try {
//			/* --------------------------------------------- */
//			List<Prescription> values = q.getResultList();
//			if (values == null || values.size() < 1)
//				return true;
//			/* ------------------------------------------------------- */
//			// Create a HashMap to store the Entrys by the incident id
//			/* ------------------------------------------------------- */
//			HashMap<Integer, IncidentEntry> entries = new HashMap<Integer, IncidentEntry>();
//
//			for (Prescription mesVal : values) {
//				/* ------------------------------------------------------- */
//				IncidentEntry currEntry = entries.get(mesVal.getIncidentId());
//				/* ------------------------------------------------------- */
//				// if null, we create a new one
//				/* ------------------------------------------------------- */
//				if (currEntry == null) {
//					/* ------------------------------------------------------- */
//					// create a new IncidentEntry
//					/* ------------------------------------------------------- */
//					currEntry = getEntryForInsert(mesVal.getIncidentId(),
//							"measurement");
//					Incident incident = getIncident(mesVal.getIncidentId());
//
//					currEntry.setCreated(mesVal.getCreationDate());
//					currEntry.setCreatedBy(incident.getCreatedBy());
//					currEntry.setEntryDate(mesVal.getPrescriptionDate());
//					/* ------------------------------------------------------- */
//					// save in the hashmap
//					/* ------------------------------------------------------- */
//					currEntry = em.merge(currEntry);
//					entries.put(mesVal.getIncidentId(), currEntry);
//					/* ------------------------------------------------------- */
//				}
//				/* ------------------------------------------------------- */
//				// set the entry to the measuremnt value
//				/* ------------------------------------------------------- */
//				mesVal.setIncidentEntry(currEntry);
//				em.merge(mesVal);
//				/* ------------------------------------------------------- */
//			}
//			/* --------------------------------------------- */
//		} catch (Exception e) {
//			/* --------------------------------------------- */
//			e.printStackTrace();
//			return false;
//			/* --------------------------------------------- */
//		}
//
//		return true;
//		/* ================================================== */
//	}

	// /**
	// * Adds an IncidentEntry object to PrescriprionRevisions.
	// * Must be done only once per installation and only if the installation
	// * was made before the switch to flexi IncidentEntry.
	// *
	// * @return
	// */
	// @SuppressWarnings("unchecked")
	// public boolean convertPrescriptionRevisions() {
	// /* ================================================== */
	// // get all PrescriptionRevisions without an IncidentEntry
	// /* ------------------------------------------------------- */
	// Query q = em.createQuery("SELECT OBJECT(o) FROM PrescriptionRevision o "
	// +
	// "WHERE o.incidentEntryId = null ORDER BY o.incidentId ASC");
	// try {
	// /* --------------------------------------------- */
	// List<PrescriptionRevision> values = q.getResultList();
	// if (values == null || values.size() < 1)
	// return true;
	// /* ------------------------------------------------------- */
	// // Create a HashMap to store the Entrys by the incident id
	// /* ------------------------------------------------------- */
	// HashMap<Integer, Prescription> prescriptions = new HashMap<Integer,
	// Prescription>();
	//			
	// /* ------------------------------------------------------- */
	// // for each prescription revision, do a lookup of the
	// // prescription object and copy the incidentEntry
	// /* ------------------------------------------------------- */
	// Prescription currentPrescription = null;
	// for (PrescriptionRevision rev : values) {
	// /* ------------------------------------------------------- */
	// // get tha fitting prescription
	// /* ------------------------------------------------------- */
	// currentPrescription = prescriptions.get(rev.getPrescriptionId());
	// /* ------------------------------------------------------- */
	// // if not yet in the hash, load it from the database
	// /* ------------------------------------------------------- */
	// if (currentPrescription == null) {
	// /* ------------------------------------------------------- */
	// currentPrescription =
	// prescriptionManager.getPrescription(rev.getPrescriptionId());
	// prescriptions.put(currentPrescription.getId(), currentPrescription);
	// /* ------------------------------------------------------- */
	// }
	// /* ------------------------------------------------------- */
	// rev.setIncidentEntry(currentPrescription.getIncidentEntry());
	// rev.setIncidentEntryId(currentPrescription.getIncidentEntryId());
	// /* ------------------------------------------------------- */
	// em.merge(rev);
	// /* ------------------------------------------------------- */
	// }
	// /* --------------------------------------------- */
	// } catch (Exception e) {
	// /* --------------------------------------------- */
	// e.printStackTrace();
	// return false;
	// /* --------------------------------------------- */
	// }
	//		
	// return true;
	// /* ================================================== */
	// }

//	/**
//	 * Returns a Hash of patient id and name for all patients that have at least
//	 * one consultation
//	 * 
//	 * @return
//	 */
//	@SuppressWarnings("unchecked")
//	public HashMap<Integer, String> getPatientNames() {
//		/* ================================================== */
//		Query q1 = em.createNamedQuery(Patient.GET_PATIENTS_WITH_CONSULTATIONS);
//		/* ------------------------------------------------------- */
//		List<Patient> result = q1.getResultList();
//
//		HashMap<Integer, String> data = new HashMap<Integer, String>(0);
//		// now we have all patient with at least one consultation
//		if (result == null)
//			return data;
//		/* ------------------------------------------------------- */
//		for (Patient p : result) {
//			/* ------------------------------------------------------- */
//			data.put(p.getId(), p.toShortString());
//			/* ------------------------------------------------------- */
//		}
//
//		return data;
//		/* ================================================== */
//	}

//	/**
//	 * Simply counts all consultations in the database
//	 * 
//	 * @return
//	 */
//	public Long getIncidentCount() {
//		/* ================================================== */
//		Query q = em.createNamedQuery(Incident.GET_INCIDENTS_WITH_CONSULTATIONS);
//
//		Long count = (Long) q.getSingleResult();
//
//		if (count == null)
//			return 0L;
//		
//		return count;
//		/* ================================================== */
//	}

	/**
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Collection<IncidentEntryType> getAllEntryTypes() {
		/* ================================================== */
		Query q = em.createNamedQuery(IncidentEntry.GET_INCIDENT_ENTRY_TYPES);
		try {
			return q.getResultList();
		} catch (Exception e) {
			e.printStackTrace();
			return new ArrayList<IncidentEntryType>(0);
		}
		/* ================================================== */
	}

	/**
	 * Returns all incidents for the patient that have consultations
	 * 
	 * @param patientId
	 * @return
	 */
//	@SuppressWarnings("unchecked")
//	public List<Integer> getIncidentIdsWithConsultations(Integer patientId) {
//		/* ================================================== */
//		if (patientId == null)
//			return null;
//		/* ------------------------------------------------------- */
//		Query q = em.createNamedQuery(Incident.GET_INCIDENTS_WITH_CONSULTATIONS_FOR_PATIENT)
//				.setParameter("patientId", patientId);
//		try {
//			/* ------------------------------------------------------- */
//			return q.getResultList();
//			/* ------------------------------------------------------- */
//		} catch (Exception e) {
//			e.printStackTrace();
//			return null;
//		}
//		/* ================================================== */
//	}

	/**
	 * Loads the binary content of the incident entry
	 * 
	 * @param entry
	 * @return
	 */
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public IncidentEntry loadBinary (IncidentEntry entry) throws FileNotFoundException, Exception 
	{
		if (entry == null)
			return null;
		
		IncidentEntry en = em.find(IncidentEntry.class, entry.getId());
		
		if (en == null)
			return null;

		/* ------------------------------------------------------- */
		// load the binary dataw
		/* ------------------------------------------------------- */
		// important: there is a mistake in the database the filename and original filename are reversed by the entry type letter
		byte[] b = null;
		if(en.getEntryType().getName().equals(IncidentManager.LETTER))
			b = FileUtils.getGECAMedPatientFile(en.getOriginalFilename(),
				   ServerConfig.getProperty(ServerConfig.PATIENT_FILES_DIR),
				   en.getIncident().getPatientId());
		else if (en.getEntryType().getName().equals(IncidentManager.FILE))
			b = FileUtils.getGECAMedPatientFile(en.getFileName(),
				   ServerConfig.getProperty(ServerConfig.PATIENT_FILES_DIR),
				   en.getIncident().getPatientId());
		else 
			return entry;
		
		entry.setBinaryContent(b);
		return entry;
	}

	
	public byte[] loadBinary (String fileName, Integer patientId)
	{
		try
		{
			return FileUtils.getGECAMedPatientFile(fileName, 
					ServerConfig.getProperty(ServerConfig.PATIENT_FILES_DIR), 
					patientId);
		}
		catch (Exception e)
		{
			logger.log(Level.ERROR, "Couldn't load file "+fileName+" for patient with ID "+patientId, e);
			return null;
		}
			
	}
	

	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public byte[] transformToPdfA(IncidentEntry entry) throws Exception 
	{
		// make sure the binary data of this entry is loaded
		if (entry.getBinaryContent() == null)
			entry = loadBinary(entry);
		
		return GecamedToPdfConverterServer.convert(entry);
	}
	
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void saveUploadIndicator(IncidentEntry entry) {
		em.createNamedQuery(IncidentEntry.SET_UPLOAD_INDICATOR).setParameter("incidentEntryId", entry.getId()).setParameter("cdaUniqueId", entry.getCdaUniqueId()).executeUpdate();
	}
	
	/**
	 * Saves the entry and the attached entry type Returns the merged entry
	 * without binary data. must be loaded separately.
	 * 
	 * @param entry
	 * @return
	 */
	public IncidentEntry saveEntry(IncidentEntry entry, String typename) {
		/* ================================================== */
		return saveEntry(entry, typename, null);
		/* ================================================== */ 
	}
//	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	/**
	 * @param entry
	 * @param typename to search for int the databae
	 * @param mimetype to search for in the database
	 * @return
	 */
	public IncidentEntry saveEntry(IncidentEntry entry, String typename, String mimetype) {
		/* ================================================== */
		if (entry == null)
			return null;
		/* ------------------------------------------------------- */
		try {
			/* ------------------------------------------------------- */
//			// create a new type object if the entry has a property called ENTY_TYPE
//			/* ------------------------------------------------------- */
//			String propTypeName = (String) entry.getProperty(IncidentEntry.ENTRY_NAME);
//			
//			if (propTypeName != null && !"".equals(propTypeName)) {
//				/* ------------------------------------------------------- */
//				IncidentEntryType propType = new IncidentEntryType();
//				propType.setName(propTypeName);
//				entry.setEntryType(propType);
//				/* ------------------------------------------------------- */
//			}
			/* ------------------------------------------------------- */
			// find the matching entry type in the database
			/* ------------------------------------------------------- */
			if (entry.getEntryTypeId() == null || entry.getEntryType() == null
					|| !entry.getEntryType().isPersistent() ) {
				/* ------------------------------------------------------- */
				IncidentEntryType eType = null;
				
				// just to be sure that we have a date.
				if (entry.getCreated() == null) {
					entry.setCreated(new Date());
				}
				if (entry.getEntryDate() == null) {
					entry.setEntryDate(entry.getCreated());
				}
				// just to be sure that we have a creator.
				if (entry.getCreatedBy() == null) {
					entry.setCreatedBy(login.getCurrentUserID());
				}
				
				if (entry.isPersistent()) {
					// modification date
					entry.setModified(new Date());
					entry.setModifiedBy(login.getCurrentUserID());
				}
			
				/* ------------------------------------------------------- */
				// if the entry is of type file, we query the entry type by the mimetype
				/* ------------------------------------------------------- */
				// set the type if there is one
				/* ------------------------------------------------------- */
				if ((typename != null) && typename.length() != 0 && entry.getEntryType() != null) {
					entry.getEntryType().setName(typename);
				}
				/* ------------------------------------------------------- */
				// try to find the object in the database
				/* ------------------------------------------------------- */
				if (entry.getEntryType() != null)
					eType = getType(entry.getEntryType());
				/* ------------------------------------------------------- */
				// if null, try to find by the given type string
				/* ------------------------------------------------------- */
				if (eType == null)
					eType = getTypeByName(typename, mimetype);
				/* ------------------------------------------------------- */
				if (eType != null) {
					/* ------------------------------------------------------- */
					entry.setEntryType(eType);
					entry.setEntryTypeId(eType.getId());
					/* ------------------------------------------------------- */
				} else {
					/* ------------------------------------------------------- */
					if (entry.getEntryType() == null) {
						entry.setEntryType(new IncidentEntryType());
						entry.getEntryType().setMimeType("content/unknown");
					}
					// save a new entry type
					/* ------------------------------------------------------- */
					entry.getEntryType().setName(typename);
					/* ------------------------------------------------------- */
					entry.setEntryType(  em.merge(entry.getEntryType()));
					entry.setEntryTypeId(entry.getEntryType().getId());
				}
				/* ------------------------------------------------------- */
			}

			// reload incident by id
			if (entry.getIncident() == null && entry.getIncidentId() != null) {
				Incident i = em.find(Incident.class, entry.getIncidentId());
				entry.setIncident(i);
			}
			
			/* ------------------------------------------------------- */
			if (entry.getIncident() == null) {
//				entry.setIncident(saveIncident(new Incident()));
				throw new Exception("No incident specified for IncidentEntry");
			}
			/* ------------------------------------------------------- */
			// save file, if present
			/* ------------------------------------------------------- */
			if (entry.getBinaryContent() != null) {
				/* ------------------------------------------------------- */
//				System.out.println("-- BEFORE SAVING FILE --");
//				System.out.println("filename: \""+entry.getFileName()+"\"");
//				System.out.println("org filename: \""+entry.getOriginalFilename()+"\"");
//				entry.setOriginalFilename(entry.getFileName());
				
				String filename;
				if (IncidentManagerBean.LETTER.equals(entry.getEntryType().getName()))
					filename = entry.getOriginalFilename();
				else
					filename = entry.getFileName();
				
				String genFilename = FileUtils.saveGECAMedPatientFile(entry.getBinaryContent(), 
												 filename, 
												 ServerConfig.getProperty(ServerConfig.PATIENT_FILES_DIR), 
												 entry.getIncident().getPatientId());
				
				if (IncidentManagerBean.LETTER.equals(entry.getEntryType().getName()))
					entry.setOriginalFilename(genFilename);
				else
					entry.setFileName(genFilename);
				
				entry.setFileSize((long) entry.getBinaryContent().length);
				
//				System.out.println("-- AFTER SAVING FILE --");
//				System.out.println("filename: \""+entry.getFileName()+"\"");
//				System.out.println("org filename: \""+entry.getOriginalFilename()+"\"");
//				System.out.println("_______________________");
				/* ------------------------------------------------------- */
			}
			/* ------------------------------------------------------- */
			// save the entry
			/* ------------------------------------------------------- */
			entry = em.merge(entry);
			em.flush();
			
			/* outcommented - Reason: nonsense
			 * Test it on null, but don't provoke a NullpointerException, if that was the intention. 
			 */
//			IncidentEntryType t = entry.getEntryType();
//			t.getId();
//			t.getName();
//			t.getMimeType();
			
			return entry;
			/* ------------------------------------------------------- */
		} catch (Exception e) {
			logger.warn("Error while saving incident entry. id = "
					+ entry.getId(), e);
			return null;
		}
		/* ------------------------------------------------------- */

		/* ================================================== */
	}

//	/**
//	 * tries to find an entry type for the given mimetype
//	 * 
//	 * @param mimetype
//	 * @return
//	 */
//	public IncidentEntryType getTypeByMime(String mimetype) {
//		/* ================================================== */
//		Query q = em.createQuery("SELECT OBJECT(o) FROM IncidentEntryType o "
//				+ "WHERE UPPER(o.mimeType) = UPPER(:mime)");
//		q.setParameter("mime", mimetype);
//		try {
//			/* ------------------------------------------------------- */
//			IncidentEntryType ie = (IncidentEntryType) q.getSingleResult();
//			return ie;
//			/* ------------------------------------------------------- */
//		} catch (Exception e) {
//			logger.warn("No incident entry found for mime-type " + mimetype);
//			return null;
//		}
//		/* ================================================== */
//	}

	/**
	 * Creates a new IncidentEntry with prefilled data
	 * 
	 * 
	 * @param incidentId
	 * @return
	 */
	public IncidentEntry getEntryForInsert(Integer incidentId, String entryType) {
		/* ================================================== */
		IncidentEntry entry = new IncidentEntry();
		entry.setEntryType(getTypeByName(entryType, null));
		/* ------------------------------------------------------- */
		entry.setEntryTypeId(entry.getEntryType().getId());
		entry.setIncident(getIncident(incidentId));
		/* ------------------------------------------------------- */
		Date now = new Date();
		// set created date
		entry.setCreated(now);
		/* ------------------------------------------------------- */
		// set consultation date
		entry.setEntryDate(now);
		/* ------------------------------------------------------- */
		// check the user
		entry.setCreatedBy(login.getCurrentUserID());

		return entry;
		/* ================================================== */
	}

	/**
	 * tries to find an entry type for the given name
	 * 
	 * @param mimetype
	 * @return
	 */
	public IncidentEntryType getTypeByName(String name, String mimetype) {
		/* ================================================== */
		Query q = null;
		if (mimetype == null || "".equals(mimetype)) {
			/* ------------------------------------------------------- */
			q = em.createNamedQuery(IncidentEntry.GET_INCIDENT_ENTRY_TYPE_BY_NAME);
			/* ------------------------------------------------------- */
		} else {
			/* ------------------------------------------------------- */
			q = em.createNamedQuery(IncidentEntry.GET_INCIDENT_ENTRY_TYPE_BY_NAME_AND_MIME);
			q.setParameter("mime", mimetype);
			/* ------------------------------------------------------- */
		}
		q.setParameter("name", name);
		try {
			/* ------------------------------------------------------- */
			IncidentEntryType ie = (IncidentEntryType) q.getResultList().get(0);
			return ie;
			/* ------------------------------------------------------- */
		} catch (Exception e) {
			logger.warn("No incident entry found for name " + name);
			return null;
		}
		/* ================================================== */
	}
	
	
	/**
	 * Tries to find a stored type by its name and if set, the
	 * mime type
	 * 
	 * @param type
	 * @return
	 */
	public IncidentEntryType getType (IncidentEntryType type) {
		/* ================================================== */
		if (type == null || type.getName() == null || "".equals(type.getName())) {
			logger.info("Could not find a matching IncidentEntryType object");
			return null;
		}
		/* ------------------------------------------------------- */
		String queryString = "SELECT OBJECT (o) FROM IncidentEntryType o " +
								"WHERE o.name = :name";
		/* ------------------------------------------------------- */
		// append the mimetype
		/* ------------------------------------------------------- */
		if (type.getMimeType() != null)
			queryString += " AND UPPER(o.mimeType) = :mime";
		/* ------------------------------------------------------- */
		Query q = em.createQuery(queryString);
		
		q.setParameter("name", type.getName());
		try {
			/* --------------------------------------------- */
			q.setParameter("mime", type.getMimeType().toUpperCase());
			/* --------------------------------------------- */
		} catch (Exception e) {}
		/* ------------------------------------------------------- */
		try {
			/* --------------------------------------------- */
			return (IncidentEntryType) q.getResultList().get(0);
			/* --------------------------------------------- */
		} catch (Exception e) {
			/* --------------------------------------------- */
			logger.info("Could not find a matching IncidentEntryType for " + type.getName() + " - " + type.getMimeType());
//			e.printStackTrace();
			/* --------------------------------------------- */
		}
		return null;
		/* ================================================== */
	}
	

	public Boolean removeIncidentEntry(IncidentEntry entry) {
		/* ================================================== */
		
		if (entry == null)
			return false;
		
		/* ------------------------------------------------------- */
		// lookup the entity
		IncidentEntry detachedEntry = null;
		try {
			/* --------------------------------------------- */
			detachedEntry = em.find(IncidentEntry.class, entry.getId());
			em.flush();
			/* --------------------------------------------- */
		} catch (Exception e) {
			/* --------------------------------------------- */
			e.printStackTrace();
			return false;
			/* --------------------------------------------- */
		}
		/* ------------------------------------------------------- */
		// delete
		/* ------------------------------------------------------- */
		try {
			/* --------------------------------------------- */
			detachedEntry.getIncident().getIncidentEntries().size();
			detachedEntry.getIncident().getIncidentEntries().remove(detachedEntry);
//			em.merge(detachedEntry.getIncident());
			
			em.remove(detachedEntry);
			em.flush();
			
			/* --------------------------------------------- */
			// remove the attached file
			/* ------------------------------------------------------- */
			if (detachedEntry.getFileName() != null && !"".equals(detachedEntry.getFileName())) {
				/* ------------------------------------------------------- */
				FileUtils.deleteGECAMedPatientFile(detachedEntry.getFileName(),
												   ServerConfig.getProperty(ServerConfig.PATIENT_FILES_DIR), 
												   detachedEntry.getIncident().getPatientId());
				/* ------------------------------------------------------- */
			}
			/* ------------------------------------------------------- */
			Incident inc = detachedEntry.getIncident();
			/* ------------------------------------------------------- */
			// if the incident does not have any entries, we might can delete it.
			/* ------------------------------------------------------- */
			if (inc.getIncidentEntries() == null || inc.getIncidentEntries().size() < 1) {
				/* ------------------------------------------------------- */
				// delete the incident
				/* ------------------------------------------------------- */
				if (!inc.getIsAccident())
					em.remove(inc);
				/* ------------------------------------------------------- */
			}
			
			return true;
			/* --------------------------------------------- */
		} catch (Exception e) {
			/* --------------------------------------------- */
			logger.error("Error while trying to delete IncidentEntry with ID "+entry.getId(), e);
			/* --------------------------------------------- */
		}
		return false;
		/* ================================================== */
	}
	
	
	/* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager#moveIncidentEntry(lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntry, lu.tudor.santec.gecamed.patient.ejb.entity.beans.Incident)
	 */
	public void moveIncidentEntry (IncidentEntry entry2Move, Incident targetIncident)
	{
		if (!targetIncident.isPersistent())
			targetIncident = em.merge(targetIncident);
		
//		Integer sourceIncidentId = entry2Move.getIncidentId();
		entry2Move.setIncident(targetIncident);
		entry2Move.setIncidentId(targetIncident.getId());
		em.merge(entry2Move);
		
//		Incident sourceIncident = em.find(null, sourceIncidentId);
//		if ()
	}
	
	
	public Boolean removeIncidentEntry(Integer incidentEntryID) {
	    return removeIncidentEntry(em.find(IncidentEntry.class, incidentEntryID));
	}
	
	@SuppressWarnings("unchecked")
	public List<Incident> getIncidentsOfPatient (Integer patientId)
	{
		return em.createNamedQuery(Incident.GET_INCIDENTS_BY_PATIENT_ID)
				.setParameter("patientID", patientId)
				.getResultList();
	}
	
	public Incident getIncidentNewerThan(Integer patientId, Integer physicianId, Date newerThan) {
		Calendar olderThan = new GregorianCalendar();
		return getIncidentNewerThan(patientId, physicianId, newerThan, olderThan.getTime());
	}

	public Incident getIncidentNewerThan(Integer patientId, Integer physicianId, Date newerThan, Date olderThan) {
	    try {
		List l = em.createNamedQuery(Incident.GET_INCIDENTS_NEWER_THAN_BY_PATIENTID_AND_PHYSICIANID)
			.setParameter("patientID", patientId)
			.setParameter("physicianId", physicianId)
			.setParameter("newerThan", newerThan)
			.setParameter("olderThan", olderThan)
			.getResultList();
		if (l !=null && l.size() > 0)
			return (Incident) l.get(0);
	    } catch (Exception e) {
	    	logger.warn("Error geting Incident", e);
	    }
	    return null;
	}

	
	/**
	 * Checks if there are Measurements entries that have incident_id null and
	 * deletes them.
	 * 
	 */
	public Boolean deleteMeasurementValues(Integer incidentId) {

		List<MeasurementValue> values = em.createNamedQuery(
				MeasurementType.GET_MEASUREMENT_VALUES_BY_INCIDENT)
						.setParameter("incidentId", incidentId)
						.getResultList();

		if (values != null) {
			for (MeasurementValue measurementValue : values) {
				measurementValue.getIncident().getMeasurementValues().remove(measurementValue);
				em.find(MeasurementValue.class, measurementValue.getId());
				em.remove(measurementValue);
			}
		}
		return null;
	}

	
	/**
	 * Set accident data of Incident to false and delete Incident if it have no entries
	 * 
	 * @param incidentId the id of the accident incident
	 */
	public void deleteAccidentIncident(Integer incidentId) {
		Incident incident = em.find(Incident.class, incidentId);
		// set accident data of Incident to false 
		Integer patientId = incident.getPatientId();
		incident.setAccidentDate(null);
		incident.setAccidentNr(null);
		incident.setIsAccident(false);
		em.merge(incident);
		em.flush();
		// delete Incident if it have no entries
		deleteNullIncident(patientId);
	}

	
	/**
	 * Get all IncidentEntry id's with more than one prescription
	 * 
	 * @return a Integer list of IncidentEntry id's 
	 */
	public List<Integer> getIncidentEntriesIdWithPrescriptions() {

		logger.info("searching Incident Entries with more when one Prescription ...");
	    long startTime = System.currentTimeMillis();
		
	    List<Integer> incidentEntryIds = em.createNamedQuery(IncidentEntry.GET_INCIDENT_ENTRY_IDS)
	    		.getResultList();
		
		logger.info("searching Incident Entries took " + (System.currentTimeMillis()-startTime)/1000 + " sec.");
		return incidentEntryIds;
	}
	
	
	/**
	 * Get all prescriptions of the one incidentEntry
	 * 
	 * @param incidentEntryId
	 * @return a Prescription list of all Prescription
	 */
	public List<Prescription> getAllPrescriptionsOfIncidentEntry(Integer incidentEntryId)
	{
		logger.info("searching Prescriptions of IncidentEntry " + incidentEntryId + " ...");
	    long startTime = System.currentTimeMillis();
		
	    @SuppressWarnings("unchecked")
		List<Prescription> prescriptions = em.createNamedQuery(Prescription.GET_PRESCRIPTION_FOR_INCIDENT_ENTRY)
				.setParameter("incidentEntryId", incidentEntryId)
				.getResultList();
	    
	    logger.info("searching Prescriptions took " + (System.currentTimeMillis()-startTime)/1000 + " sec.");
	    
		return prescriptions;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager#getCorrespondingPrescription(java.lang.Integer)
	 */
	public Prescription getCorrespondingPrescription(Integer incidentEntryId) {
		long startTime = 0l;
		if (logger.isDebugEnabled()) {
			logger.info("searching Prescriptions of IncidentEntry " + incidentEntryId + " ...");
			startTime = System.currentTimeMillis();
		}

		Prescription prescription = null;
		try {
			prescription = (Prescription) em.createNamedQuery(Prescription.GET_PRESCRIPTION_FOR_INCIDENT_ENTRY)
					.setParameter("incidentEntryId", incidentEntryId).getSingleResult();
		} catch (NoResultException nre) {
			;
		} catch (NonUniqueResultException nure) {
			logger.error("Unexpectedly recieved multiple prescriptions for one incident entry with id " + incidentEntryId + " (must just be one).", nure);
		} catch (Exception ex) {
			logger.error("Unable to retrieve prescription for incident entry with id " + incidentEntryId + ":", ex);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("searching Prescriptions took " + (System.currentTimeMillis() - startTime) / 1000 + " sec.");
		}
		return prescription;
	}
	
	
	/**
	 * Get IncidentEntry by id
	 * 
	 * @param incidentEntryId
	 * @return the incidentEntry
	 */
	public IncidentEntry getIncidentEntry(Integer incidentEntryId)
	{
		IncidentEntry incidentEntry = em.find(IncidentEntry.class, incidentEntryId);
		
		return incidentEntry;
	}
	
	/**
	 * Get all IncidentEntries ids where the incident is null.
	 * 
	 * @return a list of IncidentEntries ids.
	 */
	public List<Integer> getIncidentEntriesIdWhereIncidentIdIsNull()
	{
		//SELECT id FROM "patient"."incident_entry" where incident_id is null;
		logger.info("searching IncidentEntries where Incident id is null ...");
	    long startTime = System.currentTimeMillis();
		
	    List<Integer> incidentEntryIdList = em.createNamedQuery(
	    		IncidentEntry.GET_INCIDENT_ENTRY_IDS_WITHOUT_INCIDENT)
	    		.getResultList();
	    
	    logger.info("searching IncidentEntries took " + (System.currentTimeMillis()-startTime)/1000 + " sec.");
		logger.info("found " + incidentEntryIdList.size() + " IncidentEntries.");
	    return incidentEntryIdList;
	}
	
	/**
	 * Deletes a incidentEntry.
	 * 
	 * @param the incidentEntry.
	 */
	public void deleteIncidentEntry(Integer incidentEntryId)
	{    
		IncidentEntry incidentEntryDel = em.find(IncidentEntry.class, incidentEntryId);
		logger.info("deleting IncidentEntry " + incidentEntryId + " ...");
		em.remove(incidentEntryDel);
	}
	

	@SuppressWarnings("unchecked")
	public Collection<IncidentFileInfo> getIncidentFiles (boolean loadApprovedFiles, Physician loadForPhysician)
	{
		StringBuilder				queryString;
		Query						query;
		List<IncidentEntry>			entries;
		List<IncidentFileInfo>		infos;
		Map<Integer, Patient>		patientMap	= new HashMap<Integer, Patient>();
		Map<Integer, Physician>		physicianMap= new HashMap<Integer, Physician>();
		Map<Integer, GecamedUser>	userMap		= new HashMap<Integer, GecamedUser>();
		
		IncidentFileInfo	fileInfo;
		Integer				patientId;
		Patient				patient;
		Integer				physicianId;
		Physician			physician;
		Integer 			userId;
		GecamedUser			user;
		
//		query.append("SELECT OBJECT(e) FROM IncidentEntry e, IncidentEntryType t " 
//		+ "WHERE t.name = :type "
//		+ "AND t.id = e.entryTypeId "
//		+ "AND (e.code IS NULL OR e.code = '') "
//		+ "ORDER BY e.entryDate ASC"
		
		// define the query
		queryString	= new StringBuilder("SELECT OBJECT(e) FROM Incident i, ")
				.append("IncidentEntry e, IncidentEntryType t ") 
				.append("WHERE t.name = :type ")
				.append("AND t.id = e.entryTypeId ")
				.append("AND i.id = e.incidentId ");
		
		if (loadForPhysician != null)
			queryString.append("AND i.physicianId = :physician ");
		
		if (!loadApprovedFiles)
			queryString.append("AND (e.code IS NULL OR e.code = '') ");
		
		queryString.append("ORDER BY i.incidentDate DESC ");
		
		query	= em.createQuery(queryString.toString())
				.setParameter("type", IncidentManager.FILE);
		if (loadForPhysician != null)
			query	= query.setParameter("physician", loadForPhysician.getId());
		
		// get the incident entries
		entries	= query.getResultList();
		
		// get the patient and user IDs
		for (IncidentEntry entry : entries)
		{
			patientId	= entry.getIncident().getPatientId();
			patientMap.put(patientId, null);
			
			physicianId	= entry.getIncident().getPhysicianId();
			physicianMap.put(physicianId, null);
			
			try
			{
				userId	= Integer.parseInt(entry.getCode());
				userMap.put(userId, null);
			}
			catch (Exception e) {}
		}
		
		// load the patients
		for (Integer id : patientMap.keySet())
			patientMap.put(id,	em.find(Patient.class, id));
		
		// load the physicians
		for (Integer id : physicianMap.keySet())
			physicianMap.put(id,em.find(Physician.class, id));
		
		// load the patients
		for (Integer id : userMap.keySet())
			userMap.put(id,		em.find(GecamedUser.class, id));
		
		// create & fill the result list
		infos	= new ArrayList<IncidentFileInfo>(entries.size());
		for (IncidentEntry entry : entries)
		{
			fileInfo	= new IncidentFileInfo();
			patientId	= entry.getIncident().getPatientId();
			patient		= patientMap.get(patientId);
			physicianId	= entry.getIncident().getPhysicianId();
			physician	= physicianMap.get(physicianId);
			
			try
			{
				userId	= Integer.parseInt(entry.getCode());
				user	= userMap.get(userId);
			}
			catch (Exception e) 
			{
				user	= null;
			}
			
			fileInfo.setEntry(entry);
			fileInfo.setPatient(patient);
			fileInfo.setPhysician(physician);
			fileInfo.setUser(user);
			infos.add(fileInfo);
		}
		
		return infos;
	}
	
	/**
	 * Factury function that eases your life
	 * @return An instance of an incident manager bean
	 */
	public static IncidentManager getInstance() {
		return (IncidentManager) ManagerFactory.getRemote(IncidentManagerBean.class);
	}
	
	
	public IncidentEntry setEntryCode(IncidentEntry entry, String code)
	{
		entry	= em.find(IncidentEntry.class, entry.getId());
		entry.setCode(code);
		entry	= em.merge(entry);
		
		return entry;
	}
}