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.web.rest; 020 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026import java.util.concurrent.ExecutionException; 027 028import net.sf.json.JSONObject; 029 030import org.apache.commons.lang3.StringUtils; 031import org.restlet.data.Form; 032import org.restlet.data.MediaType; 033import org.restlet.data.Status; 034import org.restlet.representation.EmptyRepresentation; 035import org.restlet.representation.Representation; 036import org.restlet.representation.StringRepresentation; 037import org.restlet.resource.Get; 038import org.restlet.resource.ServerResource; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042import pt.ua.dicoogle.core.QueryExpressionBuilder; 043import pt.ua.dicoogle.core.dim.DIMGeneric; 044import pt.ua.dicoogle.plugins.PluginController; 045import pt.ua.dicoogle.sdk.utils.DictionaryAccess; 046import pt.ua.dicoogle.sdk.datastructs.SearchResult; 047import pt.ua.dicoogle.sdk.task.JointQueryTask; 048import pt.ua.dicoogle.sdk.task.Task; 049 050/** 051 * 052 * @author fmvalente 053 */ 054 055 056//TODO:add type to file search 057public class RestDimResource extends ServerResource{ 058 059 private static final Logger log = LoggerFactory.getLogger(RestDimResource.class); 060 061 @Get 062 public Representation represent(){ 063 064 Form queryForm = getRequest().getResourceRef().getQueryAsForm(); 065 066 String search = queryForm.getValues("q"); 067 String advSearch = queryForm.getValues("advq"); 068 069 if(StringUtils.isNotEmpty(search)){ 070 QueryExpressionBuilder q = new QueryExpressionBuilder(search); 071 search = q.getQueryString(); 072 }else if (StringUtils.isNotEmpty(advSearch)) { 073 search = advSearch; 074 }else{ 075 //SEND ERROR NO QUERY DEFINED 076 setStatus(new Status(401), "No Query String Provided: Please provide a query either by ?advq, for advanced searches, or ?q for free text"); 077 return new EmptyRepresentation(); 078 } 079 080 String type = queryForm.getValues("type"); 081 boolean dim = true; 082 if(StringUtils.isNotEmpty(type)){ 083 if(type.equalsIgnoreCase("DIM")){ 084 dim = true; 085 }else if (type.equalsIgnoreCase("RAW")) { 086 dim = false; 087 }else{ 088 //SEND ERROR!! WRONG RETURN TYPE 089 setStatus(new Status(402), "Wrong return type: Supported types, dim (default), raw."); 090 091 return new EmptyRepresentation(); 092 } 093 } 094 095 List<String> knownProviders = new ArrayList<String>(); 096 String[] providers = queryForm.getValuesArray("provider"); 097 List<String> activeProviders = PluginController.getInstance().getQueryProvidersName(true); 098 boolean queryAll = providers.length == 0; 099 for(String p : providers){ 100 if(p.equalsIgnoreCase("all")){ 101 queryAll = true; 102 break; 103 }else if(activeProviders.contains(p)){ 104 knownProviders.add(p); 105 } 106 } 107 activeProviders = null; 108 109 String[] extraFieldList = queryForm.getValuesArray("field"); 110 HashMap<String, String> extraFields = new HashMap<String, String>(); 111 //attaches the required extrafields 112 if(extraFieldList.length == 0 || dim){ 113 extraFields.put("PatientName", "PatientName"); 114 extraFields.put("PatientID", "PatientID"); 115 extraFields.put("Modality", "Modality"); 116 extraFields.put("StudyDate", "StudyDate"); 117 extraFields.put("SeriesInstanceUID", "SeriesInstanceUID"); 118 extraFields.put("StudyID", "StudyID"); 119 extraFields.put("StudyInstanceUID", "StudyInstanceUID"); 120 extraFields.put("Thumbnail", "Thumbnail"); 121 extraFields.put("SOPInstanceUID", "SOPInstanceUID"); 122 }else{ 123 Map<String, String> availableTags = new HashMap<String, String>(); 124 for(String tag : DictionaryAccess.getInstance().getTagList().keySet()){ 125 availableTags.put(tag.toLowerCase(), tag); 126 } 127 for(String f : extraFieldList){ 128 if(f.equalsIgnoreCase("all")){ 129 for(String k : availableTags.values()){ 130 extraFields.put(k, k); 131 } 132 break; 133 } 134 if(availableTags.containsKey(f)){ 135 extraFields.put(availableTags.get(f), availableTags.get(f)); 136 } 137 } 138 } 139 140 //System.err.println("ADVSEARCH: "+advSearch); 141 //System.err.println("FINAL SEARCH QUERY: "+search); 142 143 long startTime = System.currentTimeMillis(); 144 MyHolder holder = new MyHolder(); 145 if(queryAll) 146 PluginController.getInstance().queryAll(holder, search, extraFields); 147 else 148 PluginController.getInstance().query(holder, knownProviders, search, extraFields); 149 150 ArrayList<SearchResult> resultsArr = new ArrayList<SearchResult>(); 151 152 try { 153 Iterable<SearchResult> results = holder.get(); 154 155 for(SearchResult r : results) 156 resultsArr.add(r); 157 158 results = null; 159 160 } catch (InterruptedException | ExecutionException e) { 161 // TODO Auto-generated catch block 162 e.printStackTrace(); 163 } 164 startTime = System.currentTimeMillis() - startTime; 165 166 String ret = ""; 167 MediaType mtype = null; 168 if(dim){ 169 ret = processDIMResults(resultsArr); 170 mtype = MediaType.APPLICATION_XML; 171 }else{ 172 ret = processJSON(resultsArr, startTime); 173 mtype = MediaType.APPLICATION_JSON; 174 } 175 176 if(StringUtils.isEmpty(ret) && !resultsArr.isEmpty()){ 177 //RAISE ERROR 178 setStatus(new Status(400), "Error parsing results data:"); 179 return new EmptyRepresentation(); 180 } 181 182 //constructs our xml data struct 183 return new StringRepresentation(ret, mtype); 184 } 185 186 private static String processDIMResults(Collection<SearchResult> results){ 187 DIMGeneric dim = null; 188 try{ 189 dim = new DIMGeneric(results); 190 return dim.getXML(); 191 } 192 catch (Exception ex) { 193// LoggerFactory.getLogger(RestDimResource.class).error(ex.getMessage(), ex); 194 ex.printStackTrace(); 195 } 196 //and returns an xml version of our dim search 197 return null; 198 199 } 200 201 private static String processJSON(Collection<SearchResult> results, long elapsedTime){ 202 JSONObject resp = new JSONObject(); 203 for(SearchResult r : results){ 204 JSONObject rj = new JSONObject(); 205 rj.put("uri", r.getURI().toString()); 206 207 JSONObject fields = new JSONObject(); 208 fields.accumulateAll(r.getExtraData()); 209 210 rj.put("fields", fields); 211 212 resp.accumulate("results", rj); 213 } 214 resp.put("numResults", results.size()); 215 resp.put("elapsedTime", elapsedTime); 216 217 return resp.toString(); 218 } 219 220 private static class MyHolder extends JointQueryTask{ 221 222 @Override 223 public void onCompletion() { 224 // TODO Auto-generated method stub 225 226 } 227 228 @Override 229 public void onReceive(Task<Iterable<SearchResult>> e) { 230 // TODO Auto-generated method stub 231 232 } 233 234 } 235}