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}