001/* ***** BEGIN LICENSE BLOCK *****
002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003 *
004 * The contents of this file are subject to the Mozilla Public License Version
005 * 1.1 (the "License"); you may not use this file except in compliance with
006 * the License. You may obtain a copy of the License at
007 * http://www.mozilla.org/MPL/
008 *
009 * Software distributed under the License is distributed on an "AS IS" basis,
010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011 * for the specific language governing rights and limitations under the
012 * License.
013 *
014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in
015 * Java(TM), hosted at https://github.com/gunterze/dcm4che.
016 *
017 * The Initial Developer of the Original Code is
018 * Agfa Healthcare.
019 * Portions created by the Initial Developer are Copyright (C) 2011
020 * the Initial Developer. All Rights Reserved.
021 *
022 * Contributor(s):
023 * See @authors listed below
024 *
025 * Alternatively, the contents of this file may be used under the terms of
026 * either the GNU General Public License Version 2 or later (the "GPL"), or
027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
028 * in which case the provisions of the GPL or the LGPL are applicable instead
029 * of those above. If you wish to allow use of your version of this file only
030 * under the terms of either the GPL or the LGPL, and not to allow others to
031 * use your version of this file under the terms of the MPL, indicate your
032 * decision by deleting the provisions above and replace them with the notice
033 * and other provisions required by the GPL or the LGPL. If you do not delete
034 * the provisions above, a recipient may use your version of this file under
035 * the terms of any one of the MPL, the GPL or the LGPL.
036 *
037 * ***** END LICENSE BLOCK ***** */
038package org.dcm4che3.tool.wadouri;
039
040import java.io.File;
041import java.io.IOException;
042import java.io.InputStream;
043import java.net.HttpURLConnection;
044import java.net.URL;
045import java.nio.charset.Charset;
046import java.nio.file.Files;
047import java.nio.file.StandardCopyOption;
048import java.util.ResourceBundle;
049
050import javax.xml.transform.OutputKeys;
051import javax.xml.transform.Templates;
052import javax.xml.transform.TransformerFactory;
053import javax.xml.transform.sax.SAXTransformerFactory;
054import javax.xml.transform.sax.TransformerHandler;
055import javax.xml.transform.stream.StreamResult;
056import javax.xml.transform.stream.StreamSource;
057
058import org.apache.commons.cli.CommandLine;
059import org.apache.commons.cli.OptionBuilder;
060import org.apache.commons.cli.Options;
061import org.apache.commons.cli.ParseException;
062import org.dcm4che3.data.Attributes;
063import org.dcm4che3.io.SAXReader;
064import org.dcm4che3.io.SAXWriter;
065import org.dcm4che3.tool.common.CLIUtils;
066import org.dcm4che3.tool.wadouri.test.WadoURIResponse;
067import org.slf4j.Logger;
068import org.slf4j.LoggerFactory;
069
070/**
071 * @author Hesham Elbadawi <bsdreko@gmail.com>
072 * 
073 */
074
075public class WadoURI{
076    
077    private static final Logger LOG = LoggerFactory.getLogger(WadoURI.class);
078    
079    private static Options options;
080    
081    private static ResourceBundle rb = ResourceBundle
082            .getBundle("org.dcm4che3.tool.wadouri.messages");
083    
084    private SAXTransformerFactory saxTransformer;
085    
086    private Templates xsltTemplates;
087    
088    private File outDir;
089    
090    private File xsltFile;
091    
092    private String outFileName;
093    
094    private String requestTimeOut;
095    
096    private boolean xmlIndent = false;
097    
098    private boolean xmlIncludeKeyword = true;
099    
100    private String url;
101    
102    private String objectID;
103    
104    private String contentType;
105    
106    private String charset;
107    
108    private boolean anonymize;
109    
110    private String annotation;
111    
112    private int rows=Integer.MAX_VALUE;
113    
114    private int columns=Integer.MAX_VALUE;
115    
116    private String regionCoordinates;
117    
118    private String windowParams;
119    
120    private int frameNumber=Integer.MAX_VALUE;
121    
122    private int imageQuality=Integer.MAX_VALUE;
123    
124    private String presentationStateID;
125    
126    private String transferSyntax; 
127    
128    private boolean overlays;
129
130    private WadoURIResponse response;
131    
132    public WadoURI() {}
133
134    public WadoURI(String url, String studyUID, String seriesUID, String objectUID,
135            String contentType, String charset, boolean anonymize,
136            String annotation, int rows, int columns, String regionCoordinates,
137            String windowCenter, String windowWidth, int frameNumber,
138            int imageQuality, String presentationSeriesUID,
139            String presentationUID, String transferSyntax) {
140        setUrl(url);
141        setObjectID(studyUID+":"+seriesUID+":"+objectUID);
142        setContentType(contentType);
143        setCharset(charset);
144        setAnonymize(anonymize);
145        setAnnotation(annotation);
146        setRows(rows);
147        setColumns(columns);
148        setRegionCoordinates(regionCoordinates);
149        setWindowParams(windowCenter+":"+windowWidth);
150        setFrameNumber(frameNumber);
151        setImageQuality(imageQuality);
152        setPresentationStateID(presentationSeriesUID+":"+presentationUID);
153        setTransferSyntax(transferSyntax);
154    }
155
156    private static CommandLine parseComandLine(String[] args)
157            throws ParseException {
158        options = new Options();
159        
160        options.addOption(null, "request-timeout", true, rb.getString("request-timeout"));
161
162        addWadoOptions(options);
163        
164        addOutputOptions(options);
165        
166        CLIUtils.addCommonOptions(options);
167        
168        return CLIUtils.parseComandLine(args,options, rb, WadoURI.class);
169    }
170    
171    @SuppressWarnings("static-access")
172    private static void addWadoOptions(Options opts) {
173           
174        //add objectID;
175            opts.addOption(OptionBuilder.withArgName("studyUID:seriesUID:objectUID")
176                    .withLongOpt("object-id").withDescription(rb.getString("object-id"))
177                    .hasArg(true).create());
178            
179        //add contentType;
180            opts.addOption(OptionBuilder.withArgName("mediaType")
181                    .withLongOpt("content-type").withDescription(rb.getString("content-type"))
182                    .hasArg(true).create());
183            
184        //add charset;
185            opts.addOption(OptionBuilder.withArgName("charset")
186                    .withLongOpt("charset").withDescription(rb.getString("charset"))
187                    .hasArg(true).create());
188            
189           //add anonymize;
190            opts.addOption(OptionBuilder.hasArg(false).withLongOpt("anonymize")
191                    .withDescription(rb.getString("anonymize")).create());
192            
193        //add annotation;
194            opts.addOption(OptionBuilder.withArgName("item")
195                    .withLongOpt("annotation").withDescription(rb.getString("annotation"))
196                    .hasArg(true).create());
197            
198        //add rows;
199            opts.addOption(OptionBuilder.withArgName("numberOfRows")
200                    .withLongOpt("rows").withDescription(rb.getString("rows"))
201                    .hasArg(true).create());
202            
203        //add columns;
204            opts.addOption(OptionBuilder.withArgName("numberOfColumns")
205                    .withLongOpt("columns").withDescription(rb.getString("columns"))
206                    .hasArg(true).create());
207            
208        //add regionCoordinates;
209            opts.addOption(OptionBuilder.withArgName("xLeft,yLeft,xRight,yRight")
210                    .withLongOpt("region").withDescription(rb.getString("region"))
211                    .hasArg(true).create());
212            
213        //add windowParams;
214            opts.addOption(OptionBuilder.withArgName("center:width")
215                    .withLongOpt("window-params").withDescription(rb.getString("window-params"))
216                    .hasArg(true).create());
217            
218        //add frameNumber;
219            opts.addOption(OptionBuilder.withArgName("number")
220                    .withLongOpt("frame-number").withDescription(rb.getString("frame-number"))
221                    .hasArg(true).create());
222            
223        //add imageQuality;
224            opts.addOption(OptionBuilder.withArgName("number")
225                    .withLongOpt("image-quality").withDescription(rb.getString("image-quality"))
226                    .hasArg(true).create());
227            
228        //add presentationStateID;
229            opts.addOption(OptionBuilder.withArgName("SeriesUID:SOPUID")
230                    .withLongOpt("presentation-id").withDescription(rb.getString("presentation-id"))
231                    .hasArg(true).create());
232        //add transferSyntax; 
233            opts.addOption(OptionBuilder.withArgName("tsUID")
234                    .withLongOpt("transfer-syntax").withDescription(rb.getString("transfer-syntax"))
235                    .hasArg(true).create());
236    }
237
238    @SuppressWarnings("static-access")
239    private static void addOutputOptions(Options opts) {
240        opts.addOption(OptionBuilder
241                .withLongOpt("out-dir")
242                .hasArg()
243                .withArgName("directory")
244                .withDescription(rb.getString("out-dir"))
245                .create());
246        opts.addOption(OptionBuilder
247                .withLongOpt("out-file")
248                .hasArg()
249                .withArgName("name")
250                .withDescription(rb.getString("out-file"))
251                .create());
252        opts.addOption(OptionBuilder
253                .withLongOpt("xsl")
254                .hasArg()
255                .withArgName("xsl-file")
256                .withDescription(rb.getString("xsl"))
257                .create("x"));
258        opts.addOption("I", "indent", false, rb.getString("indent"));
259        opts.addOption("K", "no-keyword", false, rb.getString("no-keyword"));
260    }
261
262    public static void main(String[] args) {
263        CommandLine cl = null;
264        try {
265            WadoURI main = new WadoURI();
266            cl = parseComandLine(args);
267            
268            verifyandSetOptions(cl, main);
269
270            String response = null;
271            try {
272               response = sendRequest(main);
273            } catch (Exception e) {
274                System.out.print("Error sending request {}"+e);
275            }
276            
277            System.out.print(response);
278        } catch (ParseException e) {
279            System.out.println("wadouri: " + e.getMessage());
280            System.err.println(rb.getString("try"));
281            System.exit(2);
282        }
283    }
284
285
286    private static void verifyandSetOptions(CommandLine cl, WadoURI main) {
287
288        if (cl.hasOption("out-dir"))
289            main.setOutDir(new File(cl.getOptionValue("out-dir")));
290        else
291            main.setOutDir(new File("./"));
292        
293        if(cl.hasOption("out-file"))
294            main.setOutFileName(cl.getOptionValue("out-file", cl.getOptionValue("out-file")));
295        else
296            main.setOutFileName(cl.getOptionValue("out-file", "wadoResponse"));
297        
298        if (cl.hasOption("x"))
299            main.setXsltFile(new File(cl.getOptionValue("x")));
300        
301        main.setXmlIndent(cl.hasOption("I"));
302        
303        main.setXmlIncludeKeyword(!cl.hasOption("K"));
304
305        
306        if(cl.hasOption("request-timeout"))
307        main.setRequestTimeOut(cl.getOptionValue("request-timout"));
308        
309        if(cl.hasOption("object-id") 
310                && cl.getOptionValue("object-id").matches(".+:.+:.+"))
311            main.setObjectID(cl.getOptionValue("object-id"));
312        else 
313            throw new IllegalArgumentException("wadouri: studyUID, SeriesUID and objectUID "
314                    + "must be present in the request parameters.");
315        
316        if(cl.hasOption("content-type"))
317            main.setContentType(cl.getOptionValue("content-type"));
318        else 
319            main.setContentType("application/dicom");
320        
321        if(cl.hasOption("charset"))
322            main.setCharset(Charset.isSupported(cl.getOptionValue("charset"))?cl.getOptionValue("charset")
323                    :"utf-8");
324        
325        main.setAnonymize(cl.hasOption("anonymize"));
326        
327        if(cl.hasOption("annotation"))
328        main.setAnnotation(cl.getOptionValue("annotation"));
329        
330        if(cl.hasOption("rows"))
331            main.setRows(Integer.valueOf(cl.getOptionValue("rows")));
332        
333        if(cl.hasOption("columns"))
334            main.setColumns(Integer.valueOf(cl.getOptionValue("columns")));
335        
336        if(cl.hasOption("region")) 
337            if( cl.getOptionValue("region").matches(".+:.+:.+:.+") )
338                main.setRegionCoordinates(cl.getOptionValue("region"));
339            else 
340                throw new IllegalArgumentException("wadouri: region Option incorrectly specified");
341        
342        if(cl.hasOption("window-params"))
343            if(cl.getOptionValue("window-params").matches("[0-9]+:[0-9]+"))
344                main.setWindowParams(cl.getOptionValue("window-params"));
345            else
346                throw new IllegalArgumentException("wadouri: window params Option incorrectly specified");
347        
348        if(cl.hasOption("frame-number") 
349                && (main.getContentType() != null 
350                && !main.getContentType().equalsIgnoreCase("application/dicom")))
351            main.setFrameNumber(Integer.valueOf(cl.getOptionValue("frame-number")));
352        
353        if(cl.hasOption("image-quality")
354                && ((main.getContentType() != null 
355                && !main.getContentType().equalsIgnoreCase("application/dicom"))
356                || (main.getTransferSyntax() != null
357                && (main.getTransferSyntax().equalsIgnoreCase("1.2.840.10008.1.2.4.81")
358                        || main.getTransferSyntax().equalsIgnoreCase("1.2.840.10008.1.2.4.51")
359                        || main.getTransferSyntax().equalsIgnoreCase("1.2.840.10008.1.2.4.52")))))
360            main.setImageQuality(Integer.valueOf(cl.getOptionValue("image-quality")));
361            
362        if(cl.hasOption("presentation-id"))
363            if(cl.getOptionValue("presentation-id").matches(".+:.+"))
364                main.setPresentationStateID("pre");
365            else
366                throw new IllegalArgumentException("wadouri: presentation-id Option incorrectly specified");
367        
368        if(cl.hasOption("transfer-syntax"))
369            main.setTransferSyntax(cl.getOptionValue("transfer-syntax"));
370        
371        if(cl.getArgs().length == 0 || cl.getArgs().length > 1)
372            throw new IllegalArgumentException("wadouri: Can not decide URL,"
373                    + " too many or too few arguments specified");
374        else
375            main.setUrl(cl.getArgs()[0]);
376        
377        if(!main.getOutDir().exists())
378            main.getOutDir().mkdirs();
379    }
380
381    private static String addParam(String url, String key, String field) {
382
383        if(url.contains("?"))
384                return url+="&"+key+"="+field;
385        else
386            return url+="?"+key+"="+field;
387        
388    }
389
390    public void wado(WadoURI main) throws Exception {
391        URL newUrl = new URL(setWadoRequestQueryParams(main,main.getUrl()));
392        System.out.println(newUrl.toString());
393        HttpURLConnection connection = (HttpURLConnection) newUrl
394                .openConnection();
395        
396        connection.setDoOutput(true);
397        
398        connection.setDoInput(true);
399        
400        connection.setInstanceFollowRedirects(true);
401        
402        connection.setRequestMethod("GET");
403        
404        if(main.getRequestTimeOut() != null) {
405            connection.setConnectTimeout(Integer.valueOf(main.getRequestTimeOut()));
406            connection.setReadTimeout(Integer.valueOf(main.getRequestTimeOut()));
407        }
408        
409        connection.setUseCaches(false);
410        int rspCode = connection.getResponseCode();
411        String rspMessage = connection.getResponseMessage();
412        InputStream in = connection.getInputStream();
413        
414        String contentType = connection.getHeaderField("Content-Type");
415        String f = null;
416        if(contentType.contains("application")) {
417            if(contentType.contains("application/dicom+xml"))
418                f=writeXML(in, main);
419            else if(contentType.contains("application/pdf"))
420                f=writeFile(in, main, ".pdf");
421            else //dicom 
422                f=writeFile(in, main, ".dcm");
423        }
424        else if(contentType.contains("image")) {
425            if(contentType.contains("image/jpeg"))
426                f=writeFile(in, main, ".jpeg");
427            else if(contentType.contains("image/png"))
428                f=writeFile(in, main, ".png");
429            else //gif
430                f=writeFile(in, main, ".gif");
431        }
432        else if(contentType.contains("text")) {
433            if(contentType.contains("text/html")) {
434                f=writeFile(in, main, ".html");
435            }
436            else if(contentType.contains("text/rtf")) {
437                f=writeFile(in, main, ".rtf");
438            }
439            else if(contentType.contains("text/xml")) {
440                f=writeFile(in, main, ".xml");
441            }
442            else // text/plain
443                f=writeFile(in, main, ".txt");
444        }
445        this.response = new WadoURIResponse(rspCode, rspMessage, f);
446        connection.disconnect();
447    }
448
449    private static String sendRequest(final WadoURI main) throws Exception {
450        URL newUrl = new URL(setWadoRequestQueryParams(main,main.getUrl()));
451        System.out.println(newUrl.toString());
452        HttpURLConnection connection = (HttpURLConnection) newUrl
453                .openConnection();
454        
455        connection.setDoOutput(true);
456        
457        connection.setDoInput(true);
458        
459        connection.setInstanceFollowRedirects(true);
460        
461        connection.setRequestMethod("GET");
462        
463        if(main.getRequestTimeOut() != null) {
464            connection.setConnectTimeout(Integer.valueOf(main.getRequestTimeOut()));
465            connection.setReadTimeout(Integer.valueOf(main.getRequestTimeOut()));
466        }
467        
468        connection.setUseCaches(false);
469        String response = "Server responded with "
470                +connection.getResponseCode() + " - " 
471                +connection.getResponseMessage();
472        InputStream in = connection.getInputStream();
473        
474        String contentType = connection.getHeaderField("Content-Type");
475        
476        if(contentType.contains("application")) {
477            if(contentType.contains("application/dicom+xml"))
478                writeXML(in, main);
479            else if(contentType.contains("application/pdf"))
480                writeFile(in, main, ".pdf");
481            else //dicom 
482                writeFile(in, main, ".dcm");
483        }
484        else if(contentType.contains("image")) {
485            if(contentType.contains("image/jpeg"))
486                writeFile(in, main, ".jpeg");
487            else if(contentType.contains("image/png"))
488                writeFile(in, main, ".png");
489            else //gif
490                writeFile(in, main, ".gif");
491        }
492        else if(contentType.contains("text")) {
493            if(contentType.contains("text/html")) {
494                writeFile(in, main, ".html");
495            }
496            else if(contentType.contains("text/rtf")) {
497                writeFile(in, main, ".rtf");
498            }
499            else // text/plain
500                writeFile(in, main, ".txt");
501        }
502        connection.disconnect();
503
504        return response;
505
506    }
507    private static TransformerHandler getTransformerHandler(WadoURI main) throws Exception {
508        
509        SAXTransformerFactory stf = main.saxTransformer;
510        
511        if (stf == null)
512            main.saxTransformer = stf = (SAXTransformerFactory) TransformerFactory
513                .newInstance();
514        
515        if (main.getXsltFile() == null)
516            return stf.newTransformerHandler();
517
518        Templates templates = main.xsltTemplates;
519        
520        if (templates == null){
521            templates = stf.newTemplates(new StreamSource(main.xsltFile));
522            main.xsltTemplates = templates;
523        }
524        
525        return stf.newTransformerHandler(templates);
526    }
527    
528    private static String writeXML(InputStream in, WadoURI main) throws Exception {
529        
530        File file = new File(main.getOutDir(), main.getOutFileName()+".xml");
531        TransformerHandler th = getTransformerHandler(main);
532        th.getTransformer().setOutputProperty(OutputKeys.INDENT,
533                main.xmlIndent ? "yes" : "no");
534        th.setResult(new StreamResult(file));
535        Attributes attrs= SAXReader.parse(in);
536        SAXWriter saxWriter = new SAXWriter(th);
537        saxWriter.setIncludeKeyword(main.xmlIncludeKeyword); 
538        saxWriter.write(attrs);
539        return file.getAbsolutePath();
540    }
541
542    private static String writeFile(InputStream in, WadoURI main, String extension) {
543        File file = new File(main.getOutDir(), main.getOutFileName()+extension);
544        try {
545            Files.copy(in,file
546            .toPath(),StandardCopyOption.REPLACE_EXISTING);
547        } catch (IOException e) {
548            System.out.println("wadouri: Error writing results to file "+ e.getMessage());
549        }
550        return file.getAbsolutePath();
551    }
552
553
554    private static String setWadoRequestQueryParams(WadoURI main,String url) {
555        
556        url = addParam(url, "requestType", "WADO");
557        String[] objectID = main.getObjectID().split(":");
558        url = addParam(url, "studyUID",objectID[0]);
559        url = addParam(url, "seriesUID",objectID[1]);
560        url = addParam(url, "objectUID",objectID[2]);
561        
562        if(main.getContentType() != null)
563            url = addParam(url, "contentType", main.getContentType());
564        
565        if(main.getCharset() != null)
566            url = addParam(url, "charset", main.getCharset());
567        
568        if(main.anonymize)
569            url = addParam(url, "anonymize", "yes");
570        
571        if(main.getAnnotation() != null)
572            url = addParam(url, "annotation", main.getAnnotation());
573        
574        if(main.getRows() != Integer.MAX_VALUE)
575            url = addParam(url, "rows", Integer.toString(main.getRows()));
576        
577        if(main.getColumns() != Integer.MAX_VALUE)
578            url = addParam(url, "columns", Integer.toString(main.getColumns()));
579        
580        if(main.getRegionCoordinates() != null)
581            url = addParam(url, "region", main.getRegionCoordinates());
582        
583        if(main.getWindowParams() != null) {
584            String[] windowParams = main.getWindowParams().split(":");
585            url = addParam(url, "windowCenter", windowParams[0]);
586            url = addParam(url, "windowWidth", windowParams[1]);
587        }
588        
589        if(main.getFrameNumber() != Integer.MAX_VALUE)
590            url = addParam(url, "frameNumber", Integer.toString(main.getFrameNumber()));
591        
592        if(main.getImageQuality() != Integer.MAX_VALUE)
593            url = addParam(url, "imageQuality", Integer.toString(main.getImageQuality()));
594        
595        if(main.getPresentationStateID() != null) {
596            String[] presentationUID = main.getPresentationStateID().split(":");
597            url = addParam(url, "presentationSeriesUID", presentationUID[0]);
598            url = addParam(url, "presentationUID", presentationUID[1]);
599        }
600        
601        if(main.getContentType().matches("application/dicom")
602                && main.getTransferSyntax() != null)
603            url = addParam(url, "transferSyntax", main.getTransferSyntax());
604        
605        url = addParam(url, "overlays", main.isOverlays()? "true": "false");
606        
607        return url;
608    }
609
610
611    public File getOutDir() {
612        return outDir;
613    }
614
615    public void setOutDir(File outDir) {
616        outDir.mkdirs();
617        this.outDir = outDir;
618    }
619
620    public File getXsltFile() {
621        return xsltFile;
622    }
623
624    public void setXsltFile(File xsltFile) {
625        this.xsltFile = xsltFile;
626    }
627
628    public String getOutFileName() {
629        return outFileName;
630    }
631
632    public void setOutFileName(String outFileName) {
633        this.outFileName = outFileName;
634    }
635
636    public String getRequestTimeOut() {
637        return requestTimeOut;
638    }
639
640    public void setRequestTimeOut(String requestTimeOut) {
641        this.requestTimeOut = requestTimeOut;
642    }
643
644    public boolean isXmlIndent() {
645        return xmlIndent;
646    }
647
648    public void setXmlIndent(boolean xmlIndent) {
649        this.xmlIndent = xmlIndent;
650    }
651
652    public boolean isXmlIncludeKeyword() {
653        return xmlIncludeKeyword;
654    }
655
656    public void setXmlIncludeKeyword(boolean xmlIncludeKeyword) {
657        this.xmlIncludeKeyword = xmlIncludeKeyword;
658    }
659
660    
661    public String getUrl() {
662        return url;
663    }
664
665    public void setUrl(String url) {
666        this.url = url;
667    }
668
669
670    public String getObjectID() {
671        return objectID;
672    }
673
674
675    public void setObjectID(String objectID) {
676        this.objectID = objectID;
677    }
678
679
680    public String getContentType() {
681        return contentType;
682    }
683
684
685    public void setContentType(String contentType) {
686        this.contentType = contentType;
687    }
688
689
690    public String getCharset() {
691        return charset;
692    }
693
694
695    public void setCharset(String charset) {
696        this.charset = charset;
697    }
698
699
700    public boolean isAnonymize() {
701        return anonymize;
702    }
703
704
705    public void setAnonymize(boolean anonymize) {
706        this.anonymize = anonymize;
707    }
708
709
710    public String getAnnotation() {
711        return annotation;
712    }
713
714
715    public void setAnnotation(String annotation) {
716        if(!annotation.contains("NULL"))
717        this.annotation = annotation;
718    }
719
720
721    public int getRows() {
722        return rows;
723    }
724
725
726    public void setRows(int rows) {
727        if(rows > 0)
728        this.rows = rows;
729    }
730
731
732    public int getColumns() {
733        return columns;
734    }
735
736
737    public void setColumns(int columns) {
738        if(columns > 0)
739        this.columns = columns;
740    }
741
742
743    public String getRegionCoordinates() {
744        return regionCoordinates;
745    }
746
747
748    public void setRegionCoordinates(String regionCoordinates) {
749        if(!regionCoordinates.contains("NULL"))
750        this.regionCoordinates = regionCoordinates;
751    }
752
753
754    public String getWindowParams() {
755        return windowParams;
756    }
757
758
759    public void setWindowParams(String windowParams) {
760        if(!windowParams.contains("NULL"))
761        this.windowParams = windowParams;
762    }
763
764
765    public int getFrameNumber() {
766        return frameNumber;
767    }
768
769
770    public void setFrameNumber(int frameNumber) {
771        if(frameNumber > 0)
772        this.frameNumber = frameNumber;
773    }
774
775
776    public int getImageQuality() {
777        return imageQuality;
778    }
779
780
781    public void setImageQuality(int imageQuality) {
782        if(imageQuality > 0)
783        this.imageQuality = imageQuality;
784    }
785
786
787    public String getPresentationStateID() {
788        return presentationStateID;
789    }
790
791
792    public void setPresentationStateID(String presentationStateID) {
793        if(!presentationStateID.contains("NULL"))
794        this.presentationStateID = presentationStateID;
795    }
796
797
798    public String getTransferSyntax() {
799        return transferSyntax;
800    }
801
802
803    public void setTransferSyntax(String transferSyntax) {
804        if(!transferSyntax.contains("NULL"))
805        this.transferSyntax = transferSyntax;
806    }
807
808    public boolean isOverlays() {
809        return overlays;
810    }
811
812    public void setOverlays(boolean overlays) {
813        this.overlays = overlays;
814    }
815
816    public WadoURIResponse getResponse() {
817        return response;
818    }
819
820}