Java tutorial
/******************************************************************************* * Copyright (c) 2015 The Board of Trustees of the Leland Stanford Junior University * BY CLICKING ON "ACCEPT," DOWNLOADING, OR OTHERWISE USING EPAD, YOU AGREE TO THE FOLLOWING TERMS AND CONDITIONS: * STANFORD ACADEMIC SOFTWARE SOURCE CODE LICENSE FOR * "ePAD Annotation Platform for Radiology Images" * * This Agreement covers contributions to and downloads from the ePAD project ("ePAD") maintained by The Board of Trustees * of the Leland Stanford Junior University ("Stanford"). * * * Part A applies to downloads of ePAD source code and/or data from ePAD. * * * Part B applies to contributions of software and/or data to ePAD (including making revisions of or additions to code * and/or data already in ePAD), which may include source or object code. * * Your download, copying, modifying, displaying, distributing or use of any ePAD software and/or data from ePAD * (collectively, the "Software") is subject to Part A. Your contribution of software and/or data to ePAD (including any * that occurred prior to the first publication of this Agreement) is a "Contribution" subject to Part B. Both Parts A and * B shall be governed by and construed in accordance with the laws of the State of California without regard to principles * of conflicts of law. Any legal action involving this Agreement or the Research Program will be adjudicated in the State * of California. This Agreement shall supersede and replace any license terms that you may have agreed to previously with * respect to ePAD. * * PART A. DOWNLOADING AGREEMENT - LICENSE FROM STANFORD WITH RIGHT TO SUBLICENSE ("SOFTWARE LICENSE"). * 1. As used in this Software License, "you" means the individual downloading and/or using, reproducing, modifying, * displaying and/or distributing Software and the institution or entity which employs or is otherwise affiliated with you. * Stanford hereby grants you, with right to sublicense, with respect to Stanford's rights in the Software, a * royalty-free, non-exclusive license to use, reproduce, make derivative works of, display and distribute the Software, * provided that: (a) you adhere to all of the terms and conditions of this Software License; (b) in connection with any * copy, distribution of, or sublicense of all or any portion of the Software, the terms and conditions in this Software * License shall appear in and shall apply to such copy and such sublicense, including without limitation all source and * executable forms and on any user documentation, prefaced with the following words: "All or portions of this licensed * product have been obtained under license from The Board of Trustees of the Leland Stanford Junior University. and are * subject to the following terms and conditions" AND any user interface to the Software or the "About" information display * in the Software will display the following: "Powered by ePAD http://epad.stanford.edu;" (c) you preserve and maintain * all applicable attributions, copyright notices and licenses included in or applicable to the Software; (d) modified * versions of the Software must be clearly identified and marked as such, and must not be misrepresented as being the * original Software; and (e) you consider making, but are under no obligation to make, the source code of any of your * modifications to the Software freely available to others on an open source basis. * * 2. The license granted in this Software License includes without limitation the right to (i) incorporate the Software * into your proprietary programs (subject to any restrictions applicable to such programs), (ii) add your own copyright * statement to your modifications of the Software, and (iii) provide additional or different license terms and conditions * in your sublicenses of modifications of the Software; provided that in each case your use, reproduction or distribution * of such modifications otherwise complies with the conditions stated in this Software License. * 3. This Software License does not grant any rights with respect to third party software, except those rights that * Stanford has been authorized by a third party to grant to you, and accordingly you are solely responsible for (i) * obtaining any permissions from third parties that you need to use, reproduce, make derivative works of, display and * distribute the Software, and (ii) informing your sublicensees, including without limitation your end-users, of their * obligations to secure any such required permissions. * 4. You agree that you will use the Software in compliance with all applicable laws, policies and regulations including, * but not limited to, those applicable to Personal Health Information ("PHI") and subject to the Institutional Review * Board requirements of the your institution, if applicable. Licensee acknowledges and agrees that the Software is not * FDA-approved, is intended only for research, and may not be used for clinical treatment purposes. Any commercialization * of the Software is at the sole risk of you and the party or parties engaged in such commercialization. You further agree * to use, reproduce, make derivative works of, display and distribute the Software in compliance with all applicable * governmental laws, regulations and orders, including without limitation those relating to export and import control. * 5. You or your institution, as applicable, will indemnify, hold harmless, and defend Stanford against any third party * claim of any kind made against Stanford arising out of or related to the exercise of any rights granted under this * Agreement, the provision of Software, or the breach of this Agreement. Stanford provides the Software AS IS and WITH ALL * FAULTS. Stanford makes no representations and extends no warranties of any kind, either express or implied. Among * other things, Stanford disclaims any express or implied warranty in the Software: * (a) of merchantability, of fitness for a particular purpose, * (b) of non-infringement or * (c) arising out of any course of dealing. * * Title and copyright to the Program and any associated documentation shall at all times remain with Stanford, and * Licensee agrees to preserve same. Stanford reserves the right to license the Program at any time for a fee. * 6. None of the names, logos or trademarks of Stanford or any of Stanford's affiliates or any of the Contributors, or any * funding agency, may be used to endorse or promote products produced in whole or in part by operation of the Software or * derived from or based on the Software without specific prior written permission from the applicable party. * 7. Any use, reproduction or distribution of the Software which is not in accordance with this Software License shall * automatically revoke all rights granted to you under this Software License and render Paragraphs 1 and 2 of this * Software License null and void. * 8. This Software License does not grant any rights in or to any intellectual property owned by Stanford or any * Contributor except those rights expressly granted hereunder. * * PART B. CONTRIBUTION AGREEMENT - LICENSE TO STANFORD WITH RIGHT TO SUBLICENSE ("CONTRIBUTION AGREEMENT"). * 1. As used in this Contribution Agreement, "you" means an individual providing a Contribution to ePAD and the * institution or entity which employs or is otherwise affiliated with you. * 2. This Contribution Agreement applies to all Contributions made to ePAD at any time. By making a Contribution you * represent that: (i) you are legally authorized and entitled by ownership or license to make such Contribution and to * grant all licenses granted in this Contribution Agreement with respect to such Contribution; (ii) if your Contribution * includes any patient data, all such data is de-identified in accordance with U.S. confidentiality and security laws and * requirements, including but not limited to the Health Insurance Portability and Accountability Act (HIPAA) and its * regulations, and your disclosure of such data for the purposes contemplated by this Agreement is properly authorized and * in compliance with all applicable laws and regulations; and (iii) you have preserved in the Contribution all applicable * attributions, copyright notices and licenses for any third party software or data included in the Contribution. * 3. Except for the licenses you grant in this Agreement, you reserve all right, title and interest in your Contribution. * 4. You hereby grant to Stanford, with the right to sublicense, a perpetual, worldwide, non-exclusive, no charge, * royalty-free, irrevocable license to use, reproduce, make derivative works of, display and distribute the Contribution. * If your Contribution is protected by patent, you hereby grant to Stanford, with the right to sublicense, a perpetual, * worldwide, non-exclusive, no-charge, royalty-free, irrevocable license under your interest in patent rights embodied in * the Contribution, to make, have made, use, sell and otherwise transfer your Contribution, alone or in combination with * ePAD or otherwise. * 5. You acknowledge and agree that Stanford ham may incorporate your Contribution into ePAD and may make your * Contribution as incorporated available to members of the public on an open source basis under terms substantially in * accordance with the Software License set forth in Part A of this Agreement. You further acknowledge and agree that * Stanford shall have no liability arising in connection with claims resulting from your breach of any of the terms of * this Agreement. * 6. YOU WARRANT THAT TO THE BEST OF YOUR KNOWLEDGE YOUR CONTRIBUTION DOES NOT CONTAIN ANY CODE OBTAINED BY YOU UNDER AN * OPEN SOURCE LICENSE THAT REQUIRES OR PRESCRIBES DISTRBUTION OF DERIVATIVE WORKS UNDER SUCH OPEN SOURCE LICENSE. (By way * of non-limiting example, you will not contribute any code obtained by you under the GNU General Public License or other * so-called "reciprocal" license.) *******************************************************************************/ package edu.stanford.epad.epadws.service; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.io.IOUtils; import com.pixelmed.dicom.Attribute; import com.pixelmed.dicom.AttributeList; import com.pixelmed.dicom.AttributeTag; import com.pixelmed.dicom.CodeStringAttribute; import com.pixelmed.dicom.DateAttribute; import com.pixelmed.dicom.DecimalStringAttribute; import com.pixelmed.dicom.DicomException; import com.pixelmed.dicom.IntegerStringAttribute; import com.pixelmed.dicom.LongStringAttribute; import com.pixelmed.dicom.PersonNameAttribute; import com.pixelmed.dicom.ShortStringAttribute; import com.pixelmed.dicom.SpecificCharacterSet; import com.pixelmed.dicom.TagFromName; import com.pixelmed.dicom.TimeAttribute; import com.pixelmed.dicom.UniqueIdentifierAttribute; import com.pixelmed.network.ApplicationEntity; import com.pixelmed.network.ApplicationEntityMap; import com.pixelmed.query.QueryTreeModel; import com.pixelmed.query.QueryTreeRecord; import edu.stanford.epad.common.util.EPADConfig; import edu.stanford.epad.common.util.EPADFileUtils; import edu.stanford.epad.dtos.DicomTag; import edu.stanford.epad.dtos.DicomTagList; import edu.stanford.epad.dtos.RemotePAC; import edu.stanford.epad.dtos.RemotePACEntity; import edu.stanford.epad.dtos.RemotePACQueryConfig; import edu.stanford.epad.dtos.internal.DCM4CHEEStudy; import edu.stanford.epad.dtos.internal.DCM4CHEEStudyList; import edu.stanford.epad.epadws.dcm4chee.Dcm4cheeServer; import edu.stanford.epad.epadws.epaddb.EpadDatabase; import edu.stanford.epad.epadws.epaddb.EpadDatabaseOperations; import edu.stanford.epad.epadws.models.Project; import edu.stanford.epad.epadws.models.RemotePACQuery; import edu.stanford.epad.epadws.models.Study; import edu.stanford.epad.epadws.models.Subject; import edu.stanford.epad.epadws.models.User; import edu.stanford.epad.epadws.queries.Dcm4CheeQueries; /** * Class to create Remote PAC Records and Query/Retrieve data for Remote PACs * * @author Dev Gude * */ public class RemotePACService extends RemotePACSBase { static RemotePACService rpsinstance; public static final int MAX_CACHE_ENTRIES = 25000; public static final int MAX_SERIES_QUERY = 500; public static final int MAX_INSTANCE_QUERY = 7000; static Map<String, QueryTreeRecord> remoteQueryCache = new HashMap<String, QueryTreeRecord>(); static Map<String, List<RemotePACEntity>> patientCache = new HashMap<String, List<RemotePACEntity>>(); // SerieUID to userName:projectID public static Map<String, String> pendingTransfers = new HashMap<String, String>(); // AETitle to userName public static Map<String, String> monitorTransfers = new HashMap<String, String>(); public static Map<String, Long> monitorStart = new HashMap<String, Long>(); public static DicomTagList dicomTags = null; public static RemotePACService getInstance() throws Exception { if (rpsinstance == null) { rpsinstance = new RemotePACService(); } return rpsinstance; } private RemotePACService() throws DicomException, IOException { super(); } public static void checkPropertiesFile() { File propertiesFile = new File(EPADConfig.getEPADRemotePACsConfigFilePath()); //if (!propertiesFile.exists()) { //cavit updated BufferedReader reader = null; InputStream is = null; StringBuilder sb = new StringBuilder(); String lineTemp = null; try { is = EPADFileUtils.class.getClassLoader().getResourceAsStream(propertiesFile.getName()); reader = new BufferedReader(new InputStreamReader(is, "UTF8")); String line = null; while ((line = reader.readLine()) != null) { if (line.equals("Dicom.RemoteAEs.local.CalledAETitle=EPAD_DCM")) { lineTemp = "Dicom.RemoteAEs." + EPADConfig.aeTitle.toString() + ".CalledAETitle=" + EPADConfig.aeTitle.toString(); sb.append(lineTemp); sb.append("\n"); lineTemp = null; } else if (line.equals("Dicom.CallingAETitle=EPAD_DCM")) { lineTemp = line.replaceAll("EPAD_DCM", EPADConfig.aeTitle.toString()); sb.append(lineTemp); sb.append("\n"); lineTemp = null; } else if (line.equals("Dicom.RemoteAEs.local.HostNameOrIPAddress=_HOSTNAME_")) { lineTemp = "Dicom.RemoteAEs." + EPADConfig.aeTitle.toString() + ".HostNameOrIPAddress=" + EPADConfig.dicomServerIP.toString(); sb.append(lineTemp); sb.append("\n"); lineTemp = null; } else if (line.equals("Dicom.RemoteAEs.local.PrimaryDeviceType=WSD")) { lineTemp = "Dicom.RemoteAEs." + EPADConfig.aeTitle.toString() + ".PrimaryDeviceType=WSD"; sb.append(lineTemp); sb.append("\n"); lineTemp = null; } else if (line.equals("Dicom.RemoteAEs.local.Port=11112")) { lineTemp = "Dicom.RemoteAEs." + EPADConfig.aeTitle.toString() + ".Port=11112"; sb.append(lineTemp); sb.append("\n"); lineTemp = null; } else if (line.equals("Dicom.RemoteAEs=local")) { lineTemp = "Dicom.RemoteAEs=" + EPADConfig.aeTitle.toString(); sb.append(lineTemp); sb.append("\n"); lineTemp = null; } else { sb.append(line); sb.append("\n"); } } } catch (Exception x) { log.warning("Error creating properties file", x); return; } finally { if (reader != null) IOUtils.closeQuietly(reader); else if (is != null) IOUtils.closeQuietly(is); } EPADFileUtils.write(propertiesFile, sb.toString()); //cavit // } } public static DicomTagList getDicomTags() { if (dicomTags != null) return dicomTags; File dicomTagFile = new File(EPADConfig.getEPADWebServerEtcDir() + "dicomtags.txt"); BufferedReader reader = null; InputStream is = null; if (!dicomTagFile.exists()) { StringBuilder sb = new StringBuilder(); try { is = EPADFileUtils.class.getClassLoader().getResourceAsStream(dicomTagFile.getName()); reader = new BufferedReader(new InputStreamReader(is, "UTF8")); String line = null; while ((line = reader.readLine()) != null) { sb.append(line); sb.append("\n"); } } catch (Exception x) { log.warning("Error creating tags file", x); return null; } finally { if (reader != null) IOUtils.closeQuietly(reader); else if (is != null) IOUtils.closeQuietly(is); } EPADFileUtils.write(dicomTagFile, sb.toString()); } DicomTagList dclist = new DicomTagList(); try { is = EPADFileUtils.class.getClassLoader().getResourceAsStream(dicomTagFile.getName()); reader = new BufferedReader(new InputStreamReader(is, "UTF8")); String line = null; while ((line = reader.readLine()) != null) { if (line.trim().startsWith("#")) continue; String[] fields = line.split(","); if (fields.length < 3) continue; if (fields[1].trim().length() < 8) continue; DicomTag tag = new DicomTag(fields[0], fields[2], "0x" + fields[1].substring(0, 4), "0x" + fields[1].substring(4, 8), "", ""); dclist.addDicomTag(tag); } } catch (Exception x) { log.warning("Error creating tags file", x); return null; } finally { if (reader != null) IOUtils.closeQuietly(reader); else if (is != null) IOUtils.closeQuietly(is); } dicomTags = dclist; return dclist; } /** * Get all configured remote PACs * @return */ public List<RemotePAC> getRemotePACs() throws Exception { Dcm4cheeServer instanceDcm4cheeServer = new Dcm4cheeServer(); instanceDcm4cheeServer.connect(); List<String[]> connectionList = instanceDcm4cheeServer.listAetitle(); int atpos = -1; int control = 0; List<RemotePAC> rps = new ArrayList<RemotePAC>(); ApplicationEntityMap aeMap = networkApplicationInformation.getApplicationEntityMap(); for (Object aeName : aeMap.keySet()) { ApplicationEntity ae = (ApplicationEntity) aeMap.get(aeName); String localName = networkApplicationInformation .getLocalNameFromApplicationEntityTitle(aeName.toString()); RemotePAC rp = new RemotePAC(localName, ae.getDicomAETitle(), ae.getPresentationAddress().getHostname(), ae.getPresentationAddress().getPort(), ae.getQueryModel(), ae.getPrimaryDeviceType()); //cavit for (int i = 0; i < connectionList.size(); i++) { String[] strArray = new String[4]; strArray = (connectionList.get(i)); if (ae.getDicomAETitle().equals(strArray[1])) { control = 1; atpos = i; } } if (control == 1) { control = 0; } else { instanceDcm4cheeServer.addAetitle(ae.getDicomAETitle(), ae.getPresentationAddress().getHostname(), Integer.toString(ae.getPresentationAddress().getPort())); } //cavit rps.add(rp); } instanceDcm4cheeServer = null; instanceDcm4cheeServer = new Dcm4cheeServer(); instanceDcm4cheeServer.connect(); //cavit connectionList.clear(); connectionList = instanceDcm4cheeServer.listAetitle(); for (int i = 0; i < connectionList.size(); i++) { String[] strArraya = new String[4]; strArraya = (connectionList.get(i)); control = 0; for (Object aeName : aeMap.keySet()) { ApplicationEntity ae = (ApplicationEntity) aeMap.get(aeName); String localName = networkApplicationInformation .getLocalNameFromApplicationEntityTitle(aeName.toString()); if (((strArraya[1].equals(ae.getDicomAETitle())))) { control = 1; atpos = i; } } if (control == 1) { control = 0; } else { addRemotePAC(strArraya[1], strArraya[1], strArraya[2], Integer.parseInt(strArraya[3]), null, "WSD"); } } instanceDcm4cheeServer = null; //cavit if (EPADConfig.getParamValue("TCIA_APIKEY") != null && EPADConfig.getParamValue("TCIA_APIKEY").length() > 0) { try { List<String> collections = TCIAService.getInstance().getCollections(); //check for null if (collections != null) { for (String collection : collections) { RemotePAC rpac = new RemotePAC(TCIAService.TCIA_PREFIX + collection, TCIAService.TCIA_PREFIX + collection, "services.cancerimagingarchive.net", 443, "", ""); rps.add(rpac); } } Set<String> sharedLists = TCIAService.getInstance().getSharedLists(); if (sharedLists != null) { for (String sharedList : sharedLists) { RemotePAC rpac = new RemotePAC(TCIAService.TCIA_PREFIX + sharedList, TCIAService.TCIA_PREFIX + sharedList, "services.cancerimagingarchive.net", 443, "", ""); rps.add(rpac); } } } catch (Exception e) { log.warning("Error getting TCIA collections", e); } } return rps; } /** * Get remote PAC by PAC ID * @param pacID * @return */ public RemotePAC getRemotePAC(String pacID) { ApplicationEntityMap aeMap = networkApplicationInformation.getApplicationEntityMap(); for (Object aeName : aeMap.keySet()) { ApplicationEntity ae = (ApplicationEntity) aeMap.get(aeName); String localName = networkApplicationInformation .getLocalNameFromApplicationEntityTitle(aeName.toString()); if (localName.equals(pacID)) { return new RemotePAC(localName, ae.getDicomAETitle(), ae.getPresentationAddress().getHostname(), ae.getPresentationAddress().getPort(), ae.getQueryModel(), ae.getPrimaryDeviceType()); } } return null; } /** * Add a Remote PAC to configuration file * @param pac * @throws Exception */ public synchronized void addRemotePAC(String loggedInUser, RemotePAC pac) throws Exception { User user = DefaultEpadProjectOperations.getInstance().getUser(loggedInUser); if (!user.isAdmin() && !user.hasPermission(User.CreatePACPermission)) throw new Exception("No permission to create PAC configuration"); if (pac.pacID.startsWith("tcia")) throw new Exception("Invalid PAC ID:" + pac.pacID); List<RemotePAC> rps = new ArrayList<RemotePAC>(); ApplicationEntityMap aeMap = networkApplicationInformation.getApplicationEntityMap(); for (Object aeName : aeMap.keySet()) { ApplicationEntity ae = (ApplicationEntity) aeMap.get(aeName); String localName = networkApplicationInformation .getLocalNameFromApplicationEntityTitle(aeName.toString()); RemotePAC rp = new RemotePAC(localName, ae.getDicomAETitle(), ae.getPresentationAddress().getHostname(), ae.getPresentationAddress().getPort(), ae.getQueryModel(), ae.getPrimaryDeviceType()); rps.add(rp); } int count = 0; for (RemotePAC p : rps) { //cavit if (p.pacID.equalsIgnoreCase(pac.pacID)) count++; } if (count == 0) { addRemotePAC(pac.pacID, pac.aeTitle, pac.hostname, pac.port, pac.queryModel, pac.primaryDeviceType); } else { throw new Exception("Abbreviation already exist "); } pac = null; } //cavit public synchronized void modifyRemotePAC(String loggedInUser, RemotePAC pac, RemotePAC oldpac) throws Exception { User user = DefaultEpadProjectOperations.getInstance().getUser(loggedInUser); if (pac.pacID.startsWith("tcia")) throw new Exception("This PAC Configuration can not be modified:" + pac.pacID); if (!user.isAdmin() && !user.hasPermission(User.CreatePACPermission)) throw new Exception("No permission to modify PAC configuration"); //cavit List<RemotePAC> rps = new ArrayList<RemotePAC>(); ApplicationEntityMap aeMap = networkApplicationInformation.getApplicationEntityMap(); for (Object aeName : aeMap.keySet()) { ApplicationEntity ae = (ApplicationEntity) aeMap.get(aeName); String localName = networkApplicationInformation .getLocalNameFromApplicationEntityTitle(aeName.toString()); RemotePAC rp = new RemotePAC(localName, ae.getDicomAETitle(), ae.getPresentationAddress().getHostname(), ae.getPresentationAddress().getPort(), ae.getQueryModel(), ae.getPrimaryDeviceType()); rps.add(rp); } int count = 0; for (RemotePAC p : rps) { //cavit if ((p.pacID.equalsIgnoreCase(pac.pacID))) { for (RemotePAC k : rps) { if ((!k.pacID.equalsIgnoreCase(p.pacID)) && (k.aeTitle.equals(pac.aeTitle))) { count++; } } } } if (count == 0) { removeRemotePAC(pac.pacID); //cavit addRemotePAC(loggedInUser, pac); } else { throw new Exception("Pacs name already exist"); } pac = null; } //cavit /** * Modify a Remote PAC in configuration file * @param pac * @throws Exception */ public synchronized void modifyRemotePAC(String loggedInUser, RemotePAC pac) throws Exception { User user = DefaultEpadProjectOperations.getInstance().getUser(loggedInUser); if (pac.pacID.startsWith("tcia")) throw new Exception("This PAC Configuration can not be modified:" + pac.pacID); if (!user.isAdmin() && !user.hasPermission(User.CreatePACPermission)) throw new Exception("No permission to modify PAC configuration"); removeRemotePAC(pac.pacID); addRemotePAC(loggedInUser, pac); } /** * Remove a Remote PAC from configuration file * @param pac * @throws Exception */ public synchronized void removeRemotePAC(String loggedInUser, RemotePAC pac) throws Exception { User user = DefaultEpadProjectOperations.getInstance().getUser(loggedInUser); if (!user.isAdmin() && !user.hasPermission(User.CreatePACPermission)) throw new Exception("No permission to delete PAC configuration"); List<RemotePACQuery> queries = getRemotePACQueries(pac.pacID); if (queries.size() > 0) { throw new Exception( "Periodic queries have been configured for PAC:" + pac.pacID + ", it can not be deleted"); } //cavit if (pac.aeTitle.equalsIgnoreCase(EPADConfig.aeTitle)) { List<RemotePAC> pacs = getRemotePACs(); int count = 0; for (RemotePAC p : pacs) { //cavit if (p.aeTitle.equalsIgnoreCase(EPADConfig.aeTitle)) count++; } if (count >= 1) throw new Exception("Local PAC can not be deleted"); } removeRemotePAC(pac.pacID); Dcm4cheeServer instanceDcm4cheeServer = new Dcm4cheeServer(); instanceDcm4cheeServer.connect(); if (instanceDcm4cheeServer.deleteAetitle(pac.aeTitle).equals("null")) { log.info("Pacs Conection Deleted succesfully\n AEtitle :" + pac.aeTitle + "\n Host Name :" + pac.hostname + "\n Port no :" + Integer.toString(pac.port)); } else { throw new Exception("Unable to delete pacs connection : " + "\n AEtitle: " + pac.aeTitle + " Host Name: " + pac.hostname + "Port no:" + pac.port); } instanceDcm4cheeServer = null; this.storeProperties(pac.pacID + " deleted by EPAD " + new Date()); } /** * Get all Remote PAC automatic daily queries * @param pacID * @return * @throws Exception */ public List<RemotePACQuery> getRemotePACQueries(String pacID) throws Exception { List<RemotePACQuery> queries = new ArrayList<RemotePACQuery>(); List objects = new RemotePACQuery().getObjects("pacID = '" + pacID + "' order by pacid"); queries.addAll(objects); return queries; } public List<RemotePACQuery> getAllQueries() throws Exception { List<RemotePACQuery> queries = new ArrayList<RemotePACQuery>(); List objects = new RemotePACQuery().getObjects("1 = 1 order by pacid"); queries.addAll(objects); return queries; } /** * Get Remote PAC automatic daily query for pac and subject * @param pacID * @param subjectUID * @return * @throws Exception */ public RemotePACQuery getRemotePACQuery(String pacID, String subjectUID) throws Exception { Subject subject = DefaultEpadProjectOperations.getInstance().getSubject(subjectUID); if (subject == null) throw new Exception("Subject:" + subjectUID + " not found"); List objects = new RemotePACQuery() .getObjects("pacID = '" + pacID + "' and subject_id ='" + subject.getId() + "'"); if (objects.size() > 1) { log.warning("More than one query found for PacID:" + pacID + " and SubjectID:" + subjectUID); } else if (objects.size() == 0) { return null; } return (RemotePACQuery) objects.get(0); } /** * Create Remote PAC automatic daily query configuration in database * @param username * @param pacID * @param subjectUID * @param patientName * @param modality * @param studyDate * @param period * @param projectID * @return * @throws Exception */ public RemotePACQuery createRemotePACQuery(String username, String pacID, String subjectUID, String patientName, String modality, String studyDate, String period, String projectID) throws Exception { User user = DefaultEpadProjectOperations.getInstance().getUser(username); if (!user.isAdmin() && !user.hasPermission(User.CreateAutoPACQueryPermission)) throw new Exception("No permission to create PAC Patient Query configuration"); if (projectID.equals(EPADConfig.getParamValue("UnassignedProjectID", "nonassigned"))) throw new Exception("Query can not be added to project:" + projectID); RemotePACQuery query = null; try { query = getRemotePACQuery(pacID, subjectUID); if (query != null && !user.isAdmin() && !user.getUsername().equals(query.getRequestor())) ; throw new Exception("Remote PAC and Patient already configured for periodic query"); } catch (Exception x) { } ; Project project = DefaultEpadProjectOperations.getInstance().getProject(projectID); if (project == null) throw new Exception("Project " + projectID + " not found"); RemotePAC pac = this.getRemotePAC(pacID); if (pac == null && !pacID.startsWith(TCIAService.TCIA_PREFIX)) throw new Exception("Remote PAC " + pacID + " not found"); if (pac != null && pac.hostname.equalsIgnoreCase(EPADConfig.xnatServer) && pac.port == 11112) { throw new Exception("This is the local PAC, image data can not transferred from it"); } Subject subject = DefaultEpadProjectOperations.getInstance().getSubject(subjectUID); if (subject == null) { subject = DefaultEpadProjectOperations.getInstance().createSubject(username, subjectUID, patientName, null, null); } else if (studyDate == null || studyDate.trim().length() == 0) { try { List<Study> studies = DefaultEpadProjectOperations.getInstance() .getStudiesForSubject(subject.getSubjectUID()); Set<String> studyUIDs = new HashSet<String>(); for (Study study : studies) { studyUIDs.add(study.getStudyUID()); } DCM4CHEEStudyList dcm4CheeStudyList = Dcm4CheeQueries.getStudies(studyUIDs); Date date = null; for (DCM4CHEEStudy dcs : dcm4CheeStudyList.ResultSet.Result) { if (date == null || getDate(dcs.dateAcquired).after(date)) date = getDate(dcs.dateAcquired); } if (date != null) { Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.add(Calendar.DATE, 1); studyDate = dateformat.format(cal.getTime()); log.info("Subject:" + subject.getSubjectUID() + " Last Study Date from DCM4CHE:" + studyDate); } } catch (Exception x) { } ; } if (query == null) query = new RemotePACQuery(); query.setRequestor(username); query.setPacId(pacID); query.setSubjectId(subject.getId()); query.setProjectId(project.getId()); query.setEnabled(true); // TODO: Validate modality. How??? query.setModality(modality); if (getDate(studyDate) != null) { query.setLastStudyDate(studyDate); } if ("Weekly".equalsIgnoreCase(period)) query.setPeriod("Weekly"); else if ("Monthly".equalsIgnoreCase(period)) query.setPeriod("Monthly"); else query.setPeriod("Daily"); log.info("Saving pac query:" + pacID + " patient:" + subject.getSubjectUID() + " Modality:" + modality + " Period:" + query.getPeriod() + " Date:" + studyDate); query.save(); return query; } /** * Delete Remote PAC automatic daily query configuration from database * @param pacID * @param subjectUID * @throws Exception */ public void removeRemotePACQuery(String loggedInUser, String pacID, String subjectUID) throws Exception { User user = DefaultEpadProjectOperations.getInstance().getUser(loggedInUser); if (!user.isAdmin() && !user.hasPermission(User.CreateAutoPACQueryPermission)) throw new Exception("No permission to delete PAC Patient Query configuration"); Subject subject = DefaultEpadProjectOperations.getInstance().getSubject(subjectUID); if (subject == null) throw new Exception("Subject:" + subjectUID + " not found"); int rows = new RemotePACQuery() .deleteObjects("pacID = '" + pacID + "' and subject_id ='" + subject.getId() + "'"); if (rows > 0) log.info("Query for PacID:" + pacID + " and SubjectID:" + subjectUID + " was deleted"); } /** * Disable Remote PAC automatic daily query configuration from database * @param pacID * @param subjectID * @throws Exception */ public void disableRemotePACQuery(String loggedInUser, String pacID, String subjectID) throws Exception { Subject subject = DefaultEpadProjectOperations.getInstance().getSubject(subjectID); if (subject == null) throw new Exception("Subject not found, ID:" + subjectID); List objects = new RemotePACQuery() .getObjects("pacID = '" + pacID + "' and subject_id =" + subject.getId()); if (objects.size() > 1) { log.warning("More than one query found for PacID:" + pacID + " and SubjectID:" + subjectID); } for (Object object : objects) { RemotePACQuery query = (RemotePACQuery) object; query.setEnabled(false); query.save(); } if (objects.size() == 0) throw new Exception("Remote Query Configuration not found"); } /** * Enable Remote PAC automatic daily query configuration from database * @param pacID * @param subjectID * @throws Exception */ public void enableRemotePACQuery(String loggedInUser, String pacID, String subjectID) throws Exception { Subject subject = DefaultEpadProjectOperations.getInstance().getSubject(subjectID); if (subject == null) throw new Exception("Subject not found, ID:" + subjectID); List objects = new RemotePACQuery() .getObjects("pacID = '" + pacID + "' and subject_id =" + subject.getId()); if (objects.size() > 1) { log.warning("More than one query found for PacID:" + pacID + " and SubjectID:" + subjectID); } if (objects.size() > 0) { RemotePACQuery query = (RemotePACQuery) objects.get(0); query.setEnabled(true); query.save(); } else throw new Exception("Remote Query Configuration not found"); } /** * Convert Remote PAC automatic database configuration to dto * @param query * @return * @throws Exception */ public RemotePACQueryConfig getConfig(RemotePACQuery query) throws Exception { Subject subject = (Subject) new Subject(query.getSubjectId()).retrieve(); Project project = (Project) new Project(query.getProjectId()).retrieve(); RemotePAC pac = this.getRemotePAC(query.getPacId()); RemotePACQueryConfig rqc = new RemotePACQueryConfig(query.getPacId(), pac.aeTitle, query.getRequestor(), subject.getSubjectUID(), project.getProjectId(), query.getModality(), query.getPeriod(), query.isEnabled(), query.getLastStudyDate(), dateformat.format(query.getLastQueryTime()), query.getLastQueryStatus()); rqc.projectName = project.getName(); rqc.subjectName = subject.getName(); if (pac != null) rqc.hostname = pac.hostname; return rqc; } public static Map<String, AttributeList> currentPACQueries = new HashMap<String, AttributeList>(); /** * Query a Remote PAC given patient/studydate filters * @param pac * @param patientNameFilter * @param patientIDFilter * @param studyDateFilter * @return * @throws Exception */ public synchronized List<RemotePACEntity> queryRemoteData(RemotePAC pac, String patientNameFilter, String patientIDFilter, String studyIDFilter, String studyDateFilter, String modality, boolean patientsOnly, boolean studiesOnly) throws Exception { return queryRemoteData(pac, patientNameFilter, patientIDFilter, studyIDFilter, studyDateFilter, modality, null, null, null, null, patientsOnly, studiesOnly); } /** * Query a Remote PAC given patient/studydate filters of filter by DICOM TagGroup/Element/Value * @param pac * @param patientNameFilter * @param patientIDFilter * @param studyIDFilter * @param studyDateFilter * @param tagGroups, eg tagGroups = {"0x0008"}; tagElements={"0x0070"}; tagValues={"GE Medical Systems"}; * @param tagElements * @param tagValues * @param patientsOnly * @param studiesOnly * @return * @throws Exception */ public synchronized List<RemotePACEntity> queryRemoteData(RemotePAC pac, String patientNameFilter, String patientIDFilter, String studyIDFilter, String studyDateFilter, String modality, String[] tagGroups, String[] tagElements, String[] tagValues, String[] tagTypes, boolean patientsOnly, boolean studiesOnly) throws Exception { try { String qlevel = null; if (studiesOnly) qlevel = "STUDY"; if (patientsOnly) qlevel = "PATIENT"; log.info("Remote PAC Query, pacID:" + pac.pacID + " patientName:" + patientNameFilter + " patientID:" + patientIDFilter + " studyDate:" + studyDateFilter + " studyIDFilter:" + studyIDFilter + " patientsOnly:" + patientsOnly + " studiesOnly:" + studiesOnly + " tagValues:" + tagValues); if ((patientNameFilter == null || patientNameFilter.length() == 0) && (patientIDFilter == null || patientIDFilter.length() == 0 || patientIDFilter.equals("1*")) && (tagGroups == null || tagGroups.length == 0) && patientsOnly) { if (patientCache.containsKey(pac.pacID)) return patientCache.get(pac.pacID); } if (currentPACQueries.containsKey(pac.pacID)) throw new Exception("Last query to this PAC still in progress"); if (patientNameFilter != null && patientNameFilter.equals("*")) patientNameFilter = ""; if (patientIDFilter != null && patientIDFilter.equals("*")) patientIDFilter = ""; this.setCurrentRemoteQueryInformationModel(pac.pacID); SpecificCharacterSet specificCharacterSet = new SpecificCharacterSet((String[]) null); AttributeList filter = new AttributeList(); currentPACQueries.put(pac.pacID, filter); { AttributeTag t = TagFromName.PatientName; Attribute a = new PersonNameAttribute(t, specificCharacterSet); if (patientNameFilter != null && patientNameFilter.length() > 0) { a.addValue(patientNameFilter.toUpperCase()); } filter.put(t, a); qlevel = "PATIENT"; } { AttributeTag t = TagFromName.PatientID; Attribute a = new ShortStringAttribute(t, specificCharacterSet); if (patientIDFilter != null && patientIDFilter.length() > 0) { a.addValue(patientIDFilter); } filter.put(t, a); qlevel = "PATIENT"; } // StudyDate formats: // from/to: 20071001-20080220 // before: -20080220 // after: 20071001- { AttributeTag t = TagFromName.StudyDate; Attribute a = new DateAttribute(t); if (studyDateFilter != null && studyDateFilter.length() > 0) { a.addValue(studyDateFilter); } filter.put(t, a); } { AttributeTag t = TagFromName.StudyInstanceUID; Attribute a = new UniqueIdentifierAttribute(t); if (studyIDFilter != null && studyIDFilter.length() > 0) { if (studyIDFilter.startsWith(pac.pacID + ":")) studyIDFilter = studyIDFilter.substring(studyIDFilter.indexOf(":") + 1); a.addValue(studyIDFilter); } filter.put(t, a); qlevel = "STUDY"; } { AttributeTag t = TagFromName.ModalitiesInStudy; Attribute a = new CodeStringAttribute(t); if (modality != null && modality.length() > 0) { a.addValue(modality.toUpperCase()); } filter.put(t, a); } if (tagGroups != null && tagElements != null && tagValues != null) { for (int i = 0; i < tagGroups.length && i < tagElements.length && i < tagValues.length; i++) { try { AttributeTag t = new AttributeTag(Integer.decode(tagGroups[i]), Integer.decode(tagElements[i])); Attribute a = null; if (tagTypes != null && tagTypes.length > i) { log.info("Attribute:" + t.toString() + " type:" + tagTypes[i] + " value:" + tagValues[i]); if (tagTypes[i].equalsIgnoreCase("LongString")) a = new LongStringAttribute(t, specificCharacterSet); else if (tagTypes[i].equalsIgnoreCase("ShortString")) a = new ShortStringAttribute(t, specificCharacterSet); else if (tagTypes[i].equalsIgnoreCase("Date")) a = new DateAttribute(t); else if (tagTypes[i].equalsIgnoreCase("Time")) a = new TimeAttribute(t); else if (tagTypes[i].equalsIgnoreCase("Integer")) a = new IntegerStringAttribute(t); else if (tagTypes[i].equalsIgnoreCase("Decimal")) a = new DecimalStringAttribute(t); else if (tagTypes[i].equalsIgnoreCase("Code")) a = new CodeStringAttribute(t); } else log.info("Attribute:" + t.toString() + " type:" + tagTypes + " value:" + tagValues[i]); if (a == null) a = new LongStringAttribute(t, specificCharacterSet); a.addValue(tagValues[i].toUpperCase()); filter.put(t, a); qlevel = "SERIES"; } catch (Exception x) { log.warning("Error decoding entered tag id" + tagGroups[i] + "," + tagElements[i], x); } } } if (qlevel != null) { AttributeTag t = TagFromName.QueryRetrieveLevel; Attribute a = new CodeStringAttribute(t); a.addValue(qlevel); if (!filter.containsKey(t)) { filter.put(t, a); } } { AttributeTag t = TagFromName.PatientBirthDate; Attribute a = new DateAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.PatientSex; Attribute a = new CodeStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.StudyID; Attribute a = new ShortStringAttribute(t, specificCharacterSet); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.StudyDescription; Attribute a = new LongStringAttribute(t, specificCharacterSet); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.StudyTime; Attribute a = new TimeAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } //{ AttributeTag t = TagFromName.PatientAge; Attribute a = new AgeStringAttribute(t); if (!filter.containsKey(t)) filter.put(t,a); } { AttributeTag t = TagFromName.SeriesDescription; Attribute a = new LongStringAttribute(t, specificCharacterSet); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.SeriesNumber; Attribute a = new IntegerStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.Manufacturer; Attribute a = new LongStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.Modality; Attribute a = new CodeStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.SeriesDate; Attribute a = new DateAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.SeriesTime; Attribute a = new TimeAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.InstanceNumber; Attribute a = new IntegerStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.ContentDate; Attribute a = new DateAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.ContentTime; Attribute a = new TimeAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.ImageType; Attribute a = new CodeStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.NumberOfFrames; Attribute a = new IntegerStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.WindowCenter; Attribute a = new DecimalStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.WindowWidth; Attribute a = new DecimalStringAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.SeriesInstanceUID; Attribute a = new UniqueIdentifierAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.SOPInstanceUID; Attribute a = new UniqueIdentifierAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.SOPClassUID; Attribute a = new UniqueIdentifierAttribute(t); if (!filter.containsKey(t)) filter.put(t, a); } { AttributeTag t = TagFromName.SpecificCharacterSet; Attribute a = new CodeStringAttribute(t); filter.put(t, a); a.addValue("ISO_IR 100"); } if (remoteQueryCache.keySet().size() > MAX_CACHE_ENTRIES) clearQueryCache(); List<RemotePACEntity> remoteEntities = new ArrayList<RemotePACEntity>(); String key = pac.pacID; long startTime = System.currentTimeMillis(); patientIds = new HashSet<String>(); QueryTreeModel treeModel = currentRemoteQueryInformationModel.performHierarchicalQuery(filter); long endTime = System.currentTimeMillis(); //log.info("Remote PAC Query took " + (endTime-startTime) + " msecs"); QueryTreeRecord root = (QueryTreeRecord) treeModel.getRoot(); remoteEntities = traverseTree(root, 0, remoteEntities, key, patientsOnly, studiesOnly); long traverseTime = System.currentTimeMillis(); log.info("Remote PAC tree records took " + (traverseTime - startTime) + " msecs. Number of entities returned:" + remoteEntities.size()); if (patientsOnly && remoteEntities.size() > 0) remoteEntities.remove(0); // Remove AE record else if (studiesOnly && remoteEntities.size() > 0) remoteEntities.remove(0); // Remove AE record if (studyIDFilter != null && studyIDFilter.length() > 0 && !studiesOnly && remoteEntities.size() > 1) { remoteEntities.remove(0); // Remove AE record remoteEntities.remove(0); // Remove Study Record } if (patientIDFilter != null && patientIDFilter.trim().length() > 0) { EpadProjectOperations projectOperations = DefaultEpadProjectOperations.getInstance(); EpadDatabaseOperations databaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); for (RemotePACEntity rpe : remoteEntities) { if (rpe.entityType.equalsIgnoreCase("Study")) { if (databaseOperations .hasStudyInDCM4CHE(rpe.entityID.substring(rpe.entityID.indexOf(":") + 1))) rpe.inEpad = true; } else if (rpe.entityType.equalsIgnoreCase("Series")) { if (databaseOperations .hasSeriesInEPadDatabase(rpe.entityID.substring(rpe.entityID.indexOf(":") + 1))) rpe.inEpad = true; } } } if ((patientNameFilter == null || patientNameFilter.length() == 0) && (patientIDFilter == null || patientIDFilter.length() == 0 || patientIDFilter.equals("1*")) && patientsOnly) { patientCache.put(pac.pacID, remoteEntities); } log.info("Returning " + remoteEntities.size() + " records"); return remoteEntities; } catch (Exception e) { e.printStackTrace(); throw e; } finally { currentPACQueries.remove(pac.pacID); } } /** * */ public void clearQueryCache() { remoteQueryCache = new HashMap<String, QueryTreeRecord>(); dicomTags = null; } DecimalFormat decformat = new DecimalFormat("00000"); Set<String> patientIds = new HashSet<String>(); private List<RemotePACEntity> traverseTree(QueryTreeRecord node, int level, List<RemotePACEntity> entities, String key, boolean patientsOnly, boolean studiesOnly) { AttributeList al = node.getAllAttributesReturnedInIdentifier(); String type = ""; if (node.getInformationEntity() != null) { type = node.getInformationEntity().toString(); } else if (entities.size() == 0) { type = "AE"; } String ukey = key; if (entities.size() > 0) { ukey = entities.get(0).entityID + ":" + node.getUniqueKey().getDelimitedStringValuesOrEmptyString(); // Is this key better??? if (patientsOnly) ukey = entities.get(0).entityID + ":" + "SUBJECT" + ":" + node.getUniqueKey().getDelimitedStringValuesOrEmptyString(); // Is this key better??? } RemotePACEntity entity = new RemotePACEntity(type, node.getValue(), level, ukey); entity.subjectID = Attribute.getSingleStringValueOrNull(al, TagFromName.PatientID); entity.subjectName = Attribute.getSingleStringValueOrNull(al, TagFromName.PatientName); if (entity.subjectName == null || entity.subjectName.length() == 0) entity.subjectName = entity.subjectID; entity.studyDate = Attribute.getSingleStringValueOrNull(al, TagFromName.StudyDate); entity.studyDescription = Attribute.getSingleStringValueOrNull(al, TagFromName.StudyDescription); if (patientsOnly && type.equals("Study") && patientIds.contains(entity.subjectID)) { //log.info("Duplicate subject:" + entity.subjectID); return entities; } patientIds.add(entity.subjectID); remoteQueryCache.put(ukey, node); if (!studiesOnly || !type.equals("Series")) entities.add(entity); int num = entities.size(); if (num % 100 == 0) log.info("Remote Query, number of records, received:" + num); if (studiesOnly && entities.size() >= MAX_SERIES_QUERY) return entities; if (!studiesOnly && entities.size() >= MAX_INSTANCE_QUERY) return entities; int n = ((QueryTreeRecord) node).getChildCount(); for (int i = 0; i < n; i++) { if ((!studiesOnly || !type.equals("Study")) && !type.equals("Series")) { //log.info("Remote Query, getting children:" + type); traverseTree((QueryTreeRecord) ((QueryTreeRecord) node).getChildAt(i), level + 1, entities, key + ":" + decformat.format(i), patientsOnly, studiesOnly); } } return entities; } /** * Initiate transfer of a Remote PAC images to local PAC (patient/study id is found, it is added to project) * @param pac * @param entityID - This ID is contained in the RemotePACEntity query result consists of pacid and series uid or instance uid * @param projectID * @param userName * @param sessionID * @return * @throws Exception */ public synchronized String retrieveRemoteData(RemotePAC pac, String entityID, String projectID, String userName, String sessionID) throws Exception { if (pac.hostname.equalsIgnoreCase(EPADConfig.xnatServer) && pac.port == 11112) { throw new Exception("This is the local PAC, image data can not transferred from it"); } if (entityID.contains("SUBJECT:")) { throw new Exception("Patients can not be transferred. Please select a Study or Series"); } String uniqueKey = entityID; String root = uniqueKey; if (root.indexOf(":") != -1) root = root.substring(0, root.lastIndexOf(":")); if (!uniqueKey.startsWith(pac.pacID)) uniqueKey = pac.pacID + ":" + uniqueKey; QueryTreeRecord node = remoteQueryCache.get(uniqueKey); // If no cached pointers, query entire PAC again (or should we give an error???) if (node == null) { queryRemoteData(pac, "", "", "", "", "", false, false); node = remoteQueryCache.get(uniqueKey); if (node == null) throw new Exception("Remote data not found:" + uniqueKey); } String type = node.getInformationEntity().toString(); String studyUID = null; String studyDate = null; String seriesUID = null; String patientID = null; String patientName = ""; if (!type.equalsIgnoreCase("Study")) { if (type.equalsIgnoreCase("Series")) seriesUID = node.getUniqueKey().getSingleStringValueOrNull(); QueryTreeRecord parent = (QueryTreeRecord) node.getParent(); if (parent != null) { type = parent.getInformationEntity().toString(); if (!type.equalsIgnoreCase("Study")) { if (type.equalsIgnoreCase("Series")) seriesUID = parent.getUniqueKey().getSingleStringValueOrNull(); parent = (QueryTreeRecord) parent.getParent(); type = parent.getInformationEntity().toString(); if (type.equalsIgnoreCase("Study")) { studyUID = parent.getUniqueKey().getSingleStringValueOrNull(); studyDate = Attribute.getSingleStringValueOrNull( parent.getAllAttributesReturnedInIdentifier(), TagFromName.StudyDate); patientID = Attribute.getSingleStringValueOrNull( parent.getAllAttributesReturnedInIdentifier(), TagFromName.PatientID); patientName = Attribute.getSingleStringValueOrEmptyString( parent.getAllAttributesReturnedInIdentifier(), TagFromName.PatientName); } } else { studyUID = parent.getUniqueKey().getSingleStringValueOrNull(); studyDate = Attribute.getSingleStringValueOrNull(parent.getAllAttributesReturnedInIdentifier(), TagFromName.StudyDate); patientID = Attribute.getSingleStringValueOrNull(parent.getAllAttributesReturnedInIdentifier(), TagFromName.PatientID); patientName = Attribute.getSingleStringValueOrEmptyString( parent.getAllAttributesReturnedInIdentifier(), TagFromName.PatientName); } } } else { studyUID = uniqueKey; if (studyUID.indexOf(":") != -1) studyUID = studyUID.substring(studyUID.indexOf(":") + 1); studyDate = Attribute.getSingleStringValueOrNull(node.getAllAttributesReturnedInIdentifier(), TagFromName.StudyDate); patientID = Attribute.getSingleStringValueOrNull(node.getAllAttributesReturnedInIdentifier(), TagFromName.PatientID); patientName = Attribute.getSingleStringValueOrEmptyString(node.getAllAttributesReturnedInIdentifier(), TagFromName.PatientName); } if (studyUID != null && patientID != null && projectID != null && projectID.trim().length() > 0) { UserProjectService.addSubjectAndStudyToProject(patientID, patientName, studyUID, studyDate, projectID, sessionID, userName); } if (seriesUID != null) pendingTransfers.put(seriesUID, userName + ":" + projectID); this.setCurrentRemoteQueryInformationModel(pac.pacID); if (node != null) { setCurrentRemoteQuerySelection(node.getUniqueKeys(), node.getUniqueKey(), node.getAllAttributesReturnedInIdentifier()); log.info("Request retrieval of " + currentRemoteQuerySelectionLevel + " " + currentRemoteQuerySelectionUniqueKey.getSingleStringValueOrEmptyString() + " from " + pac.pacID + " (" + currentRemoteQuerySelectionRetrieveAE + ")"); File xfrstart = new File(EPADConfig.dcm4cheeHome + "/" + pac.aeTitle + "_XfrStarted.log"); File xfrend = new File(EPADConfig.dcm4cheeHome + "/" + pac.aeTitle + "_XfrEnded.log"); try { if (xfrstart.exists()) xfrstart.delete(); if (xfrend.exists()) xfrend.delete(); } catch (Exception x) { } performRetrieve(currentRemoteQuerySelectionUniqueKeys, currentRemoteQuerySelectionLevel, currentRemoteQuerySelectionRetrieveAE); } monitorTransfers.put(pac.aeTitle, userName + ":" + pac.pacID); monitorStart.put(pac.aeTitle, System.currentTimeMillis()); if (studyUID != null) return studyUID + ":" + studyDate; else return seriesUID; } /** * @return */ public List<String> getPendingTransfers() { List<String> transfers = new ArrayList<String>(); for (String id : pendingTransfers.keySet()) { String transfer = id + ":" + pendingTransfers.get(id); transfers.add(transfer); } return transfers; } public static void checkTransfers() { if (monitorTransfers.isEmpty()) return; EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); Set<String> removeAet = new HashSet<String>(); for (String aet : monitorTransfers.keySet()) { //log.info("Checking data transfer from " + aet); File xfrstart = new File(EPADConfig.dcm4cheeHome + "/" + aet + "_XfrStarted.log"); File xfrend = new File(EPADConfig.dcm4cheeHome + "/" + aet + "_XfrEnded.log"); try { if (xfrstart.exists()) { String logStart = EPADFileUtils.readFileAsString(xfrstart); epadDatabaseOperations.insertEpadEvent( monitorTransfers.get(aet).substring(0, monitorTransfers.get(aet).indexOf(":")), logStart.replace('\n', ' '), aet, aet, aet, aet, "", "", "Remote PAC Transfer"); log.info("Added PAC Transfer Started Event for " + monitorTransfers.get(aet)); xfrstart.delete(); } if (xfrend.exists()) { monitorStart.put(aet, 0L); String logEnd = EPADFileUtils.readFileAsString(xfrend); epadDatabaseOperations.insertEpadEvent( monitorTransfers.get(aet).substring(0, monitorTransfers.get(aet).indexOf(":")), logEnd.replace('\n', ' '), aet, aet, aet, aet, "", "", "Remote PAC Transfer"); log.info("Added PAC Transfer Ended Event for " + monitorTransfers.get(aet)); xfrend.delete(); } } catch (Exception x) { removeAet.add(aet); log.warning("Error in checking", x); } } for (String aet : monitorStart.keySet()) { if ((System.currentTimeMillis() - monitorStart.get(aet)) > 3600000) { removeAet.add(aet); } } for (String aet : removeAet) { monitorTransfers.remove(aet); monitorStart.remove(aet); } } SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMdd"); private Date getDate(String dateStr) { try { return dateformat.parse(dateStr); } catch (Exception x) { return null; } } }