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.aim; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.IOUtils; import org.json.JSONArray; import org.json.JSONObject; import org.json.XML; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.pixelmed.dicom.Attribute; import com.pixelmed.dicom.AttributeList; import com.pixelmed.dicom.SOPClass; import com.pixelmed.dicom.SequenceAttribute; import com.pixelmed.dicom.SequenceItem; import com.pixelmed.dicom.TagFromName; import edu.stanford.epad.common.dicom.DCM4CHEEImageDescription; import edu.stanford.epad.common.pixelmed.PixelMedUtils; import edu.stanford.epad.common.plugins.PluginAIMUtil; import edu.stanford.epad.common.util.EPADConfig; import edu.stanford.epad.common.util.EPADFileUtils; import edu.stanford.epad.common.util.EPADLogger; import edu.stanford.epad.common.util.MongoDBOperations; import edu.stanford.epad.common.util.XmlNamespaceTranslator; import edu.stanford.epad.dtos.EPADAIM; import edu.stanford.epad.dtos.EPADAIMList; import edu.stanford.epad.dtos.EPADImageList; import edu.stanford.epad.dtos.EPADAIMList.EPADAIMResultSet; import edu.stanford.epad.dtos.internal.DCM4CHEESeries; import edu.stanford.epad.dtos.internal.DICOMElement; import edu.stanford.epad.dtos.internal.DICOMElementList; import edu.stanford.epad.epadws.aim.aimapi.Aim; import edu.stanford.epad.epadws.aim.aimapi.Aim4; import edu.stanford.epad.epadws.dcm4chee.Dcm4CheeDatabase; import edu.stanford.epad.epadws.dcm4chee.Dcm4CheeDatabaseOperations; import edu.stanford.epad.epadws.epaddb.EpadDatabase; import edu.stanford.epad.epadws.epaddb.EpadDatabaseOperations; import edu.stanford.epad.epadws.handlers.HandlerUtil; import edu.stanford.epad.epadws.handlers.core.FrameReference; import edu.stanford.epad.epadws.handlers.core.ImageReference; import edu.stanford.epad.epadws.handlers.core.SeriesReference; import edu.stanford.epad.epadws.handlers.event.EventHandler; import edu.stanford.epad.epadws.models.NonDicomSeries; import edu.stanford.epad.epadws.models.Project; import edu.stanford.epad.epadws.models.Subject; import edu.stanford.epad.epadws.models.Template; import edu.stanford.epad.epadws.plugins.PluginConfig; import edu.stanford.epad.epadws.processing.pipeline.task.PluginStartTask; import edu.stanford.epad.epadws.queries.Dcm4CheeQueries; import edu.stanford.epad.epadws.queries.DefaultEpadOperations; import edu.stanford.epad.epadws.queries.EpadOperations; import edu.stanford.epad.epadws.service.DefaultEpadProjectOperations; import edu.stanford.epad.epadws.service.EpadProjectOperations; import edu.stanford.epad.epadws.service.SessionService; import edu.stanford.epad.epadws.service.UserProjectService; import edu.stanford.hakan.aim4api.base.ImagingObservationCharacteristic; import edu.stanford.hakan.aim4api.base.AimException; import edu.stanford.hakan.aim4api.base.Algorithm; import edu.stanford.hakan.aim4api.base.CD; import edu.stanford.hakan.aim4api.base.CalculationEntity; import edu.stanford.hakan.aim4api.base.DicomImageReferenceEntity; import edu.stanford.hakan.aim4api.base.DicomSegmentationEntity; import edu.stanford.hakan.aim4api.base.Enumerations; import edu.stanford.hakan.aim4api.base.ExtendedCalculationResult; import edu.stanford.hakan.aim4api.base.II; import edu.stanford.hakan.aim4api.base.Image; import edu.stanford.hakan.aim4api.base.ImageAnnotationCollection; import edu.stanford.hakan.aim4api.base.ImageCollection; import edu.stanford.hakan.aim4api.base.ImageSeries; import edu.stanford.hakan.aim4api.base.ImageStudy; import edu.stanford.hakan.aim4api.base.ImagingObservationEntity; import edu.stanford.hakan.aim4api.base.ImagingPhysicalEntity; import edu.stanford.hakan.aim4api.base.ST; import edu.stanford.hakan.aim4api.base.SegmentationEntityCollection; import edu.stanford.hakan.aim4api.base.TwoDimensionSpatialCoordinate; import edu.stanford.hakan.aim4api.base.TwoDimensionSpatialCoordinateCollection; import edu.stanford.hakan.aim4api.compability.aimv3.DICOMImageReference; import edu.stanford.hakan.aim4api.compability.aimv3.ImageAnnotation; import edu.stanford.hakan.aim4api.compability.aimv3.Lexicon; import edu.stanford.hakan.aim4api.compability.aimv3.Modality; import edu.stanford.hakan.aim4api.compability.aimv3.Person; import edu.stanford.hakan.aim4api.compability.aimv3.Segmentation; import edu.stanford.hakan.aim4api.compability.aimv3.SegmentationCollection; import edu.stanford.hakan.aim4api.compability.aimv3.User; import edu.stanford.hakan.aim4api.project.epad.Enumerations.ShapeType; import edu.stanford.hakan.aim4api.usage.AnnotationBuilder; import edu.stanford.hakan.aim4api.usage.AnnotationGetter; import edu.stanford.hakan.aim4api.usage.AnnotationValidator; /** * * * * @author martin */ public class AIMUtil { private static final EPADLogger log = EPADLogger.getInstance(); private static final String aim3Namespace = EPADConfig.aim3Namespace; private static final String eXistUsername = EPADConfig.eXistUsername; private static final String eXistPassword = EPADConfig.eXistPassword; private static final String eXistServerUrl = EPADConfig.eXistServerUrl; private static final String eXistCollection = EPADConfig.eXistCollection; private static final String baseAnnotationDir = EPADConfig.baseAnnotationDir; private static final String xsdFilePath = EPADConfig.xsdFilePath; private static final String useV4 = EPADConfig.useV4; private static final String aim4Namespace = EPADConfig.aim4Namespace; private static final String eXistCollectionV4 = EPADConfig.eXistCollectionV4; private static final String xsdFileV4 = EPADConfig.xsdFileV4; private static final String xsdFilePathV4 = EPADConfig.xsdFilePathV4; //a list of strings, holds information about the uploaded dso, to be used during DSOMaskPNGGeneration to update the aim enity in db //holds seriesID,dsoInstanceUid,aimID,projectID in this order public static List<String[]> dsoAims = new ArrayList<>(); public static void updateDSOStartIndex(EPADAIM aim, int dsoStartIndex) { ImageAnnotationCollection iac = null; EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); try { iac = AnnotationGetter.getImageAnnotationCollectionFromString(aim.xml, xsdFilePathV4); iac.getImageAnnotation().setDsoStartIndex(dsoStartIndex); //update the one in db epadDatabaseOperations.updateAIMXml(aim.aimID, iac.getXMLString()); //update the one in exist saveImageAnnotationToServer(iac, aim.projectID, dsoStartIndex, null, false); } catch (AimException e) { log.info("Aim exception getting the aim from string " + e.getMessage()); } } private static long getTime(String timestamp) { try { Date date = new SimpleDateFormat("yyyy-dd-MM HH:mm:ss").parse(timestamp); return date.getTime(); } catch (Exception x) { return 0; } } /** * @param ImageAnnotationCollection aim - AIM 4 implementation * @param frameNumber * @param jsessionID * @return * @throws AimException * @throws edu.stanford.hakan.aim4api.base.AimException */ public static ImageAnnotationCollection saveImageAnnotationToServer(ImageAnnotationCollection aim, String projectID, int frameNumber, String jsessionID) throws AimException, edu.stanford.hakan.aim4api.base.AimException { return saveImageAnnotationToServer(aim, projectID, frameNumber, jsessionID, true); } public static ImageAnnotationCollection saveImageAnnotationToServer(ImageAnnotationCollection aim, String projectID, int frameNumber, String jsessionID, boolean invokePlugin) throws AimException, edu.stanford.hakan.aim4api.base.AimException { //String result = ""; if (aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode() != null) { if (isPluginStillRunning(aim.getUniqueIdentifier().getRoot())) throw new edu.stanford.hakan.aim4api.base.AimException("Previous version of this AIM " + aim.getUniqueIdentifier().getRoot() + " is still being processed by the plugin"); // For safety, write a backup file - what is this strange safety feature?? String tempXmlPath = baseAnnotationDir + "temp-" + aim.getUniqueIdentifier().getRoot() + ".xml"; String storeXmlPath = baseAnnotationDir + aim.getUniqueIdentifier().getRoot() + ".xml"; File tempFile = new File(tempXmlPath); File storeFile = new File(storeXmlPath); String xml = edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(aim); log.info("Saving AIM xml=" + xml); log.info("Saving AIM file with ID " + aim.getUniqueIdentifier() + " to temp folder " + tempXmlPath); edu.stanford.hakan.aim4api.usage.AnnotationBuilder.saveToFile(aim, tempXmlPath, xsdFilePathV4); log.info(AnnotationBuilder.getAimXMLsaveResult()); if (storeFile.exists()) { storeFile.delete(); } tempFile.renameTo(storeFile); String collectionName = eXistCollectionV4; if (projectID != null && projectID.length() > 0) collectionName = collectionName + "/" + projectID; aim = edu.stanford.hakan.aim4api.usage.AnnotationBuilder.saveToServer(aim, eXistServerUrl, aim4Namespace, collectionName, xsdFilePathV4, eXistUsername, eXistPassword); log.info(edu.stanford.hakan.aim4api.usage.AnnotationBuilder.getAimXMLsaveResult()); try { if (projectID != null && projectID.length() > 0) saveAimToMongo(aim, projectID); } catch (Exception e) { log.warning("Error saving aim to mongodb", e); } if (aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName() != null && aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName() .equals("epad-plugin")) { // Which template has been used to fill the AIM file String templateName = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); // ex: jjv-5 log.info("Found an AIM plugin template with name " + templateName + " and AIM ID " + aim.getUniqueIdentifier()); boolean templateHasBeenFound = false; String handlerName = null; String pluginName = null; List<String> list = PluginConfig.getInstance().getPluginTemplateList(); for (int i = 0; i < list.size(); i++) { String templateNameFounded = list.get(i); if (templateNameFounded.equals(templateName)) { handlerName = PluginConfig.getInstance().getPluginHandlerList().get(i); pluginName = PluginConfig.getInstance().getPluginNameList().get(i); templateHasBeenFound = true; } } if (templateHasBeenFound && jsessionID != null && invokePlugin) { // Start plugin task log.info("Starting Plugin task for:" + pluginName); (new Thread(new PluginStartTask(jsessionID, pluginName, aim.getUniqueIdentifier().getRoot(), frameNumber, projectID))).start(); } } } return aim; } public static boolean deleteAIM(String aimID, String projectID) { try { String collectionName = eXistCollectionV4; if (projectID != null && projectID.length() > 0) collectionName = collectionName + "/" + projectID; List<ImageAnnotationCollection> aims = AIMQueries.getAIMImageAnnotationsV4(projectID, AIMSearchType.ANNOTATION_UID, aimID, "admin"); log.info("Number of aims found in exist with aimID = " + aimID + " : " + aims.size()); edu.stanford.hakan.aim4api.database.exist.ExistManager.removeImageAnnotationCollectionFromServer( eXistServerUrl, aim4Namespace, collectionName, eXistUsername, eXistPassword, aimID); MongoDBOperations.deleteAnotationInMongo(aimID, projectID); return true; } catch (Exception ex) { log.warning("Error deleting AIM annotation " + aimID, ex); return false; } } public static boolean isPluginStillRunning(String aimID) { try { EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); List<Map<String, String>> eventMaps = epadDatabaseOperations.getEpadEventsForAimID(aimID); if (eventMaps.size() == 0) { eventMaps = new ArrayList<Map<String, String>>(); Map<String, String> eventMap = EventHandler.deletedEvents.get(aimID); if (eventMap != null) eventMaps.add(eventMap); } if (eventMaps.size() > 0) { log.info("last event:" + eventMaps.get(0)); if ("Started".equals(eventMaps.get(0).get("event_status")) && getTime(eventMaps.get(0) .get("created_time")) > (System.currentTimeMillis() - 10 * 60 * 60 * 1000)) { return true; } } } catch (Exception x) { } return false; } /** * Generate an AIM file for a new DICOM Segmentation Object (DSO). This generation process is used when a new DSO is * detected in dcm4chee. For the moment, we set the owner of the AIM annotation to admin. * <p> * This AIM file actually annotates the original image, NOT the DSO. The Referenced SOP Instance UID field in the * DICOM DSO tag file identifies the image from which the segmentation object is derived from. It contains the imageID * of the original image but does not contain the study or series identifiers for that image - so we need to discover * them by querying ePAD. */ /** * {@link PluginAIMUtil#generateAIMFileForDSO} is very similar. * */ public static ImageAnnotation generateAIMFileForDSO(File dsoFile) throws Exception { return generateAIMFileForDSO(dsoFile, "shared", null); } public static ImageAnnotation generateAIMFileForDSO(File dsoFile, String username, String projectID) throws Exception { return generateAIMFileForDSO(dsoFile, username, projectID, null); } public static ImageAnnotation generateAIMFileForDSO(File dsoFile, String username, String projectID, String aimName) throws Exception { log.info("Creating DSO AIM for user " + username + " in project " + projectID + " file:" + dsoFile.getAbsolutePath()); AttributeList dsoDICOMAttributes = PixelMedUtils.readDICOMAttributeList(dsoFile); String patientID = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.PatientID); String patientName = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.PatientName); String patientBirthDay = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.PatientBirthDate); if (patientBirthDay.trim().length() != 8) patientBirthDay = "19650212"; String patientSex = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.PatientSex); if (patientSex.trim().length() != 1) patientSex = "F"; String dsoDate = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.SeriesDate); if (dsoDate.trim().length() != 8) dsoDate = "20001017"; String sopClassUID = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.SOPClassUID); String studyUID = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.StudyInstanceUID); log.info("DSO:" + dsoFile.getAbsolutePath() + " PatientID:" + patientID + " studyUID:" + studyUID + " projectID:" + projectID); String seriesUID = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.SeriesInstanceUID); String imageUID = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.SOPInstanceUID); String description = Attribute.getSingleStringValueOrEmptyString(dsoDICOMAttributes, TagFromName.SeriesDescription); // TODO: This call to get Referenced Image does not work ??? String[] referencedImageUID = Attribute.getStringValues(dsoDICOMAttributes, TagFromName.ReferencedSOPInstanceUID); String[] segNums = SequenceAttribute .getArrayOfSingleStringValueOrEmptyStringOfNamedAttributeWithinSequenceItems(dsoDICOMAttributes, TagFromName.SegmentSequence, TagFromName.SegmentNumber); if (segNums == null) segNums = new String[1]; Dcm4CheeDatabaseOperations dcm4CheeDatabaseOperations = Dcm4CheeDatabase.getInstance() .getDcm4CheeDatabaseOperations(); SequenceAttribute referencedSeriesSequence = (SequenceAttribute) dsoDICOMAttributes .get(TagFromName.ReferencedSeriesSequence); String referencedSeriesUID = ""; if (referencedSeriesSequence != null) { Iterator sitems = referencedSeriesSequence.iterator(); if (sitems.hasNext()) { SequenceItem sitem = (SequenceItem) sitems.next(); if (sitem != null) { AttributeList list = sitem.getAttributeList(); SequenceAttribute referencedInstanceSeq = (SequenceAttribute) list .get(TagFromName.ReferencedInstanceSequence); Iterator sitems2 = referencedInstanceSeq.iterator(); while (sitems2.hasNext()) { sitem = (SequenceItem) sitems2.next(); list = sitem.getAttributeList(); if (list.get(TagFromName.ReferencedSOPInstanceUID) != null) { referencedImageUID = new String[1]; referencedImageUID[0] = list.get(TagFromName.ReferencedSOPInstanceUID) .getSingleStringValueOrEmptyString(); referencedSeriesUID = dcm4CheeDatabaseOperations .getSeriesUIDForImage(referencedImageUID[0]); if (referencedSeriesUID != null && referencedSeriesUID.length() > 0) { log.info("ReferencedSOPInstanceUID:" + referencedImageUID[0]); break; } else log.info("DSO Referenced Image not found:" + referencedImageUID[0]); } } } } } if (referencedSeriesUID != null && referencedSeriesUID.length() != 0) { // Found corresponding series in dcm4chee String referencedStudyUID = studyUID; // Will be same study as DSO patientName = trimTrailing(patientName); log.info("Generating AIM file for DSO series " + seriesUID + " for patient " + patientName); log.info("SOP Class UID=" + sopClassUID); log.info("DSO Study UID=" + studyUID); log.info("DSO Series UID=" + seriesUID); log.info("DSO Image UID=" + imageUID); log.info("Referenced SOP Instance UID=" + referencedImageUID[0]); log.info("Referenced Series Instance UID=" + referencedSeriesUID); DCM4CHEEImageDescription id = dcm4CheeDatabaseOperations.getImageDescription(referencedStudyUID, referencedSeriesUID, referencedImageUID[0]); log.info("class uid from image description" + id.classUID); String name = aimName; if (name == null || name.trim().length() == 0) name = description; if (name == null || name.trim().length() == 0) name = "segmentation"; ImageAnnotation imageAnnotation = new ImageAnnotation(0, "", dsoDate.substring(0, 4) + "-" + dsoDate.substring(4, 6) + "-" + dsoDate.substring(6, 8) + "T00:00:00", name, "SEG", "SEG Only", "", "", ""); SegmentationCollection sc = new SegmentationCollection(); sc.AddSegmentation(new Segmentation(0, imageUID, sopClassUID, referencedImageUID[0], 1)); imageAnnotation.setSegmentationCollection(sc); //ml adding sop class to createdicomimage references below DICOMImageReference originalDICOMImageReference = PluginAIMUtil.createDICOMImageReferenceV3Compability( referencedStudyUID, referencedSeriesUID, referencedImageUID[0], id.classUID); imageAnnotation.addImageReference(originalDICOMImageReference); //ml 2. image reference removed // DICOMImageReference dsoDICOMImageReference = PluginAIMUtil.createDICOMImageReferenceV3Compability(studyUID, seriesUID, // imageUID, sopClassUID); // imageAnnotation.addImageReference(dsoDICOMImageReference); Person person = new Person(); person.setSex(patientSex.trim()); if (patientBirthDay.trim().length() == 8) person.setBirthDate(patientBirthDay.substring(0, 4) + "-" + patientBirthDay.substring(4, 6) + "-" + patientBirthDay.substring(6, 8) + "T00:00:00"); // TODO person.setId(patientID); person.setName(patientName); person.setCagridId(0); imageAnnotation.addPerson(person); // TODO Not general. See if we can generate AIM on GUI upload of DSO with correct user. setImageAnnotationUser(imageAnnotation, username); log.info("Saving AIM file for DSO " + imageUID + " in series " + seriesUID + " with ID " + imageAnnotation.getUniqueIdentifier()); try { boolean missingproject = false; if (projectID == null || projectID.trim().length() == 0) { missingproject = true; projectID = EPADConfig.xnatUploadProjectID; } ImageAnnotationCollection aim4 = saveImageAnnotationToServer(imageAnnotation, projectID); if (aim4 != null) { ImageReference imageReference = new ImageReference(projectID, patientID, referencedStudyUID, referencedSeriesUID, referencedImageUID[0]); EpadDatabaseOperations dbOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); EPADAIM aim = dbOperations.getAIM(imageAnnotation.getUniqueIdentifier()); if (aim != null) { if (!username.equals("shared")) dbOperations.updateAIM(aim.aimID, projectID, username); } else { aim = dbOperations.addDSOAIM(username, imageReference, seriesUID, imageAnnotation.getUniqueIdentifier(), edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(aim4), name); if ((aim.color == null || aim.color.trim().length() == 0) && segNums.length > 1) { dbOperations.updateAIMColor(aim.aimID, ","); // Indicate multiple colors needed } } if (missingproject) { EpadProjectOperations projectOperations = DefaultEpadProjectOperations.getInstance(); Project proj = projectOperations.getFirstProjectForStudy(studyUID); if (proj != null && !proj.getProjectId().equals(EPADConfig.xnatUploadProjectID)) { generateAIMFileForDSO(dsoFile, "shared", proj.getProjectId()); } } } return imageAnnotation; } catch (AimException e) { log.warning("Exception saving AIM file for DSO image " + imageUID + " in series " + seriesUID, e); } } else { log.warning("DSO " + imageUID + " in series " + seriesUID + " with no corresponding DICOM image"); } return null; /* * ServerEventUtil.postEvent(username, "DSOReady", imageAnnotation.getUniqueIdentifier(), aimName, patientID, * patientName, "", "", ""); */ } public static ImageAnnotation generateAIMForNiftiDSO(String username, String projectID, String subjectID, String studyUID, String seriesUID, String imageUID, File niftiFile) throws Exception { log.info("Creating DSO AIM for user " + username + " in project " + projectID); EpadOperations epadOperations = DefaultEpadOperations.getInstance(); EpadProjectOperations projectOperations = DefaultEpadProjectOperations.getInstance(); Dcm4CheeDatabaseOperations dcm4CheeDatabaseOperations = Dcm4CheeDatabase.getInstance() .getDcm4CheeDatabaseOperations(); NonDicomSeries ndSeries = projectOperations.getNonDicomSeries(seriesUID); String referencedSeriesUID = ndSeries.getReferencedSeries(); Date seriesDate = ndSeries.getSeriesDate(); if (seriesDate == null) seriesDate = new Date(); String dsoDate = new SimpleDateFormat("yyyyMMdd").format(seriesDate); Subject subject = projectOperations.getSubject(subjectID); String referencedStudyUID = studyUID; // Will be same study as DSO String patientName = subject.getName(); log.info("Generating AIM file for Nifti DSO: " + imageUID + " for patient " + patientName); log.info("DSO Study UID=" + studyUID); log.info("DSO Series UID=" + seriesUID); log.info("DSO Image UID=" + imageUID); log.info("Referenced Series Instance UID=" + referencedSeriesUID); List<DCM4CHEEImageDescription> imageDescriptions = dcm4CheeDatabaseOperations.getImageDescriptions(studyUID, referencedSeriesUID); String name = imageUID; if (name == null || name.trim().length() == 0) name = "segmentation"; ImageAnnotation imageAnnotation = new ImageAnnotation(0, "", dsoDate.substring(0, 4) + "-" + dsoDate.substring(4, 6) + "-" + dsoDate.substring(6, 8) + "T00:00:00", name, "SEG", "SEG Only", "", "", ""); SegmentationCollection sc = new SegmentationCollection(); sc.AddSegmentation( new Segmentation(0, imageUID, SOPClass.SegmentationStorage, imageDescriptions.get(0).imageUID, 1)); imageAnnotation.setSegmentationCollection(sc); DICOMImageReference originalDICOMImageReference = PluginAIMUtil.createDICOMImageReferenceV3Compability( referencedStudyUID, referencedSeriesUID, imageDescriptions.get(0).imageUID); imageAnnotation.addImageReference(originalDICOMImageReference); DICOMImageReference dsoDICOMImageReference = PluginAIMUtil.createDICOMImageReferenceV3Compability(studyUID, seriesUID, imageUID); imageAnnotation.addImageReference(dsoDICOMImageReference); Person person = new Person(); if (subject.getGender() != null) person.setSex(subject.getGender().trim()); Date dob = subject.getDob(); String patientBirthDay = ""; if (dob != null) patientBirthDay = new SimpleDateFormat("yyyyMMdd").format(dob); if (patientBirthDay.trim().length() == 8) person.setBirthDate(patientBirthDay.substring(0, 4) + "-" + patientBirthDay.substring(4, 6) + "-" + patientBirthDay.substring(6, 8) + "T00:00:00"); // TODO person.setId(subjectID); person.setName(patientName); person.setCagridId(0); imageAnnotation.addPerson(person); // TODO Not general. See if we can generate AIM on GUI upload of DSO with correct user. setImageAnnotationUser(imageAnnotation, username); log.info("Saving AIM file for DSO " + imageUID + " in series " + seriesUID + " with ID " + imageAnnotation.getUniqueIdentifier()); try { ImageAnnotationCollection iac = saveImageAnnotationToServer(imageAnnotation, projectID); if (iac != null) { ImageReference imageReference = new ImageReference(projectID, subjectID, referencedStudyUID, referencedSeriesUID, imageDescriptions.get(0).imageUID); EpadDatabaseOperations dbOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); EPADAIM aim = dbOperations.getAIM(imageAnnotation.getUniqueIdentifier()); if (aim != null) { if (!username.equals("shared")) dbOperations.updateAIM(aim.aimID, projectID, username); } else { dbOperations.addDSOAIM(username, imageReference, seriesUID, imageAnnotation.getUniqueIdentifier(), edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(iac), name); } } return imageAnnotation; } catch (AimException e) { log.warning("Exception saving AIM file for DSO image " + imageUID + " in series " + seriesUID, e); } return null; } private static String trimTrailing(String xnatName) { while (xnatName.endsWith("^")) xnatName = xnatName.substring(0, xnatName.length() - 1); String name = xnatName.trim(); return name; } public static boolean uploadAIMAnnotations(HttpServletRequest httpRequest, PrintWriter responseStream, String annotationsUploadDirPath) throws FileUploadException, IOException, FileNotFoundException, AimException, edu.stanford.hakan.aim4api.base.AimException { // See http://www.tutorialspoint.com/servlets/servlets-file-uploading.htm // Create a factory for disk-based file items DiskFileItemFactory factory = new DiskFileItemFactory(); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); List<FileItem> items = upload.parseRequest(httpRequest); // Process the uploaded items Iterator<FileItem> fileItemIterator = items.iterator(); String username = httpRequest.getParameter("username"); int fileCount = 0; boolean saveError = false; String projectID = httpRequest.getParameter("projectID"); String patientID = httpRequest.getParameter("patientID"); String studyID = httpRequest.getParameter("studyUID"); String seriesID = httpRequest.getParameter("seriesUID"); String imageID = httpRequest.getParameter("imageUID"); String frameNo = "0"; while (fileItemIterator.hasNext()) { FileItem fileItem = fileItemIterator.next(); if (fileItem.isFormField()) { if (fileItem.getFieldName().equals("projectID")) { projectID = fileItem.getString(); } else if (fileItem.getFieldName().equals("patientID")) { patientID = fileItem.getString(); } else if (fileItem.getFieldName().equals("studyID")) { studyID = fileItem.getString(); } else if (fileItem.getFieldName().equals("seriesID")) { seriesID = fileItem.getString(); } else if (fileItem.getFieldName().equals("imageID")) { imageID = fileItem.getString(); } else if (fileItem.getFieldName().equals("frameNo")) { frameNo = fileItem.getString(); } else if (fileItem.getFieldName().equals("username")) { username = fileItem.getString(); } } else { fileCount++; log.debug("Uploading annotation number " + fileCount); //FileItemStream fileItemStream = fileItemIterator.next(); String name = fileItem.getFieldName(); //InputStream inputStream = fileItemStream.openStream(); String tempXMLFileName = "temp-" + System.currentTimeMillis() + ".xml"; File aimFile = new File(annotationsUploadDirPath + tempXMLFileName); // write the file try { fileItem.write(aimFile); } catch (Exception e) { e.printStackTrace(); log.warning("Error receiving AIM file:" + e); responseStream.print("error reading (" + fileCount + "): " + name); continue; } responseStream.print("added (" + fileCount + "): " + name); ImageAnnotationCollection imageAnnotation = AIMUtil.getImageAnnotationFromFileV4(aimFile, xsdFilePathV4); if (imageAnnotation != null) { String jsessionID = SessionService.getJSessionIDFromRequest(httpRequest); AIMUtil.saveImageAnnotationToServer(imageAnnotation, projectID, getInt(frameNo), jsessionID); responseStream.println( "-- Add to AIM server: " + imageAnnotation.getUniqueIdentifier().getRoot() + "<br>"); } else { responseStream.println("-- Failed ! not added to AIM server<br>"); saveError = true; } if (aimFile.exists()) aimFile.delete(); projectID = null; patientID = null; studyID = null; seriesID = null; imageID = null; frameNo = "0"; } } return saveError; } /** * @param aimFile * @param projectID * @param sessionId * @param username * @param uploaded * @return true if error in AIM save * @throws AimException * @throws edu.stanford.hakan.aim4api.base.AimException */ public static boolean saveAIMAnnotation(File aimFile, String projectID, String sessionId, String username) throws AimException { return saveAIMAnnotation(aimFile, projectID, 0, sessionId, username, false); } public static boolean saveAIMAnnotation(File aimFile, String projectID, int frameNumber, String sessionId, String username, boolean uploaded) throws AimException { return saveAIMAnnotation(aimFile, projectID, frameNumber, sessionId, username, uploaded, false); } public static boolean saveAIMAnnotation(File aimFile, String projectID, int frameNumber, String sessionId, String username, boolean uploaded, boolean isDicomSR) throws AimException { final Dcm4CheeDatabaseOperations dcm4CheeDatabaseOperations = Dcm4CheeDatabase.getInstance() .getDcm4CheeDatabaseOperations(); if (aimFile == null) return true; try { log.info("Converting AIM file to ImageAnnotationCollection Object " + aimFile.getAbsolutePath()); EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); ImageAnnotationCollection imageAnnotationColl = AIMUtil.getImageAnnotationFromFileV4(aimFile, xsdFilePathV4); if (imageAnnotationColl == null) { List<Map<String, String>> coordinationTerms = new ArrayList<Map<String, String>>(); try { coordinationTerms = epadDatabaseOperations.getCoordinationData("%"); } catch (Exception x) { } ; ImageAnnotationCollection iac = edu.stanford.hakan.aim4api.usage.AnnotationGetter .getImageAnnotationCollectionFromFile(aimFile.getAbsolutePath()); edu.stanford.hakan.aim4api.compability.aimv3.ImageAnnotation iaV3 = new edu.stanford.hakan.aim4api.compability.aimv3.ImageAnnotation( iac); imageAnnotationColl = iaV3.toAimV4(coordinationTerms); if (imageAnnotationColl == null) log.warning("Unable to save aim:" + EPADFileUtils.readFileAsString(aimFile)); } if (imageAnnotationColl != null) { SegmentationEntityCollection sec = imageAnnotationColl.getImageAnnotations().get(0) .getSegmentationEntityCollection(); if (sec != null) log.debug("Aim: " + imageAnnotationColl.getUniqueIdentifier().getRoot() + " SEC size:" + sec.getSegmentationEntityList().size()); if (sec != null && imageAnnotationColl.getImageAnnotations().get(0).getListTypeCode().get(0) .getCode().equals("SEG")) { if (uploaded) throw new Exception("SEGOnly annotations should not be uploaded"); if (sec.getSegmentationEntityList().size() == 0) { epadDatabaseOperations.deleteAIM(username, imageAnnotationColl.getUniqueIdentifier().getRoot()); throw new Exception("Invalid AIM, contains empty segmentation data"); } } EPADAIM ea = epadDatabaseOperations.getAIM(imageAnnotationColl.getUniqueIdentifier().getRoot()); Aim4 aim = new Aim4(imageAnnotationColl); String patientID = aim.getPatientID(); String imageID = aim.getFirstImageID(); String seriesID = aim.getFirstSeriesID(); if (imageID != null && imageID.length() > 0) seriesID = aim.getSeriesID(imageID); String studyID = aim.getStudyID(seriesID); //try fix for aim edit tedseg if (studyID == null || studyID.equals("")) { studyID = dcm4CheeDatabaseOperations.getStudyUIDForSeries(seriesID); } List<String> seriesIds = aim.getSeriesIDs(); if (ea != null && !ea.projectID.equals(projectID)) { if (ea.projectID.equals(EPADConfig.xnatUploadProjectID)) { epadDatabaseOperations.updateAIM(ea.aimID, projectID, username); } else projectID = ea.projectID; } String dsoSeriesUID = ""; if (seriesIds.size() > 1) { dsoSeriesUID = seriesIds.get(1); log.info("Source SeriesUID:" + seriesID + " dsoSeriesUID:" + dsoSeriesUID); } if (ea != null) { log.info("frame num:" + ea.dsoFrameNo); if (ea.dsoFrameNo != 0) {//there is a frame number in db use that! log.info("setting the xml with existing frameno " + ea.dsoFrameNo + " aim: " + imageAnnotationColl.getXMLString()); imageAnnotationColl.getImageAnnotation().setDsoStartIndex(ea.dsoFrameNo); } if (ea.seriesUID == null) { log.warning("no series in aim. skipping check"); } else { log.debug("ea.seriesUID:" + ea.seriesUID + " seriesID:" + seriesID); if (ea.seriesUID != null && !ea.seriesUID.equals(seriesID) && (seriesIds.size() == 1 || !ea.seriesUID.equals(seriesIds.get(1)))) { String message = "Invalid SeriesUID in AIM xml, AimID:" + ea.aimID + " Incorrect seriesUID in AIM:" + seriesID + " Should be:" + ea.seriesUID; log.warning(message); String xml = edu.stanford.hakan.aim4api.usage.AnnotationBuilder .convertToString(imageAnnotationColl); log.info("DSO aim:" + xml); epadDatabaseOperations.deleteAIM("admin", ea.aimID); // throw new Exception(message); imageID = ea.imageUID; seriesID = ea.seriesUID; return false; } if (seriesIds.size() > 1 && ea.seriesUID != null && ea.seriesUID.equals(seriesIds.get(1))) { seriesID = seriesIds.get(1); // How weird, the actual series is second dsoSeriesUID = seriesIds.get(0); log.info("Source SeriesUID:" + seriesID + " dsoSeriesUID:" + dsoSeriesUID); } } } log.info("Saving AIM file with ID " + imageAnnotationColl.getUniqueIdentifier() + " projectID:" + projectID + " seriesUID:" + seriesID + " username:" + username); imageAnnotationColl = AIMUtil.saveImageAnnotationToServer(imageAnnotationColl, projectID, frameNumber, sessionId); String xml = edu.stanford.hakan.aim4api.usage.AnnotationBuilder .convertToString(imageAnnotationColl); if (xml == null || xml.trim().length() < 100) throw new Exception("Error converting ImageAnnotationCollection to String"); log.info("Save annotation:" + imageAnnotationColl.getUniqueIdentifier().getRoot()); if (imageAnnotationColl != null && projectID != null && username != null) { FrameReference frameReference = new FrameReference(projectID, patientID, studyID, seriesID, imageID, new Integer(frameNumber)); EPADAIM eaim = epadDatabaseOperations.addAIM(username, frameReference, imageAnnotationColl.getUniqueIdentifier().getRoot(), xml, imageAnnotationColl.getImageAnnotation().getName().getValue(), isDicomSR); try { if (sec != null && sec.getSegmentationEntityList().size() > 0) { if (sec.getSegmentationEntityList().get(0).getXsiType() .equals("DicomSegmentationEntity")) { DicomSegmentationEntity dse = (DicomSegmentationEntity) sec .getSegmentationEntityList().get(0); log.info("DSO RSUID:" + dse.getReferencedSopInstanceUid().getRoot() + " SUID:" + dse.getSopInstanceUid().getRoot()); SeriesReference seriesReference = new SeriesReference(projectID, null, null, seriesID); List<EPADAIM> aims = epadDatabaseOperations.getAIMs(seriesReference); //ml aim for no imageref for dso if (dse != null && seriesIds.size() == 1) { dsoSeriesUID = dcm4CheeDatabaseOperations .getSeriesUIDForImage(dse.getSopInstanceUid().getRoot()); if (dsoSeriesUID.equals("")) { //DSO is not in db yet //required info // seriesID,dsoInstanceUid,aimID,projectID dsoAims.add(new String[] { seriesID, dse.getSopInstanceUid().getRoot(), eaim.aimID, projectID, String.valueOf(isDicomSR) }); } } // updateDSOStartIndex(eaim, e.ds); //if (eaim != null && eaim.dsoSeriesUID == null && aims.size() > 1 && seriesIds.size() > 1) { //ml if (eaim != null && eaim.dsoSeriesUID == null && aims.size() > 1 && !dsoSeriesUID.equals("")) { for (EPADAIM e : aims) { log.info("Checking, aimID:" + e.aimID + " dsoSeries:" + e.dsoSeriesUID + " this:" + dsoSeriesUID); if (!e.aimID.equals(eaim.aimID) && e.dsoSeriesUID != null && e.dsoSeriesUID.equals(dsoSeriesUID)) { ImageReference imageReference = new ImageReference(projectID, e.subjectID, e.studyUID, e.seriesUID, e.imageUID); if (((eaim.name != null && e.name != null) && (eaim.name.equals(e.name) || eaim.name.equals(e.name.replace("ePAD DSO-", "")))) || (e.isDicomSR == false && eaim.isDicomSR == false)) {// if none of them are dicomsr epadDatabaseOperations.deleteAIM("admin", e.aimID); log.info("Deleting aim with name:" + e.name + " and aimID:" + eaim.aimID); } log.info("Updating dsoSeriesUID in aim database:" + e.dsoSeriesUID + " aimID:" + eaim.aimID); epadDatabaseOperations.addDSOAIM(username, imageReference, e.dsoSeriesUID, eaim.aimID); if (eaim.dsoFrameNo == 0) epadDatabaseOperations.updateAIMDSOFrameNo(eaim.aimID, e.dsoFrameNo); // break; } } } } } } catch (Exception x) { log.warning("Error checking segmentation", x); } } return false; } } catch (Exception e) { try { log.warning("Error saving annotation:" + EPADFileUtils.readFileAsString(aimFile), e); } catch (Exception x) { log.warning("Error saving annotation", e); } throw new edu.stanford.hakan.aim4api.base.AimException(e.getMessage()); } return true; } public static AIMSearchType getAIMSearchType(HttpServletRequest httpRequest) { for (AIMSearchType aimSearchType : AIMSearchType.values()) { if (httpRequest.getParameter(aimSearchType.getName()) != null) return aimSearchType; } log.warning("No valid AIM search type parameter found"); return null; } public static void queryAIMImageAnnotations(PrintWriter responseStream, AIMSearchType aimSearchType, Map<String, String> searchValueByProject, String user) throws ParserConfigurationException, AimException, edu.stanford.hakan.aim4api.base.AimException { long starttime = System.currentTimeMillis(); List<ImageAnnotationCollection> aims = new ArrayList<ImageAnnotationCollection>(); for (String projectID : searchValueByProject.keySet()) { log.info("ProjectID:" + projectID + " type:" + aimSearchType + " value:" + searchValueByProject.get(projectID)); List<ImageAnnotationCollection> paims = AIMQueries.getAIMImageAnnotationsV4(projectID, aimSearchType, searchValueByProject.get(projectID), user); log.info("" + paims.size() + " AIM4 file(s) found for project:" + projectID + " for user " + user); aims.addAll(paims); } returnImageAnnotationsXMLV4(responseStream, aims); } public static void queryAIMImageAnnotations(PrintWriter responseStream, String projectID, AIMSearchType aimSearchType, String searchValue, String user) throws ParserConfigurationException, AimException, edu.stanford.hakan.aim4api.base.AimException { queryAIMImageAnnotationsV4(responseStream, projectID, aimSearchType, searchValue, user); } public static void queryAIMImageAnnotations(PrintWriter responseStream, String projectID, AIMSearchType aimSearchType, String searchValue, String user, int startIndex, int count) throws ParserConfigurationException, AimException, edu.stanford.hakan.aim4api.base.AimException { queryAIMImageAnnotationsV4(responseStream, projectID, aimSearchType, searchValue, user); } //ml aimv3 is not used anymore public static EPADAIMList queryAIMImageAnnotationSummaries(EPADAIMList aims, String user, int index, int count, String sessionID) throws ParserConfigurationException, AimException { Map<String, String> projectAimIDs = getUIDCsvList(sessionID, aims, user); List<ImageAnnotation> annotations = new ArrayList<ImageAnnotation>(); for (String projectId : projectAimIDs.keySet()) { annotations.addAll(AIMQueries.getAIMImageAnnotations(projectId, AIMSearchType.ANNOTATION_UID, projectAimIDs.get(projectId), user, index, count)); } log.info("" + annotations.size() + " AIM file(s) found for user " + user); Map<String, EPADAIM> aimMAP = new HashMap<String, EPADAIM>(); EPADAIMResultSet rs = aims.ResultSet; for (EPADAIM aim : rs.Result) { aimMAP.put(aim.aimID, aim); } aims = new EPADAIMList(); long starttime = System.currentTimeMillis(); for (ImageAnnotation aim : annotations) { Aim a = new Aim(aim); EPADAIM ea = aimMAP.get(aim.getUniqueIdentifier()); ea.name = aim.getName(); ea.template = aim.getCodeMeaning(); ea.templateType = aim.getCodeValue(); ea.date = aim.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = null; aims.addAIM(ea); } long parsetime = System.currentTimeMillis(); log.info("Time taken to parse annotations:" + (parsetime - starttime) + " msecs"); log.info("" + annotations.size() + " annotations returned to client"); return aims; } public static void queryAIMImageAnnotationsV4(PrintWriter responseStream, EPADAIMList aims, AIMSearchType aimSearchType, String searchValue, String user, String sessionID, boolean jsonFormat) throws Exception { Map<String, String> aimIdsMap = getUIDCsvList(sessionID, aims, user); Map<String, EPADAIM> aimsMap = new HashMap<String, EPADAIM>(); for (EPADAIM aim : aims.ResultSet.Result) { aimsMap.put(aim.aimID, aim); } if (!aimSearchType.equals(AIMSearchType.JSON_QUERY)) { List<ImageAnnotationCollection> iacs = new ArrayList<ImageAnnotationCollection>(); for (String projectID : aimIdsMap.keySet()) { String aimIds = "," + aimIdsMap.get(projectID) + ","; List<ImageAnnotationCollection> paims = AIMQueries.getAIMImageAnnotationsV4(projectID, aimSearchType, searchValue, user); for (ImageAnnotationCollection aim : paims) { if (aimIds.contains("," + aim.getUniqueIdentifier().getRoot() + ",")) iacs.add(aim); } } log.info("" + iacs.size() + " AIM4 file(s) found for user " + user); if (iacs.size() == 0) return; if (!jsonFormat) { returnImageAnnotationsXMLV4(responseStream, iacs); return; } else { StringBuilder xml = new StringBuilder("<imageAnnotations>\n"); for (ImageAnnotationCollection iac : iacs) { EPADAIM aim = aimsMap.get(iac.getUniqueIdentifier().getRoot()); if (aim != null && aim.xml != null) xml.append(aim.xml); } xml.append("</imageAnnotations>\n"); responseStream.print(xml); } } else { StringBuilder jsonSB = new StringBuilder("{\"imageAnnotations\":"); int count = 0; List<String> jsonIds = new ArrayList<String>(); for (String projectID : aimIdsMap.keySet()) { String aimIds = "," + aimIdsMap.get(projectID) + ","; List<String> jsons = AIMQueries.getJsonAnnotations(projectID, aimSearchType, searchValue, user); for (String json : jsons) { JsonObject root = (JsonObject) new JsonParser().parse(json); JsonObject imageCollection = root.getAsJsonObject("ImageAnnotationCollection"); String aimID = imageCollection.getAsJsonObject("uniqueIdentifier").getAsJsonPrimitive("root") .getAsString(); if (aimIds.contains("," + aimID + ",")) { if (count > 0) jsonSB.append(","); jsonSB.append(json); jsonIds.add(aimID); count++; } } } jsonSB.append("}"); log.info("" + count + " AIM4 file(s) found for user " + user); if (count == 0) return; if (jsonFormat) { responseStream.print(jsonSB); return; } else { StringBuilder xml = new StringBuilder("<imageAnnotations>\n"); for (String id : jsonIds) { EPADAIM aim = aimsMap.get(id); if (aim != null && aim.xml != null) xml.append(aim.xml); } xml.append("</imageAnnotations>\n"); responseStream.print(xml); } } } public static void queryAIMImageAnnotationsV4(PrintWriter responseStream, String projectID, AIMSearchType aimSearchType, String searchValue, String user) throws ParserConfigurationException, edu.stanford.hakan.aim4api.base.AimException { List<ImageAnnotationCollection> aims = AIMQueries.getAIMImageAnnotationsV4(projectID, aimSearchType, searchValue, user); log.info("" + aims.size() + " AIM4 file(s) found for user " + user); if (aims.size() == 0) return; returnImageAnnotationsXMLV4(responseStream, aims); } public static void returnImageAnnotationsXMLV4(PrintWriter responseStream, List<ImageAnnotationCollection> aims) throws ParserConfigurationException, edu.stanford.hakan.aim4api.base.AimException { long starttime = System.currentTimeMillis(); DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); Document doc = docBuilder.newDocument(); Element root = doc.createElement("imageAnnotations"); doc.appendChild(root); for (ImageAnnotationCollection aim : aims) { Node node = aim.getXMLNode(docBuilder.newDocument()); Node copyNode = doc.importNode(node, true); Element res = (Element) copyNode; // Copy the node res.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); res.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); res.setAttribute("xsi:schemaLocation", "gme://caCORE.caCORE/4.4/edu.northwestern.radiology.AIM AIM_v4_rv44_XML.xsd"); res.setAttribute("xmlns", "gme://caCORE.caCORE/4.4/edu.northwestern.radiology.AIM"); Node n = renameNodeNS(res, "ImageAnnotationCollection", "gme://caCORE.caCORE/4.4/edu.northwestern.radiology.AIM"); root.appendChild(n); // Adding to the root } String queryResults = XmlDocumentToString(doc, "gme://caCORE.caCORE/4.4/edu.northwestern.radiology.AIM"); long xmltime = System.currentTimeMillis(); log.info("Time taken create xml:" + (xmltime - starttime) + " msecs for " + aims.size() + " annotations"); responseStream.print(queryResults); long resptime = System.currentTimeMillis(); log.info("" + aims.size() + " annotations returned to client, time to write resp:" + (resptime - xmltime) + " msecs"); } public static EPADAIMList filterPermittedImageAnnotations(EPADAIMList aims, String user, String sessionID) throws ParserConfigurationException, AimException { return filterPermittedImageAnnotations(aims, user, sessionID, null); } public static EPADAIMList filterPermittedImageAnnotations(EPADAIMList aims, String user, String sessionID, String projectUID) throws ParserConfigurationException, AimException { long starttime = System.currentTimeMillis(); EPADAIMList aimsFromExist = new EPADAIMList(); EPADAIMList aimsFromDB = new EPADAIMList(); for (EPADAIM ea : aims.ResultSet.Result) { if (projectUID == null || projectUID.equals("") || ea.projectID.equals(projectUID)) { if (ea.xml == null || ea.xml.equals("")) { aimsFromExist.addAIM(ea); } else { aimsFromDB.addAIM(ea); } } } log.info("aimd from db:" + aimsFromDB.ResultSet.totalRecords); List<EPADAIM> aimsDB = new ArrayList<EPADAIM>(); if (aimsFromDB.ResultSet.totalRecords > 0) { // Check permissions for aims from DB table Map<String, List<EPADAIM>> aimsMap = getPermittedAIMs(sessionID, aimsFromDB, user); long permtime = System.currentTimeMillis(); for (List<EPADAIM> paims : aimsMap.values()) { aimsDB.addAll(paims); } // Get other params for (int i = 0; i < aimsDB.size(); i++) { EPADAIM ea = aimsDB.get(i); try { List<ImageAnnotationCollection> iacs = edu.stanford.hakan.aim4api.usage.AnnotationGetter .getImageAnnotationCollectionsFromString(ea.xml, null); ImageAnnotationCollection aim = iacs.get(0); Aim4 a = new Aim4(aim); ea.name = aim.getImageAnnotations().get(0).getName().getValue(); //ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystem();// .getCode(); //ml ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); ea.date = aim.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = aim.getXMLString(); //the only different thing from summaries!!! very bad solution!! } catch (edu.stanford.hakan.aim4api.base.AimException e) { log.warning("Invalid AIM xml in DB, aimID:" + ea.aimID, e); aimsDB.remove(i--); aimsFromExist.addAIM(ea); } } } long dbtime = System.currentTimeMillis(); List<ImageAnnotationCollection> annotations = new ArrayList<ImageAnnotationCollection>(); if (aimsFromExist.ResultSet.totalRecords > 0) { // Check permission for aims from Exist Map<String, String> projectAimIDs = getUIDCsvList(sessionID, aimsFromExist, user); for (String projectID : projectAimIDs.keySet()) { String uids = projectAimIDs.get(projectID); if (uids.trim().length() > 0) { List<ImageAnnotationCollection> iacs = AIMQueries.getAIMImageAnnotationsV4(projectID, AIMSearchType.ANNOTATION_UID, uids, user); annotations.addAll(iacs); if (iacs.size() == 0) log.warning("Annotations not found in Exist for uids:" + uids); log.info("" + iacs.size() + " AIM4 file(s) found for project:" + projectID + " for user " + user); } } } long existtime = System.currentTimeMillis(); Map<String, EPADAIM> aimMAP = new HashMap<String, EPADAIM>(); EPADAIMResultSet rs = aims.ResultSet; for (EPADAIM aim : rs.Result) { aimMAP.put(aim.aimID, aim); } aims = new EPADAIMList(); for (ImageAnnotationCollection aim : annotations) { try { Aim4 a = new Aim4(aim); EPADAIM ea = aimMAP.get(aim.getUniqueIdentifier()); if (ea == null) continue; if (aim.getImageAnnotations().get(0).getName() != null) { ea.name = aim.getImageAnnotations().get(0).getName().getValue(); } if (aim.getImageAnnotations().get(0).getListTypeCode() != null && aim.getImageAnnotations().get(0).getListTypeCode().size() > 0) { //ml what is this? //it is like this just above // ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getDisplayName().getValue(); // ea.templateType = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); //ml ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); } ea.date = aim.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = aim.getXMLString(); //the only different thing from summaries!!! very bad solution!! aims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing annotation:" + aim, x); x.printStackTrace(); } } aims.ResultSet.Result.addAll(aimsDB); aims.ResultSet.totalRecords = aims.ResultSet.Result.size(); long endtime = System.currentTimeMillis(); log.info("" + aims.ResultSet.totalRecords + " annotation summaries returned to client, took:" + (endtime - starttime) + " msecs, db time:" + (dbtime - starttime) + " exist time:" + (existtime - dbtime) + " iac to summaries:" + (existtime - endtime)); return aims; } public static EPADAIMList queryAIMImageAnnotationSummariesV4(EPADAIMList aims, String user, String sessionID) throws ParserConfigurationException, AimException { long starttime = System.currentTimeMillis(); EPADAIMList aimsFromExist = new EPADAIMList(); EPADAIMList aimsFromDB = new EPADAIMList(); for (EPADAIM ea : aims.ResultSet.Result) { if (ea.xml == null || ea.xml.equals("")) { aimsFromExist.addAIM(ea); } else { aimsFromDB.addAIM(ea); } } List<EPADAIM> aimsDB = new ArrayList<EPADAIM>(); if (aimsFromDB.ResultSet.totalRecords > 0) { // Check permissions for aims from DB table Map<String, List<EPADAIM>> aimsMap = getPermittedAIMs(sessionID, aimsFromDB, user); long permtime = System.currentTimeMillis(); for (List<EPADAIM> paims : aimsMap.values()) { aimsDB.addAll(paims); } // Get other params for (int i = 0; i < aimsDB.size(); i++) { EPADAIM ea = aimsDB.get(i); try { List<ImageAnnotationCollection> iacs = edu.stanford.hakan.aim4api.usage.AnnotationGetter .getImageAnnotationCollectionsFromString(ea.xml, null); ImageAnnotationCollection aim = iacs.get(0); Aim4 a = new Aim4(aim); ea.name = aim.getImageAnnotations().get(0).getName().getValue(); //ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystem();// .getCode(); //ml ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); ea.date = aim.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = null; } catch (edu.stanford.hakan.aim4api.base.AimException e) { log.warning("Invalid AIM xml in DB, aimID:" + ea.aimID, e); aimsDB.remove(i--); aimsFromExist.addAIM(ea); } } } long dbtime = System.currentTimeMillis(); List<ImageAnnotationCollection> annotations = new ArrayList<ImageAnnotationCollection>(); if (aimsFromExist.ResultSet.totalRecords > 0) { // Check permission for aims from Exist Map<String, String> projectAimIDs = getUIDCsvList(sessionID, aimsFromExist, user); for (String projectID : projectAimIDs.keySet()) { String uids = projectAimIDs.get(projectID); if (uids.trim().length() > 0) { List<ImageAnnotationCollection> iacs = AIMQueries.getAIMImageAnnotationsV4(projectID, AIMSearchType.ANNOTATION_UID, uids, user); annotations.addAll(iacs); if (iacs.size() == 0) log.warning("Annotations not found in Exist for uids:" + uids); log.info("" + iacs.size() + " AIM4 file(s) found for project:" + projectID + " for user " + user); } } } long existtime = System.currentTimeMillis(); Map<String, EPADAIM> aimMAP = new HashMap<String, EPADAIM>(); EPADAIMResultSet rs = aims.ResultSet; for (EPADAIM aim : rs.Result) { aimMAP.put(aim.aimID, aim); } aims = new EPADAIMList(); for (ImageAnnotationCollection aim : annotations) { try { Aim4 a = new Aim4(aim); EPADAIM ea = aimMAP.get(aim.getUniqueIdentifier()); if (ea == null) continue; if (aim.getImageAnnotations().get(0).getName() != null) { ea.name = aim.getImageAnnotations().get(0).getName().getValue(); } if (aim.getImageAnnotations().get(0).getListTypeCode() != null && aim.getImageAnnotations().get(0).getListTypeCode().size() > 0) { //ml what is this? //it is like this just above // ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getDisplayName().getValue(); // ea.templateType = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); //ml ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); } ea.date = aim.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); aims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing annotation:" + aim, x); x.printStackTrace(); } } aims.ResultSet.Result.addAll(aimsDB); aims.ResultSet.totalRecords = aims.ResultSet.Result.size(); long endtime = System.currentTimeMillis(); log.info("" + aims.ResultSet.totalRecords + " annotation summaries returned to client, took:" + (endtime - starttime) + " msecs, db time:" + (dbtime - starttime) + " exist time:" + (existtime - dbtime) + " iac to summaries:" + (existtime - endtime)); return aims; } public static EPADAIMList queryAIMImageAnnotationSummariesV4(EPADAIMList aims, AIMSearchType searchType, String searchValue, String user, String sessionID) throws Exception { long starttime = System.currentTimeMillis(); EPADAIMList returnAims = new EPADAIMList(); Map<String, List<EPADAIM>> aimsMap = getPermittedAIMs(sessionID, aims, user); if (searchType.equals(AIMSearchType.AIM_QUERY)) { for (String projectID : aimsMap.keySet()) { List<EPADAIM> paims = aimsMap.get(projectID); Map<String, EPADAIM> paimsMap = new HashMap<String, EPADAIM>(); for (EPADAIM paim : paims) { paimsMap.put(paim.aimID, paim); } List<ImageAnnotationCollection> iacs = AIMQueries.getAIMImageAnnotationsV4(projectID, searchType, searchValue, user); // Get other params for (int i = 0; i < iacs.size(); i++) { ImageAnnotationCollection iac = iacs.get(i); try { EPADAIM ea = paimsMap.get(iac.getUniqueIdentifier().getRoot()); Aim4 a = new Aim4(iac); ea.name = iac.getImageAnnotations().get(0).getName().getValue(); //ml ea.template = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = iac.getImageAnnotations().get(0).getListTypeCode().get(0) .getCodeSystemName(); ea.date = iac.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = null; returnAims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing ImageAnnotationCollection:" + iac, x); } } } } else if (searchType.equals(AIMSearchType.JSON_QUERY)) { for (String projectID : aimsMap.keySet()) { List<EPADAIM> paims = aimsMap.get(projectID); Map<String, EPADAIM> paimsMap = new HashMap<String, EPADAIM>(); for (EPADAIM paim : paims) { paimsMap.put(paim.aimID, paim); } List<String> jsons = AIMQueries.getJsonAnnotations(projectID, searchType, searchValue, user); log.debug("Json query:" + searchValue + " number of matchs:" + jsons.size()); // Get other params for (int i = 0; i < jsons.size(); i++) { JsonObject root = null; try { root = (JsonObject) new JsonParser().parse(jsons.get(i)); //log.debug("Json result:" + root); JsonObject imageCollection = root.getAsJsonObject("ImageAnnotationCollection"); String aimID = imageCollection.getAsJsonObject("uniqueIdentifier") .getAsJsonPrimitive("root").getAsString(); EPADAIM ea = paimsMap.get(aimID); //log.debug("Json ImageAnnotation:" + imageCollection.getAsJsonObject("imageAnnotations").getAsJsonObject("ImageAnnotation")); ea.name = imageCollection.getAsJsonObject("imageAnnotations") .getAsJsonObject("ImageAnnotation").getAsJsonObject("name") .getAsJsonPrimitive("value").getAsString(); //ml ea.template = imageCollection.getAsJsonObject("imageAnnotations") .getAsJsonObject("ImageAnnotation").getAsJsonObject("typeCode") .getAsJsonPrimitive("code").getAsString(); ea.templateType = imageCollection.getAsJsonObject("imageAnnotations") .getAsJsonObject("ImageAnnotation").getAsJsonObject("typeCode") .getAsJsonPrimitive("codeSystemName").getAsString(); ea.date = imageCollection.getAsJsonObject("dateTime").getAsJsonPrimitive("value") .getAsString(); ea.comment = imageCollection.getAsJsonObject("imageAnnotations") .getAsJsonObject("ImageAnnotation").getAsJsonObject("comment") .getAsJsonPrimitive("value").getAsString(); ea.studyDate = ((JsonObject) imageCollection.getAsJsonObject("imageAnnotations") .getAsJsonObject("ImageAnnotation") .getAsJsonObject("imageReferenceEntityCollection") .getAsJsonArray("ImageReferenceEntity").get(0)).getAsJsonObject("imageStudy") .getAsJsonObject("startDate").getAsJsonPrimitive("value").getAsString(); ea.patientName = imageCollection.getAsJsonObject("person").getAsJsonObject("name") .getAsJsonPrimitive("value").getAsString(); ea.xml = null; returnAims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing json annotation:" + root, x); } } } } long endtime = System.currentTimeMillis(); log.info("" + returnAims.ResultSet.totalRecords + " annotation summaries returned to client, took:" + (endtime - starttime) + " msecs"); return returnAims; } public static void queryAIMImageAnnotationsV4(PrintWriter responseStream, EPADAIMList aims, String user, String sessionID) throws ParserConfigurationException, edu.stanford.hakan.aim4api.base.AimException { long starttime = System.currentTimeMillis(); String annotationsXML = queryAIMImageAnnotationsV4(aims, user, sessionID); responseStream.print(annotationsXML); long resptime = System.currentTimeMillis(); log.info("Time to write resp:" + (resptime - starttime) + " msecs"); } public static void queryAIMImageJsonAnnotations(PrintWriter responseStream, EPADAIMList aims, String user, String sessionID) throws Exception { long starttime = System.currentTimeMillis(); String annotationsXML = queryAIMImageAnnotationsV4(aims, user, sessionID); String jsonString = XML.toJSONObject(annotationsXML).toString(0); ; if (jsonString == null) throw new Exception("Error converting to json"); responseStream.print(jsonString); long resptime = System.currentTimeMillis(); log.info("Time to write resp:" + (resptime - starttime) + " msecs"); } public static String queryAIMImageAnnotationsV4(EPADAIMList aims, String user, String sessionID) throws ParserConfigurationException, edu.stanford.hakan.aim4api.base.AimException { long starttime = System.currentTimeMillis(); EPADAIMList aimsFromExist = new EPADAIMList(); EPADAIMList aimsFromDB = new EPADAIMList(); for (EPADAIM ea : aims.ResultSet.Result) { if (ea.xml == null || ea.xml.equals("")) { aimsFromExist.addAIM(ea); } else { aimsFromDB.addAIM(ea); } } StringBuilder aimsDBXml = new StringBuilder("<imageAnnotations>\n"); List<EPADAIM> aimsDB = new ArrayList<EPADAIM>(); if (aimsFromDB.ResultSet.totalRecords > 0) { // Check permissions for aims from DB table Map<String, List<EPADAIM>> aimsMap = getPermittedAIMs(sessionID, aimsFromDB, user); for (List<EPADAIM> paims : aimsMap.values()) { for (int i = 0; i < paims.size(); i++) { EPADAIM ea = paims.get(i); aimsDBXml.append(ea.xml); aimsDB.add(ea); } } } List<ImageAnnotationCollection> annotations = new ArrayList<ImageAnnotationCollection>(); if (aimsFromExist.ResultSet.totalRecords > 0) { // Check permission for aims from Exist Map<String, String> projectAimIDs = getUIDCsvList(sessionID, aimsFromExist, user); for (String projectID : projectAimIDs.keySet()) { String uids = projectAimIDs.get(projectID); if (uids.trim().length() > 0) { List<ImageAnnotationCollection> iacs = AIMQueries.getAIMImageAnnotationsV4(projectID, AIMSearchType.ANNOTATION_UID, uids, user); annotations.addAll(iacs); if (iacs.size() == 0) log.warning("Annotations not found in Exist for uids:" + uids); log.info("" + iacs.size() + " AIM4 file(s) found for project:" + projectID + " for user " + user); } } } for (ImageAnnotationCollection aim : annotations) { aimsDBXml.append(edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(aim)); } long xmltime = System.currentTimeMillis(); aimsDBXml.append("</imageAnnotations>\n"); log.info("Time taken create xml:" + (xmltime - starttime) + " msecs for " + (annotations.size() + aimsDB.size()) + " annotations"); return aimsDBXml.toString(); } public static EPADAIMList getAllVersionSummaries(EPADAIM aim) throws Exception { List<ImageAnnotationCollection> iacs = AIMQueries.getAllVersions(aim); EPADAIMList aims = new EPADAIMList(); for (int i = 0; i < iacs.size(); i++) { ImageAnnotationCollection iac = iacs.get(i); try { Aim4 a = new Aim4(iac); EPADAIM ea = new EPADAIM(iac.getUniqueIdentifier().getRoot(), aim.userName, aim.projectID, aim.subjectID, aim.studyUID, aim.seriesUID, aim.imageUID, aim.instanceOrFrameNumber); ea.name = iac.getImageAnnotations().get(0).getName().getValue(); //ml ea.template = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); ea.date = iac.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = null; ea.user = a.getLoggedInUser().getLoginName(); aims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing ImageAnnotationCollection:" + iac, x); } } return aims; } public static EPADAIMList getPreviousVersionSummaries(EPADAIM aim) throws Exception { List<ImageAnnotationCollection> iacs = AIMQueries.getPreviousVersions(aim); EPADAIMList aims = new EPADAIMList(); for (int i = 0; i < iacs.size(); i++) { ImageAnnotationCollection iac = iacs.get(i); try { Aim4 a = new Aim4(iac); EPADAIM ea = new EPADAIM(iac.getUniqueIdentifier().getRoot(), aim.userName, aim.projectID, aim.subjectID, aim.studyUID, aim.seriesUID, aim.imageUID, aim.instanceOrFrameNumber); ea.name = iac.getImageAnnotations().get(0).getName().getValue(); //ml ea.template = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); ea.date = iac.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = null; ea.user = a.getLoggedInUser().getLoginName(); aims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing ImageAnnotationCollection:" + iac, x); } } return aims; } public static EPADAIMList getNextVersionSummaries(EPADAIM aim) throws Exception { List<ImageAnnotationCollection> iacs = AIMQueries.getNextVersions(aim); EPADAIMList aims = new EPADAIMList(); for (int i = 0; i < iacs.size(); i++) { ImageAnnotationCollection iac = iacs.get(i); try { Aim4 a = new Aim4(iac); EPADAIM ea = new EPADAIM(iac.getUniqueIdentifier().getRoot(), aim.userName, aim.projectID, aim.subjectID, aim.studyUID, aim.seriesUID, aim.imageUID, aim.instanceOrFrameNumber); ea.name = iac.getImageAnnotations().get(0).getName().getValue(); //ml ea.template = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); ea.date = iac.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = null; ea.user = a.getLoggedInUser().getLoginName(); aims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing ImageAnnotationCollection:" + iac, x); } } return aims; } public static void returnAllVersions(PrintWriter responseStream, EPADAIM aim) throws Exception { List<ImageAnnotationCollection> iacs = AIMQueries.getAllVersions(aim); StringBuilder annotationsXML = new StringBuilder("<imageAnnotations>\n"); for (ImageAnnotationCollection iac : iacs) { annotationsXML.append(edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(iac)); } annotationsXML.append("</imageAnnotations>\n"); responseStream.print(annotationsXML); return; } public static void returnPreviousVersions(PrintWriter responseStream, EPADAIM aim) throws Exception { List<ImageAnnotationCollection> iacs = AIMQueries.getPreviousVersions(aim); StringBuilder annotationsXML = new StringBuilder("<imageAnnotations>\n"); for (ImageAnnotationCollection iac : iacs) { annotationsXML.append(edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(iac)); } annotationsXML.append("</imageAnnotations>\n"); responseStream.print(annotationsXML); return; } public static void undoLastAIM(EPADAIM aim) throws Exception { List<ImageAnnotationCollection> iacs = AIMQueries.getPreviousVersions(aim); if (iacs.size() == 0) throw new Exception("Undo List is empty"); ImageAnnotationCollection iac = AIMQueries.makeCurrent(aim, iacs.get(0)); EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); epadDatabaseOperations.updateAIMXml(aim.aimID, edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(iac)); } public static void redoLastAIM(EPADAIM aim) throws Exception { List<ImageAnnotationCollection> iacs = AIMQueries.getNextVersions(aim); if (iacs.size() == 0) throw new Exception("Redo List is empty"); ImageAnnotationCollection iac = AIMQueries.makeCurrent(aim, iacs.get(0)); EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); epadDatabaseOperations.updateAIMXml(aim.aimID, edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(iac)); } public static EPADAIMList queryDeletedAIMImageAnnotationSummaries(AIMSearchType searchType, String searchValue, String user) throws Exception { long starttime = System.currentTimeMillis(); EPADAIMList returnAims = new EPADAIMList(); List<ImageAnnotationCollection> iacs = AIMQueries.getDeletedAIMImageAnnotations(searchType, searchValue, user); // Get other params for (int i = 0; i < iacs.size(); i++) { ImageAnnotationCollection iac = iacs.get(i); try { Aim4 a = new Aim4(iac); EPADAIM ea = new EPADAIM(iac.getUniqueIdentifier().getRoot(), a.getLoggedInUser().getLoginName(), "", a.getPatientID(), a.getFirstStudyID(), a.getFirstSeriesID(), a.getFirstImageID(), 0); ea.name = iac.getImageAnnotations().get(0).getName().getValue(); //ml ea.template = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); ea.date = iac.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); ea.xml = null; returnAims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing ImageAnnotationCollection:" + iac, x); } } long endtime = System.currentTimeMillis(); log.info("" + returnAims.ResultSet.totalRecords + " annotation summaries returned to client, took:" + (endtime - starttime) + " msecs"); return returnAims; } public static void queryDeletedAIMImageAnnotations(PrintWriter responseStream, AIMSearchType searchType, String searchValue, String user, String sessionID) throws Exception { long starttime = System.currentTimeMillis(); String annotationsXML = queryDeletedAIMImageAnnotations(searchType, searchValue, user); responseStream.print(annotationsXML); long resptime = System.currentTimeMillis(); log.info("Time to write resp:" + (resptime - starttime) + " msecs"); } public static void queryDeletedAIMImageJsonAnnotation(PrintWriter responseStream, AIMSearchType searchType, String searchValue, String user, String sessionID) throws Exception { long starttime = System.currentTimeMillis(); String annotationsXML = queryDeletedAIMImageAnnotations(searchType, searchValue, user); String jsonString = XML.toJSONObject(annotationsXML).toString(0); ; if (jsonString == null) throw new Exception("Error converting to json"); responseStream.print(jsonString); long resptime = System.currentTimeMillis(); log.info("Time to write resp:" + (resptime - starttime) + " msecs"); } public static String queryDeletedAIMImageAnnotations(AIMSearchType searchType, String searchValue, String user) throws Exception { long starttime = System.currentTimeMillis(); StringBuilder aimsDBXml = new StringBuilder("<imageAnnotations>\n"); List<ImageAnnotationCollection> iacs = AIMQueries.getDeletedAIMImageAnnotations(searchType, searchValue, user); for (ImageAnnotationCollection aim : iacs) { aimsDBXml.append(edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(aim)); } long xmltime = System.currentTimeMillis(); aimsDBXml.append("</imageAnnotations>\n"); log.info("Time taken create xml:" + (xmltime - starttime) + " msecs for " + iacs.size() + " annotations"); return aimsDBXml.toString(); } private static String XmlDocumentToString(Document document, String xmlns) { // Create an XML document from a String new XmlNamespaceTranslator().addTranslation(null, xmlns).addTranslation("", xmlns) .translateNamespaces(document); TransformerFactory transfac = TransformerFactory.newInstance(); Transformer trans = null; try { trans = transfac.newTransformer(); } catch (TransformerConfigurationException e) { log.warning("Error transforming XML document", e); } trans.setOutputProperty(OutputKeys.INDENT, "yes"); StringWriter sw = new StringWriter(); StreamResult result = new StreamResult(sw); DOMSource source = new DOMSource(document); try { trans.transform(source, result); } catch (TransformerException e) { log.warning("Error transforming XML document", e); } return sw.toString(); } // Rename namespace of the nodes private static Node renameNodeNS(Node node, String newName, String xmlns) { Element newNode = node.getOwnerDocument().createElementNS(xmlns, newName); NamedNodeMap map = node.getAttributes(); for (int i = 0; i < map.getLength(); i++) { newNode.setAttribute(map.item(i).getNodeName(), map.item(i).getNodeValue()); } NodeList tempList = node.getChildNodes(); for (int i = 0; i < tempList.getLength(); i++) { newNode.appendChild(tempList.item(i).cloneNode(true)); } return newNode; } // public static ImageAnnotation getImageAnnotationFromFile(File file, String xsdFilePath) { // try { // return AnnotationGetter.getImageAnnotationFromFile(file.getAbsolutePath(), xsdFilePath); // } catch (AimException e) { // return null; // } // } public static ImageAnnotationCollection getImageAnnotationFromFileV4(File file, String xsdFilePath) { try { String version = AnnotationValidator.getAimVersion(file.getAbsolutePath()); if ("".equals(version)) { throw new AimException("This is not a AIM Annotation File."); } if (version.contains("4")) return edu.stanford.hakan.aim4api.usage.AnnotationGetter .getImageAnnotationCollectionFromFile(file.getAbsolutePath(), xsdFilePath); else return edu.stanford.hakan.aim4api.usage.AnnotationGetter .getImageAnnotationCollectionFromFile(file.getAbsolutePath()); } catch (Exception e) { return null; } } public static String runPlugIn(String[] aimIDs, String templateName, String projectID, String jsessionID) throws Exception { return runPlugIn(aimIDs, templateName, projectID, jsessionID, true); } public static String runPlugIn(String[] aimIDs, String templateName, String projectID, String jsessionID, boolean inParallel) throws Exception { String result = ""; //ml moved out of for. look once boolean templateHasBeenFound = false; String handlerName = null; String pluginName = null; List<String> list = PluginConfig.getInstance().getPluginTemplateList(); log.info("plugin count: " + list.size()); for (int i = 0; i < list.size(); i++) { String templateNameFounded = list.get(i); log.info("found plugin: " + templateNameFounded + " name:" + PluginConfig.getInstance().getPluginNameList().get(i)); if (templateNameFounded.equals(templateName)) { handlerName = PluginConfig.getInstance().getPluginHandlerList().get(i); pluginName = PluginConfig.getInstance().getPluginNameList().get(i); templateHasBeenFound = true; } } if (inParallel) { for (String aimID : aimIDs) { if (isPluginStillRunning(aimID)) { result = result + "\n" + "Previous version of this AIM " + aimID + " is still being processed by the plugin"; continue; } if (templateHasBeenFound && jsessionID != null) { log.info("Starting Plugin task for:" + pluginName); (new Thread(new PluginStartTask(jsessionID, pluginName, aimID, 0, projectID))).start(); } } } else { //send all aims at once (new Thread(new PluginStartTask(jsessionID, pluginName, aimIDs, 0, projectID))).start(); } return result; } public static String readPlugInData(EPADAIM aim, String templateName, String jsessionID) throws Exception { String fileName = EPADConfig.getEPADWebServerAnnotationsDir() + "plugins/" + aim.aimID + "_" + templateName + ".json"; File dataFile = new File(fileName); if (!dataFile.exists()) { fileName = EPADConfig.getEPADWebServerResourcesDir() + "plugins/" + aim.aimID + "_" + templateName + ".json"; dataFile = new File(fileName); if (!dataFile.exists()) throw new Exception("Plugin data file does not exist:" + fileName); } String data = EPADFileUtils.readFileAsString(dataFile); return data; } private static void setImageAnnotationUser(ImageAnnotation imageAnnotation, String username) { List<User> userList = new ArrayList<User>(); User user = new User(); user.setLoginName(username); user.setName(username); user.setCagridId(0); userList.add(user); imageAnnotation.setListUser(userList); } private static ImageAnnotationCollection saveImageAnnotationToServer(ImageAnnotation aim, String projectID) throws AimException, edu.stanford.hakan.aim4api.base.AimException { ImageAnnotationCollection aim4 = null; String result = ""; if (aim.getCodeValue() != null) { // First, write a backup file String tempXmlPath = baseAnnotationDir + "temp-" + aim.getUniqueIdentifier() + ".xml"; String storeXmlPath = baseAnnotationDir + aim.getUniqueIdentifier() + ".xml"; File tempFile = new File(tempXmlPath); File storeFile = new File(storeXmlPath); edu.stanford.hakan.aim4api.usage.AnnotationBuilder.saveToFile(aim.toAimV4(), tempXmlPath, xsdFilePathV4); result = edu.stanford.hakan.aim4api.usage.AnnotationBuilder.getAimXMLsaveResult(); log.info("Save AIM file:" + result); if (storeFile.exists()) { storeFile.delete(); } tempFile.renameTo(storeFile); String collectionName = eXistCollectionV4; if (projectID != null && projectID.length() > 0) collectionName = collectionName + "/" + projectID; aim4 = aim.toAimV4(); aim4 = edu.stanford.hakan.aim4api.usage.AnnotationBuilder.saveToServer(aim4, eXistServerUrl, aim4Namespace, collectionName, xsdFilePathV4, eXistUsername, eXistPassword); try { saveAimToMongo(aim4, projectID); } catch (Exception e) { log.warning("Error saving aim to mongodb", e); } log.info("Save AIM to Exist:" + result); } return aim4; } public static Map<String, String> getUIDCsvList(String sessionID, EPADAIMList aimlist, String username) { long starttime = System.currentTimeMillis(); Set<String> projectIDs = aimlist.getProjectIds(); Map<String, String> projectAIMs = new HashMap<String, String>(); String defProjectID = EPADConfig.xnatUploadProjectID; for (String projectID : projectIDs) { try { String csv = ""; boolean isCollaborator = UserProjectService.isCollaborator(sessionID, username, projectID); defProjectID = projectID; log.info("User:" + username + " projectID:" + projectID + " isCollaborator:" + isCollaborator); Set<EPADAIM> aims = aimlist.getAIMsForProject(projectID); for (EPADAIM aim : aims) { if (!isCollaborator || aim.userName.equalsIgnoreCase(username) || aim.userName.equalsIgnoreCase("shared")) csv = csv + "," + aim.aimID; } if (csv.length() != 0) { projectAIMs.put(projectID, csv.substring(1)); } } catch (Exception x) { log.warning("Error checking AIM permission:", x); } } long endtime = System.currentTimeMillis(); log.info("Time taken for checking AIM permissions:" + (endtime - starttime) + " msecs, in:" + aimlist.ResultSet.totalRecords + " ok:" + projectAIMs.values().size() + " username:" + username); if (projectAIMs.keySet().isEmpty()) projectAIMs.put(defProjectID, ""); return projectAIMs; } public static Map<String, List<EPADAIM>> getPermittedAIMs(String sessionID, EPADAIMList aimlist, String username) { long starttime = System.currentTimeMillis(); Set<String> projectIDs = aimlist.getProjectIds(); Map<String, List<EPADAIM>> projectAIMsMap = new HashMap<String, List<EPADAIM>>(); for (String projectID : projectIDs) { try { boolean isCollaborator = UserProjectService.isCollaborator(sessionID, username, projectID); //log.info("User:" + username + " projectID:" + projectID + " isCollaborator:" + isCollaborator); Set<EPADAIM> aims = aimlist.getAIMsForProject(projectID); List<EPADAIM> projectAIMs = projectAIMsMap.get(projectID); if (projectAIMs == null) { projectAIMs = new ArrayList<EPADAIM>(); projectAIMsMap.put(projectID, projectAIMs); } for (EPADAIM aim : aims) { if (!isCollaborator || aim.userName.equalsIgnoreCase(username) || aim.userName.equalsIgnoreCase("shared")) projectAIMs.add(aim); } } catch (Exception x) { log.warning("Error getting aim permissions", x); } } long endtime = System.currentTimeMillis(); log.info("Time taken for checking AIM permissions:" + (endtime - starttime) + " msecs, in:" + aimlist.ResultSet.totalRecords + " out:" + projectAIMsMap.values().size() + " username:" + username); return projectAIMsMap; } public static String getReferencedImage(EPADAIM aim) throws Exception { String xml = aim.xml; if (xml == null) throw new Exception("XML data is null, aim:" + aim.aimID); int uidInd = xml.indexOf("sopInstanceUID"); if (uidInd == -1) uidInd = xml.indexOf("imageReferenceUID"); if (uidInd == -1) return null; int quoteIndex = xml.indexOf('"', uidInd); if (quoteIndex == -1) return null; int secondquote = xml.indexOf('"', quoteIndex); return xml.substring(quoteIndex, secondquote); } // public static int convertAllAim3() throws Exception { // EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); // List<EPADAIM> epadaims = epadDatabaseOperations.getAIMs(new ProjectReference(null)); // return convertAim3(epadaims); // } // // public static void convertAim3(String aimID) throws Exception { // EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); // EPADAIM epadaim = epadDatabaseOperations.getAIM(aimID); // List<EPADAIM> epadaims = new ArrayList<EPADAIM>(); // epadaims.add(epadaim); // convertAim3(epadaims); // } // // public static int convertAim3(List<EPADAIM> epadaims) throws Exception { // EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); // List<Map<String, String>> coordinationTerms = epadDatabaseOperations.getCoordinationData("%"); // //log.info("coordinations:" + coordinationTerms); // int count = 0; // for (EPADAIM epadaim: epadaims) // { // log.info("Converting AIM3:" + epadaim.aimID + " in project " + epadaim.projectID); // try { // List<ImageAnnotation> aims = AIMQueries.getAIMImageAnnotations(epadaim.projectID, AIMSearchType.ANNOTATION_UID, epadaim.aimID, "admin", 1, 50000, true); // if (aims.size() > 0) // { // ImageAnnotation aim = aims.get(0); // String tempXmlPath = baseAnnotationDir + "temp-" + aim.getUniqueIdentifier() + ".xml"; // File tempFile = new File(tempXmlPath); // AnnotationBuilder.saveToFile(aim, tempXmlPath, xsdFilePath); // ImageAnnotationCollection iac = edu.stanford.hakan.aim4api.usage.AnnotationGetter.getImageAnnotationCollectionFromFile(tempXmlPath); // edu.stanford.hakan.aim4api.compability.aimv3.ImageAnnotation iaV3 = new edu.stanford.hakan.aim4api.compability.aimv3.ImageAnnotation(iac); // log.info("Saving AIM4:" + epadaim.aimID + " in project " + epadaim.projectID); // iac = iaV3.toAimV4(coordinationTerms); // iac = AIMUtil.saveImageAnnotationToServer(iac, epadaim.projectID, 0, null, false); // if (iac != null && epadaim.projectID != null) // { // epadDatabaseOperations.updateAIMXml(epadaim.aimID, edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(iac)); // } // tempFile.delete(); // count++; // } // else // log.warning("Error converting aim3:" + epadaim.aimID + ", not found"); // // } // catch (Exception x) { // log.warning("Error converting aim3:" + epadaim.aimID, x); // } // } // return count; // } public static void updateTableXMLs(List<EPADAIM> aims) { long starttime = System.currentTimeMillis(); HashMap<String, String> searchValueByProject = new HashMap<String, String>(); Set<String> aimIDs = new HashSet<String>(); for (EPADAIM aim : aims) { String projectID = aim.projectID; if (projectID == null || projectID.trim().length() == 0) continue; String searchValue = searchValueByProject.get(projectID); if (searchValue == null) searchValue = aim.aimID; else searchValue = searchValue + "," + aim.aimID; searchValueByProject.put(projectID, searchValue); aimIDs.add(aim.aimID); } EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); for (String projectID : searchValueByProject.keySet()) { List<ImageAnnotationCollection> paims = AIMQueries.getAIMImageAnnotationsV4(projectID, AIMSearchType.ANNOTATION_UID, searchValueByProject.get(projectID), "admin"); log.info("" + paims.size() + " AIM4 file(s) found for project:" + projectID); boolean mongoErr = false; for (ImageAnnotationCollection aim : paims) { aimIDs.remove(aim.getUniqueIdentifier().getRoot()); try { EPADAIM epadAim = epadDatabaseOperations.updateAIMXml(aim.getUniqueIdentifier().getRoot(), edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(aim)); } catch (Exception e) { log.warning("Error updating AIM Table XML", e); } try { if (!mongoErr) saveAimToMongo(aim, projectID); } catch (Exception e) { log.warning("Error saving to mongoDB", e); mongoErr = true; } } } // Delete aims that are not found in Exist and have null xml for (String aimID : aimIDs) { EPADAIM aim = epadDatabaseOperations.getAIM(aimID); if (aim.xml == null || aim.xml.length() == 0) log.warning("Annotation " + aimID + " not found in ExistDB"); // epadDatabaseOperations.deleteAIM("admin", aimID); } } public static void updateTableNameColumn(List<EPADAIM> aims) { EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); for (EPADAIM aim : aims) { if (aim.xml == null || aim.xml.trim().length() == 0) continue; try { List<ImageAnnotationCollection> iacs = edu.stanford.hakan.aim4api.usage.AnnotationGetter .getImageAnnotationCollectionsFromString(aim.xml, null); if (iacs.size() == 0) continue; ImageAnnotationCollection iac = iacs.get(0); EPADAIM epadAim = epadDatabaseOperations.updateAIMName(iac.getUniqueIdentifier().getRoot(), iac.getImageAnnotation().getName().getValue()); } catch (Exception e) { log.warning("Error updating AIM Table Name", e); } } } public static void updateTableTemplateColumn(List<EPADAIM> aims) { EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); for (EPADAIM aim : aims) { if (aim.xml == null || aim.xml.trim().length() == 0) continue; try { List<ImageAnnotationCollection> iacs = edu.stanford.hakan.aim4api.usage.AnnotationGetter .getImageAnnotationCollectionsFromString(aim.xml, null); if (iacs.size() == 0) continue; ImageAnnotationCollection iac = iacs.get(0); log.info("aim:" + iac.getUniqueIdentifier().getRoot() + " templatecode:" + iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCode()); EPADAIM epadAim = epadDatabaseOperations.updateAIMTemplateCode(iac.getUniqueIdentifier().getRoot(), iac.getImageAnnotations().get(0).getListTypeCode().get(0).getCode()); } catch (Exception e) { log.warning("Error updating AIM Table TemplateCode", e); } } } public static int updateExistDBFromMysql(String aimID) { EpadDatabaseOperations epadDatabaseOperations = EpadDatabase.getInstance().getEPADDatabaseOperations(); String criteria = "1 = 1"; if (aimID != null && aimID.trim().length() > 0) criteria = "annotationUID like '" + aimID + "'"; List<EPADAIM> aims = epadDatabaseOperations.getAIMsByQuery(criteria); int count = 0; for (EPADAIM aim : aims) { if (aim.xml == null || aim.xml.trim().length() == 0) continue; try { List<ImageAnnotationCollection> iacs = edu.stanford.hakan.aim4api.usage.AnnotationGetter .getImageAnnotationCollectionsFromString(aim.xml, null); if (iacs.size() == 0) continue; ImageAnnotationCollection iac = iacs.get(0); String collectionName = eXistCollectionV4; if (aim.projectID != null && aim.projectID.length() > 0) collectionName = collectionName + "/" + aim.projectID; edu.stanford.hakan.aim4api.usage.AnnotationBuilder.saveToServer(iac, eXistServerUrl, aim4Namespace, collectionName, xsdFilePathV4, eXistUsername, eXistPassword); count++; } catch (Exception e) { log.warning("Error updating Exist Database", e); } } return count; } public static void updateMongDB(List<EPADAIM> aims) { long starttime = System.currentTimeMillis(); boolean mongoErr = false; for (EPADAIM aim : aims) { try { if (!mongoErr) MongoDBOperations.saveAnnotationToMongo(aim.aimID, aim.xml, aim.projectID); } catch (Exception e) { log.warning("Error saving to mongoDB", e); mongoErr = true; } } } public static void saveAimToMongo(ImageAnnotationCollection aim, String collection) throws Exception { String aimXML = null; try { aimXML = edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(aim); } catch (Exception e) { log.warning("Error converting AIM to XML", e); throw e; } MongoDBOperations.saveAnnotationToMongo(aim.getUniqueIdentifier().getRoot(), aimXML, collection); } public static String convertToJson(String xml) { try { JSONObject xmlJSONObj = XML.toJSONObject(xml); String jsonString = xmlJSONObj.toString(0); //log.info("JSON:" + jsonString); return jsonString; // Some other ways to convert to json // HierarchicalStreamReader sourceReader = new XppReader(new StringReader(aimXml)); // StringWriter buffer = new StringWriter(); // //JettisonBadgerFishXmlDriver jettisonDriver = new JettisonBadgerFishXmlDriver(); // JettisonMappedXmlDriver jettisonDriver = new JettisonMappedXmlDriver(); // //jettisonDriver.createWriter(buffer); // HierarchicalStreamWriter destinationWriter = jettisonDriver.createWriter(buffer); // HierarchicalStreamCopier copier = new HierarchicalStreamCopier(); // copier.copy(sourceReader, destinationWriter); // String jsonStr = buffer.toString(); // log.info("JSON:" + jsonStr); // JSONObject jsonObj = new JSONObject(jsonStr); // String xml = XML.toString(jsonObj); // log.info("New XML:" + xml); // JSONObject xmlJSONObj = XML.toJSONObject(aimXml); // String newXml = XML.toString(xmlJSONObj); // java net.sf.saxon.Transform source.xml xml-to-json.xsl use-badgerfish=true() // String[] args = new String[3]; // args[0] = aimFile.getAbsolutePath(); // args[1] = "/home/epad/DicomProxy/etc/xml-to-json.xsl"; // //args[2] = aimFile.getAbsolutePath().replace(".xml", ".json"); // args[2] = "use-badgerfish=true"; // log.info("aim file:" + args[0]); //(new Transform()).doTransform(args, "java net.sf.saxon.Transform"); //log.info("Old xml: " + EPADFileUtils.readFileAsString(aimFile)); //log.info("New Xml: " + EPADFileUtils.readFileAsString(new File(args[1]))); } catch (Exception e) { log.warning("Error converting aim to json", e); return null; } } static final String[] SCHEMA_FILES = { "AIMTemplate_v2rv13.xsd", "AIM_v3.xsd", "AimXPath.xml", "AIMTemplate_v2rvStanford.xsd", "AIM_v4_rv44_XML.xsd", "ISO_datatypes_Narrative.xsd" }; public static void checkSchemaFiles() { for (String schemaFile : SCHEMA_FILES) { File file = new File(EPADConfig.getEPADWebServerSchemaDir() + schemaFile); if (!file.exists()) { InputStream in = null; OutputStream out = null; try { in = new AIMUtil().getClass().getClassLoader().getResourceAsStream("schema/" + schemaFile); out = new FileOutputStream(file); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } } catch (Exception x) { } finally { IOUtils.closeQuietly(in); IOUtils.closeQuietly(out); } } } } static final String[] TEMPLATE_FILES = { "ATS_Template.xml", "Closed_Shape_Only.xml", "Line_Only.xml", "LungMin.xml", "LungNoduleTemplate.xml", "MB_template.xml", "plugin-lesionseg.xml", "plugin-riesz.xml", "plugin-sampleplugin.xml", "plugin-tedseg.xml", "plugin_jjvec.xml", "RECIST.xml", "ROI-Only_Template.xml", "SEG-Only_Template.xml", "Shape_Only.xml", }; public static void checkTemplateFiles() { File dir = new File(EPADConfig.getEPADWebServerTemplatesDir()); if (!dir.exists()) dir.mkdirs(); for (String templateFile : TEMPLATE_FILES) { File file = new File(EPADConfig.getEPADWebServerTemplatesDir() + templateFile); if (!file.exists()) { InputStream in = null; OutputStream out = null; try { in = new AIMUtil().getClass().getClassLoader().getResourceAsStream("templates/" + templateFile); out = new FileOutputStream(file); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } } catch (Exception x) { } finally { IOUtils.closeQuietly(in); IOUtils.closeQuietly(out); } } } } private static int getInt(String value) { try { return new Integer(value.trim()).intValue(); } catch (Exception x) { return 0; } } /****************************AIME Methods**********************************/ public static void queryAIMImageAnnotationsV4AIME(PrintWriter responseStream, AIMSearchType aimSearchType, String searchValue, String user, String sessionID, boolean jsonFormat) throws Exception { List<ImageAnnotationCollection> iacs = null; if (aimSearchType != null) { iacs = AIMQueries.getAIMImageAnnotationsV4AIME(aimSearchType, searchValue, user); log.warning("get with searchtype " + aimSearchType.getName() + " " + searchValue); } else { iacs = AIMQueries.getAIMImageAnnotationsV4AIME(AIMSearchType.ANNOTATION_UID, "all", user); log.warning("get all annotations"); } if (aimSearchType != AIMSearchType.JSON_QUERY) { if (iacs.size() == 0) return; StringBuilder xml = new StringBuilder("<imageAnnotations>\n"); for (ImageAnnotationCollection iac : iacs) { xml.append(iac.getXMLString()); } xml.append("</imageAnnotations>\n"); if (!jsonFormat) { responseStream.print(xml.toString()); } else { responseStream.print(convertToJson(xml.toString())); } } else { log.info("JSON_QUERY not supported by AIME"); } } public static void queryAIMImageAnnotationsV4AIME(PrintWriter responseStream, AIMSearchType aimSearchType, String searchValue, String user) throws ParserConfigurationException, edu.stanford.hakan.aim4api.base.AimException { List<ImageAnnotationCollection> aims = AIMQueries.getAIMImageAnnotationsV4AIME(aimSearchType, searchValue, user); log.info("" + aims.size() + " AIM4 file(s) found for user " + user); if (aims.size() == 0) return; returnImageAnnotationsXMLV4(responseStream, aims); } public static EPADAIMList queryAIMImageAnnotationSummariesV4AIME(String user, String sessionID) throws Exception { return queryAIMImageAnnotationSummariesV4AIME(AIMSearchType.ANNOTATION_UID, "all", user, sessionID); } public static EPADAIMList queryAIMImageAnnotationSummariesV4AIME(AIMSearchType searchType, String searchValue, String user, String sessionID) throws Exception { if (searchType != null) { return queryAIMImageAnnotationSummariesV4AIME(user, sessionID); } long starttime = System.currentTimeMillis(); List<ImageAnnotationCollection> iacs = AIMQueries.getAIMImageAnnotationsV4AIME(searchType, searchValue, user); EPADAIMList aims = new EPADAIMList(); for (ImageAnnotationCollection aim : iacs) { try { Aim4 a = new Aim4(aim); EPADAIM ea = null; try { ea = new EPADAIM(aim.getUniqueIdentifier().getRoot(), a.getLoggedInUser().getLoginName(), "", a.getPatientID(), a.getFirstStudyID(), a.getFirstSeriesID(), a.getFirstImageID(), 0); } catch (Exception x) { log.warning("Error parsing ImageAnnotationCollection:" + aim, x); } if (ea == null) continue; if (aim.getImageAnnotations().get(0).getName() != null) { ea.name = aim.getImageAnnotations().get(0).getName().getValue(); } if (aim.getImageAnnotations().get(0).getListTypeCode() != null && aim.getImageAnnotations().get(0).getListTypeCode().size() > 0) { //ml ea.template = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCode(); ea.templateType = aim.getImageAnnotations().get(0).getListTypeCode().get(0).getCodeSystemName(); } ea.date = aim.getDateTime(); ea.comment = a.getComment(); if (a.getFirstStudyDate() != null) ea.studyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(a.getFirstStudyDate()); ea.patientName = a.getPatientName(); aims.addAIM(ea); } catch (Exception x) { log.warning("Error parsing annotation:" + aim, x); x.printStackTrace(); } } aims.ResultSet.totalRecords = aims.ResultSet.Result.size(); long endtime = System.currentTimeMillis(); log.info("" + aims.ResultSet.totalRecords + " annotation summaries returned to client, took:" + (endtime - starttime)); return aims; } public static void queryAIMImageAnnotationsV4AIME(PrintWriter responseStream, String user, String sessionID) throws ParserConfigurationException, edu.stanford.hakan.aim4api.base.AimException { long starttime = System.currentTimeMillis(); String annotationsXML = queryAIMImageAnnotationsV4AIME(user, sessionID); responseStream.print(annotationsXML); long resptime = System.currentTimeMillis(); log.info("Time to write resp:" + (resptime - starttime) + " msecs"); } public static void queryAIMImageJsonAnnotationsAIME(PrintWriter responseStream, String user, String sessionID) throws Exception { long starttime = System.currentTimeMillis(); String annotationsXML = queryAIMImageAnnotationsV4AIME(user, sessionID); String jsonString = XML.toJSONObject(annotationsXML).toString(0); ; if (jsonString == null) throw new Exception("Error converting to json"); responseStream.print(jsonString); long resptime = System.currentTimeMillis(); log.info("Time to write resp:" + (resptime - starttime) + " msecs"); } public static String queryAIMImageAnnotationsV4AIME(String user, String sessionID) throws ParserConfigurationException, edu.stanford.hakan.aim4api.base.AimException { long starttime = System.currentTimeMillis(); List<ImageAnnotationCollection> iacs = AIMQueries.getAIMImageAnnotationsV4AIME(AIMSearchType.ANNOTATION_UID, "all", user); StringBuilder aimsDBXml = new StringBuilder("<imageAnnotations>\n"); for (ImageAnnotationCollection aim : iacs) { aimsDBXml.append(edu.stanford.hakan.aim4api.usage.AnnotationBuilder.convertToString(aim)); } long xmltime = System.currentTimeMillis(); aimsDBXml.append("</imageAnnotations>\n"); log.info("Time taken create xml:" + (xmltime - starttime) + " msecs for " + (iacs.size()) + " annotations"); return aimsDBXml.toString(); } /****************************AIME Methods***********************************/ }