001/** 002 * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ 003 * 004 * This file is part of Dicoogle/dicoogle. 005 * 006 * Dicoogle/dicoogle is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Dicoogle/dicoogle is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Dicoogle. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package pt.ua.dicoogle.server; 020 021import java.io.File; 022import java.io.IOException; 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027import org.dcm4che2.data.DicomObject; 028import org.dcm4che2.data.Tag; 029import org.dcm4che2.io.DicomInputStream; 030import org.dcm4che2.io.StopTagInputHandler; 031import org.dcm4che2.media.ApplicationProfile; 032import org.dcm4che2.media.BasicApplicationProfile; 033import org.dcm4che2.media.DicomDirReader; 034import org.dcm4che2.media.DicomDirWriter; 035import org.dcm4che2.media.FileSetInformation; 036 037 038 039/** 040 * Creates, updates and rebuilds DICOMDIR Files. 041 * @author Marco 042 */ 043public class DicomDirCreator { 044 045 private String Path; 046 private String id; 047 private DicomDirReader dicomdir; 048 private FileSetInformation fsinfo = null; 049 private ApplicationProfile ap = new BasicApplicationProfile(); 050 051 /** 052 * Creates a new DicomDirCreator object. 053 * If the DICOMDIR file doesn't exist it creates a new one, 054 * otherwise it will open the existing one. 055 * @param P Path to where the DICOMDIR file is going to be created. 056 * @param I FilesetID 057 */ 058 public DicomDirCreator(String P, String I) 059 { 060 Path = P; 061 id = I; 062 File file = new File(Path+File.separator+"DICOMDIR"); 063 if (!file.exists()) 064 { 065 try { 066 fsinfo = new FileSetInformation(); 067 fsinfo.init(); 068 if(id != null) 069 { 070 if(!id.isEmpty()) 071 { 072 fsinfo.setFileSetID(id); 073 } 074 } 075 dicomdir = new DicomDirWriter(file, fsinfo); 076 } catch (IOException ex) { 077 LoggerFactory.getLogger(DicomDirCreator.class).error(ex.getMessage(), ex); 078 } 079 } 080 else 081 { 082 try { 083 dicomdir = new DicomDirWriter(file); 084 fsinfo = dicomdir.getFileSetInformation(); 085 } catch (IOException ex) { 086 LoggerFactory.getLogger(DicomDirCreator.class).error(ex.getMessage(), ex); 087 } 088 } 089 } 090 091 /** 092 * Updates the DICOMDIR file with a new entry 093 * @param f File to be added to DICOMDIR 094 */ 095 public synchronized void updateDicomDir(File f) 096 { 097 // Severe dcm4che bug fix; it had a problem building dicom directories with files / folders beginning with a dot 098 if (f != null && !f.getName().startsWith(".")) 099 { 100 if(f.isDirectory()) 101 { 102 File[] fs = f.listFiles(); 103 104 for (int i = 0; i < fs.length; i++) 105 updateDicomDir(fs[i]); 106 107 return; 108 } 109 110 // Only dcm files will be listed in the dicom directory 111 if (f.getName().endsWith(".dcm")) 112 { 113 DicomInputStream dis = null; 114 try { 115 dis = new DicomInputStream(f); 116 dis.setHandler(new StopTagInputHandler(Tag.PixelData)); 117 DicomObject d = dis.readDicomObject(); 118 DicomObject p_record = ap.makePatientDirectoryRecord(d); 119 DicomObject sty_record = ap.makeStudyDirectoryRecord(d); 120 DicomObject s_record = ap.makeSeriesDirectoryRecord(d); 121 DicomObject i_record = ap.makeInstanceDirectoryRecord(d, dicomdir.toFileID(f)); 122 DicomObject record = ((DicomDirWriter) dicomdir).addPatientRecord(p_record); 123 record = ((DicomDirWriter) dicomdir).addStudyRecord(record, sty_record); 124 record = ((DicomDirWriter) dicomdir).addSeriesRecord(record, s_record); 125 ((DicomDirWriter) dicomdir).addChildRecord(record, i_record); 126 ((DicomDirWriter) dicomdir).commit(); 127 128 } catch (IOException ex) { 129 LoggerFactory.getLogger(DicomDirCreator.class).error(ex.getMessage(), ex); 130 } finally { 131 try { 132 dis.close(); 133 } catch (IOException ex) { 134 LoggerFactory.getLogger(DicomDirCreator.class).error(ex.getMessage(), ex); 135 } 136 } 137 } 138 } 139 } 140 141 /** 142 * Rebuilds the DICOMDIR file, by rescanning the storage path. 143 * To avoid conflicts should only be called when the server is not running. 144 */ 145 public synchronized void dicomdir_rebuild() 146 { 147 try { 148 dicomdir.close(); 149 File file = new File(Path + File.separator + "DICOMDIR"); 150 file.delete(); 151 File f = new File(Path); 152 fsinfo = new FileSetInformation(); 153 fsinfo.init(); 154 if(id != null) 155 { 156 if(!id.isEmpty()) 157 { 158 fsinfo.setFileSetID(id); 159 } 160 } 161 dicomdir = new DicomDirWriter(file, fsinfo); 162 updateDicomDir(f); 163 } catch (IOException ex) { 164 LoggerFactory.getLogger(DicomDirCreator.class).error(ex.getMessage(), ex); 165 } 166 } 167 168 /** 169 * Closes the DICOMDIR Reader/Writer 170 */ 171 public void dicomdir_close() 172 { 173 try { 174 dicomdir.close(); 175 } catch (IOException ex) { 176 LoggerFactory.getLogger(DicomDirCreator.class).error(ex.getMessage(), ex); 177 } 178 } 179 180 181}