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 */ 019/** 020 * 021 * The Goal of this class is based on DicomObject 022 * send FindRSP to destination entity 023 * 024 * It will search data at Index of Lucene 025 * 026 */ 027package pt.ua.dicoogle.server.queryretrieve; 028 029import aclmanager.core.LuceneQueryACLManager; 030import aclmanager.models.Principal; 031 032import java.io.IOException; 033import java.util.ArrayList; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039import org.dcm4che2.data.DicomElement; 040import org.dcm4che2.data.DicomObject; 041import org.dcm4che2.data.Tag; 042import org.dcm4che2.data.VR; 043import org.dcm4che2.net.Association; 044import org.dcm4che2.net.DimseRSP; 045import org.dcm4che2.net.Status; 046 047 048import pt.ua.dicoogle.core.exceptions.CFindNotSupportedException; 049import pt.ua.dicoogle.server.SearchDicomResult; 050 051/** 052 * 053 * @author Luís A. Bastião Silva <bastiao@ua.pt> 054 */ 055public class FindRSP implements DimseRSP 056{ 057 058 private DicomObject rsp; 059 private DicomObject keys; 060 061 062 063 /** 064 * Each moment in timeline we're getting a item 065 */ 066 private DicomObject mwl = null; 067 068 SearchDicomResult search = null ; 069 070 private String callingAET; 071 private LuceneQueryACLManager luke; 072 073 public FindRSP(DicomObject keys, DicomObject rsp, String callingAET, LuceneQueryACLManager luke) 074 { 075 this.rsp = rsp ; 076 this.keys = keys ; 077 078 this.callingAET = callingAET; 079 this.luke = luke; 080 081 082 /** Debug - show keys, rsp, index */ 083 if (keys!=null) 084 { 085 //DebugManager.getInstance().debug("keys object: "); 086 //DebugManager.getInstance().debug(keys.toString()); 087 } 088 if (rsp!=null) 089 { 090 //DebugManager.getInstance().debug("Rsp object"); 091 //DebugManager.getInstance().debug(rsp.toString()); 092 } 093 094 /** 095 * Get object to search 096 */ 097 ArrayList<String> extrafields = null ; 098 extrafields = new ArrayList<String>(); 099 100 extrafields.add("PatientName"); 101 extrafields.add("PatientSex"); 102 extrafields.add("PatientID"); 103 extrafields.add("Modality"); 104 extrafields.add("StudyDate"); 105 extrafields.add("StudyTime"); 106 extrafields.add("AccessionNumber"); 107 extrafields.add("StudyID"); 108 extrafields.add("StudyDescription"); 109 extrafields.add("SeriesNumber"); 110 extrafields.add("SeriesInstanceUID"); 111 extrafields.add("SeriesDescription"); 112 extrafields.add("ReferringPhysicianName"); 113 extrafields.add("PatientBirthDate"); 114 extrafields.add("ModalitiesInStudy"); 115 extrafields.add("StudyInstanceUID"); 116 extrafields.add("InstitutionName"); 117 extrafields.add("AcquisitionDeviceProcessingDescription"); 118 extrafields.add("ProtocolName"); 119 120 extrafields.add("SeriesDate"); 121 122 extrafields.add("OperatorsName"); 123 extrafields.add("RequestingPhysician"); 124 extrafields.add("BodyPartThickness"); 125 extrafields.add("PatientOrientation"); 126 extrafields.add("CompressionForce"); 127 128 extrafields.add("ViewPosition"); 129 extrafields.add("ImageLaterality"); 130 extrafields.add("AcquisitionDeviceProcessingDescription"); 131 132 133 extrafields.add("ViewCodeSequence_CodeValue"); 134 extrafields.add("ViewCodeSequence_CodingSchemeDesignator"); 135 extrafields.add("ViewCodeSequence_CodingSchemeVersion"); 136 extrafields.add("ViewCodeSequence_CodeMeaning"); 137 138 139 extrafields.add("SOPInstanceUID"); 140 141 String query = getQueryString(keys, rsp); 142 //System.out.println("OLD Query: "+query); 143 query = applyQueryFilter(query); 144 145 System.out.println("NEW Query: "+query); 146 147 /** 148 * Search results 149 * TODO: 150 * - Get Search String Query? 151 * - Is A Network Search? 152 * - How works extrafields? 153 */ 154 155 SearchDicomResult.QUERYLEVEL level = null ; 156 /* 157 if (CFindBuilder.isPatientRoot(rsp)) 158 { 159 level = SearchDicomResult.QUERYLEVEL.PATIENT; 160 } 161 else if (CFindBuilder.isStudyRoot(rsp)) 162 { 163 level = SearchDicomResult.QUERYLEVEL.STUDY; 164 }*/ 165 DicomElement elem = keys.get(Integer.parseInt("00080052", 16)); 166 String levelStr = new String(elem.getBytes()); 167 168 if (levelStr.contains("PATIENT")) 169 { 170 level = SearchDicomResult.QUERYLEVEL.PATIENT; 171 } 172 else if(levelStr.contains("STUDY")) 173 { 174 level = SearchDicomResult.QUERYLEVEL.STUDY; 175 } 176 else if (levelStr.contains("SERIES")) 177 { 178 level = SearchDicomResult.QUERYLEVEL.SERIE; 179 } 180 else if (levelStr.contains("IMAGE")) 181 { 182 level = SearchDicomResult.QUERYLEVEL.IMAGE; 183 } 184 System.out.println("Charset: "+ this.keys.get(Tag.SpecificCharacterSet)); 185 search = new SearchDicomResult(query, 186 true, extrafields, level); 187 188 189 190 if (search == null) 191 { 192 //DebugManager.getInstance().debug(">> Search is null, so" + 193 // " somethig is wrong "); 194 } 195 196 // always return Specific Character Set 197 if (!keys.contains(Tag.SpecificCharacterSet)) { 198 this.keys.putNull(Tag.SpecificCharacterSet, VR.CS); 199 keys.putNull(Tag.SpecificCharacterSet, VR.CS); 200 this.rsp.putNull(Tag.SpecificCharacterSet, VR.CS); 201 } 202 203 } 204 205 206 207 208 private String getQueryString(DicomObject keys, DicomObject rsp) 209 { 210 String result = ""; 211 try 212 { 213 CFindBuilder c = new CFindBuilder(keys, rsp); 214 result = c.getQueryString() ; 215 } catch (CFindNotSupportedException ex) 216 { 217 LoggerFactory.getLogger(FindRSP.class).error(ex.getMessage(), ex); 218 } 219 220 return result ; 221 } 222 223 private String applyQueryFilter(String normalQuery){ 224 if(luke == null) 225 return normalQuery; 226 //LuceneQueryACLManager luke = new LuceneQueryACLManager(manager); 227 228 String query = luke.produceQueryFilter(new Principal("AETitle", callingAET)); 229 if(query.length() > 0 ) 230 return normalQuery + query; 231 232 return normalQuery; 233 } 234 235 236 237 /** 238 * 239 * Verify if have a next DicomObject and set 240 * the pointer of DicomObject with correct paraments 241 * It also apply the filter to verify if the DicomObject matches 242 * with query and if it is not search for the next DicomObject. 243 * 244 * @return true if there is a next DicomObject 245 * @throws java.io.IOException 246 * @throws java.lang.InterruptedException 247 */ 248 249 @Override 250 public boolean next() throws IOException, InterruptedException 251 { 252 if (search!=null) 253 { 254 if (search.hasNext()) 255 { 256 //DebugManager.getInstance().debug("We have next, so get it"); 257 mwl = search.next(); 258 //if (mwl.matches(this.keys, true)) 259 //{ 260 261 // always return Specific Character Set 262 if (!this.mwl.contains(Tag.SpecificCharacterSet)) 263 this.mwl.putNull(Tag.SpecificCharacterSet, VR.CS); 264 this.rsp.putInt(Tag.Status, VR.US, mwl.containsAll(keys) ? Status.Pending : Status.PendingWarning); 265 return true; 266 //} 267 } 268 269 /** Sucess */ 270 this.rsp.putInt(Tag.Status, VR.US, Status.Success); 271 /** Clean pointers */ 272 this.mwl = null; 273 this.search = null; 274 return true ; 275 276 } 277 else 278 { 279 this.rsp.putInt(Tag.Status, VR.US, Status.Cancel); 280 } 281 return false; 282 } 283 284 /** 285 * 286 * @return 287 */ 288 @Override 289 public DicomObject getCommand() 290 { 291 return this.rsp; 292 } 293 294 295 /** 296 * This method see the current DicomObject and return it 297 * @return null or DicomObject 298 */ 299 @Override 300 public DicomObject getDataset() 301 { 302 //DebugManager.getInstance().debug("Get Data Set"); 303 return this.mwl != null ? this.mwl.subSet(this.keys) : null; 304 } 305 306 @Override 307 public void cancel(Association arg0) throws IOException 308 { 309 310 search = null ; 311 try 312 { 313 arg0.release(true); 314 315 } catch (InterruptedException ex) 316 { 317 LoggerFactory.getLogger(FindRSP.class).error(ex.getMessage(), ex); 318 } 319 } 320 321 @Override 322 protected void finalize() throws Throwable 323 { 324 325 super.finalize(); 326 327 328 } 329 330} 331