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 ***** */ 038 039package org.dcm4che3.tool.common; 040 041import java.io.File; 042import java.io.IOException; 043import java.io.InputStream; 044import java.security.GeneralSecurityException; 045import java.text.MessageFormat; 046import java.util.Properties; 047import java.util.ResourceBundle; 048 049import org.apache.commons.cli.CommandLine; 050import org.apache.commons.cli.CommandLineParser; 051import org.apache.commons.cli.HelpFormatter; 052import org.apache.commons.cli.MissingOptionException; 053import org.apache.commons.cli.OptionBuilder; 054import org.apache.commons.cli.OptionGroup; 055import org.apache.commons.cli.Options; 056import org.apache.commons.cli.ParseException; 057import org.apache.commons.cli.PosixParser; 058import org.dcm4che3.data.Tag; 059import org.dcm4che3.data.UID; 060import org.dcm4che3.data.Attributes; 061import org.dcm4che3.data.ElementDictionary; 062import org.dcm4che3.data.Sequence; 063import org.dcm4che3.data.VR; 064import org.dcm4che3.io.DicomEncodingOptions; 065import org.dcm4che3.net.ApplicationEntity; 066import org.dcm4che3.net.Connection; 067import org.dcm4che3.net.Device; 068import org.dcm4che3.net.Priority; 069import org.dcm4che3.net.SSLManagerFactory; 070import org.dcm4che3.net.pdu.AAssociateRQ; 071import org.dcm4che3.net.pdu.UserIdentityRQ; 072import org.dcm4che3.util.SafeClose; 073import org.dcm4che3.util.StreamUtils; 074import org.dcm4che3.util.StringUtils; 075 076/** 077 * @author Gunter Zeilinger <gunterze@gmail.com> 078 * 079 */ 080public class CLIUtils { 081 082 public static ResourceBundle rb = 083 ResourceBundle.getBundle("org.dcm4che3.tool.common.messages"); 084 085 public static void addCommonOptions(Options opts) { 086 opts.addOption("h", "help", false, rb.getString("help")); 087 opts.addOption("V", "version", false, rb.getString("version")); 088 } 089 090 @SuppressWarnings("static-access") 091 public static void addBindOption(Options opts, String defAET) { 092 opts.addOption(OptionBuilder 093 .hasArg() 094 .withArgName("aet[@ip][:port]") 095 .withDescription( 096 MessageFormat.format(rb.getString("bind"), defAET)) 097 .withLongOpt("bind") 098 .create("b")); 099 } 100 101 @SuppressWarnings("static-access") 102 public static void addBindServerOption(Options opts) { 103 opts.addOption(OptionBuilder 104 .hasArg() 105 .withArgName("[aet[@ip]:]port") 106 .withDescription(rb.getString("bind-server")) 107 .withLongOpt("bind") 108 .create("b")); 109 addRequestTimeoutOption(opts); 110 } 111 112 @SuppressWarnings("static-access") 113 public static void addConnectOption(Options opts) { 114 opts.addOption(OptionBuilder 115 .hasArg() 116 .withArgName("aet@host:port") 117 .withDescription(rb.getString("connect")) 118 .withLongOpt("connect") 119 .create("c")); 120 opts.addOption(OptionBuilder 121 .hasArg() 122 .withArgName("[user:password@]host:port") 123 .withDescription(rb.getString("proxy")) 124 .withLongOpt("proxy") 125 .create(null)); 126 opts.addOption(OptionBuilder 127 .hasArg() 128 .withArgName("name") 129 .withDescription(rb.getString("user")) 130 .withLongOpt("user") 131 .create(null)); 132 opts.addOption(OptionBuilder 133 .hasArg() 134 .withArgName("password") 135 .withDescription(rb.getString("user-pass")) 136 .withLongOpt("user-pass") 137 .create(null)); 138 opts.addOption(null, "user-rsp", false, rb.getString("user-rsp")); 139 addConnectTimeoutOption(opts); 140 addAcceptTimeoutOption(opts); 141 } 142 143 @SuppressWarnings("static-access") 144 public static void addAEOptions(Options opts) { 145 opts.addOption(OptionBuilder 146 .hasArg() 147 .withArgName("length") 148 .withDescription(rb.getString("max-pdulen-rcv")) 149 .withLongOpt("max-pdulen-rcv") 150 .create(null)); 151 opts.addOption(OptionBuilder 152 .hasArg() 153 .withArgName("length") 154 .withDescription(rb.getString("max-pdulen-snd")) 155 .withLongOpt("max-pdulen-snd") 156 .create(null)); 157 opts.addOption(OptionBuilder 158 .hasArg() 159 .withArgName("no") 160 .withDescription(rb.getString("max-ops-invoked")) 161 .withLongOpt("max-ops-invoked") 162 .create(null)); 163 opts.addOption(OptionBuilder 164 .hasArg() 165 .withArgName("no") 166 .withDescription(rb.getString("max-ops-performed")) 167 .withLongOpt("max-ops-performed") 168 .create(null)); 169 opts.addOption(null, "not-async", false, rb.getString("not-async")); 170 opts.addOption(null, "not-pack-pdv", false, rb.getString("not-pack-pdv")); 171 opts.addOption(OptionBuilder 172 .hasArg() 173 .withArgName("ms") 174 .withDescription(rb.getString("idle-timeout")) 175 .withLongOpt("idle-timeout") 176 .create(null)); 177 opts.addOption(OptionBuilder 178 .hasArg() 179 .withArgName("ms") 180 .withDescription(rb.getString("release-timeout")) 181 .withLongOpt("release-timeout") 182 .create(null)); 183 opts.addOption(OptionBuilder 184 .hasArg() 185 .withArgName("ms") 186 .withDescription(rb.getString("soclose-delay")) 187 .withLongOpt("soclose-delay") 188 .create(null)); 189 addSocketOptions(opts); 190 addTLSOptions(opts); 191 } 192 193 @SuppressWarnings("static-access") 194 public static void addRequestTimeoutOption(Options opts) { 195 opts.addOption(OptionBuilder 196 .hasArg() 197 .withArgName("ms") 198 .withDescription(rb.getString("request-timeout")) 199 .withLongOpt("request-timeout") 200 .create(null)); 201 } 202 203 @SuppressWarnings("static-access") 204 public static void addAcceptTimeoutOption(Options opts) { 205 opts.addOption(OptionBuilder 206 .hasArg() 207 .withArgName("ms") 208 .withDescription(rb.getString("accept-timeout")) 209 .withLongOpt("accept-timeout") 210 .create(null)); 211 } 212 213 @SuppressWarnings("static-access") 214 public static void addSocketOptions(Options opts) { 215 opts.addOption(OptionBuilder 216 .hasArg() 217 .withArgName("length") 218 .withDescription(rb.getString("sosnd-buffer")) 219 .withLongOpt("sosnd-buffer") 220 .create(null)); 221 opts.addOption(OptionBuilder 222 .hasArg() 223 .withArgName("length") 224 .withDescription(rb.getString("sorcv-buffer")) 225 .withLongOpt("sorcv-buffer") 226 .create(null)); 227 opts.addOption(null, "tcp-delay", false, rb.getString("tcp-delay")); 228 } 229 230 @SuppressWarnings("static-access") 231 public static void addConnectTimeoutOption(Options opts) { 232 opts.addOption(OptionBuilder 233 .hasArg() 234 .withArgName("ms") 235 .withDescription(rb.getString("connect-timeout")) 236 .withLongOpt("connect-timeout") 237 .create(null)); 238 } 239 240 @SuppressWarnings("static-access") 241 public static void addResponseTimeoutOption(Options opts) { 242 opts.addOption(OptionBuilder 243 .hasArg() 244 .withArgName("ms") 245 .withDescription(rb.getString("response-timeout")) 246 .withLongOpt("response-timeout") 247 .create(null)); 248 } 249 250 @SuppressWarnings("static-access") 251 public static void addRetrieveTimeoutOption(Options opts) { 252 opts.addOption(OptionBuilder 253 .hasArg() 254 .withArgName("ms") 255 .withDescription(rb.getString("retrieve-timeout")) 256 .withLongOpt("retrieve-timeout") 257 .create(null)); 258 } 259 260 @SuppressWarnings("static-access") 261 public static void addTLSOptions(Options opts) { 262 opts.addOption(OptionBuilder 263 .hasArg() 264 .withArgName("cipher") 265 .withDescription(rb.getString("tls-cipher")) 266 .withLongOpt("tls-cipher") 267 .create(null)); 268 opts.addOption(null, "tls", false, rb.getString("tls")); 269 opts.addOption(null, "tls-null", false, rb.getString("tls-null")); 270 opts.addOption(null, "tls-3des", false, rb.getString("tls-3des")); 271 opts.addOption(null, "tls-aes", false, rb.getString("tls-aes")); 272 opts.addOption(OptionBuilder 273 .hasArg() 274 .withArgName("protocol") 275 .withDescription(rb.getString("tls-protocol")) 276 .withLongOpt("tls-protocol") 277 .create(null)); 278 opts.addOption(null, "tls1", false, rb.getString("tls1")); 279 opts.addOption(null, "tls11", false, rb.getString("tls11")); 280 opts.addOption(null, "tls12", false, rb.getString("tls12")); 281 opts.addOption(null, "ssl3", false, rb.getString("ssl3")); 282 opts.addOption(null, "ssl2Hello", false, rb.getString("ssl2Hello")); 283 opts.addOption(null, "tls-noauth", false, rb.getString("tls-noauth")); 284 opts.addOption(OptionBuilder 285 .hasArg() 286 .withArgName("file|url") 287 .withDescription(rb.getString("key-store")) 288 .withLongOpt("key-store") 289 .create(null)); 290 opts.addOption(OptionBuilder 291 .hasArg() 292 .withArgName("storetype") 293 .withDescription(rb.getString("key-store-type")) 294 .withLongOpt("key-store-type") 295 .create(null)); 296 opts.addOption(OptionBuilder 297 .hasArg() 298 .withArgName("password") 299 .withDescription(rb.getString("key-store-pass")) 300 .withLongOpt("key-store-pass") 301 .create(null)); 302 opts.addOption(OptionBuilder 303 .hasArg() 304 .withArgName("password") 305 .withDescription(rb.getString("key-pass")) 306 .withLongOpt("key-pass") 307 .create(null)); 308 opts.addOption(OptionBuilder 309 .hasArg() 310 .withArgName("file|url") 311 .withDescription(rb.getString("trust-store")) 312 .withLongOpt("trust-store") 313 .create(null)); 314 opts.addOption(OptionBuilder 315 .hasArg() 316 .withArgName("storetype") 317 .withDescription(rb.getString("trust-store-type")) 318 .withLongOpt("trust-store-type") 319 .create(null)); 320 opts.addOption(OptionBuilder 321 .hasArg() 322 .withArgName("password") 323 .withDescription(rb.getString("trust-store-pass")) 324 .withLongOpt("trust-store-pass") 325 .create(null)); 326 } 327 328 @SuppressWarnings("static-access") 329 public static void addPriorityOption(Options opts) { 330 OptionGroup group = new OptionGroup(); 331 group.addOption(OptionBuilder 332 .withLongOpt("prior-high") 333 .withDescription(rb.getString("prior-high")) 334 .create()); 335 group.addOption(OptionBuilder 336 .withLongOpt("prior-low") 337 .withDescription(rb.getString("prior-low")) 338 .create()); 339 opts.addOptionGroup(group); 340 } 341 342 public static CommandLine parseComandLine(String[] args, Options opts, 343 ResourceBundle rb2, Class<?> clazz) throws ParseException { 344 CommandLineParser parser = new PosixParser(); 345 CommandLine cl = parser.parse(opts, args); 346 if (cl.hasOption("h")) { 347 HelpFormatter formatter = new HelpFormatter(); 348 formatter.printHelp( 349 rb2.getString("usage"), 350 rb2.getString("description"), opts, 351 rb2.getString("example")); 352 System.exit(0); 353 } 354 if (cl.hasOption("V")) { 355 Package p = clazz.getPackage(); 356 String s = p.getName(); 357 System.out.println(s.substring(s.lastIndexOf('.')+1) + ": " + 358 p.getImplementationVersion()); 359 System.exit(0); 360 } 361 return cl; 362 } 363 364 public static void configureConnect(Connection conn, 365 AAssociateRQ rq, CommandLine cl) throws ParseException { 366 if (!cl.hasOption("c")) 367 throw new MissingOptionException( 368 rb.getString("missing-connect-opt")); 369 String aeAtHostPort = cl.getOptionValue("c"); 370 String[] aeHostPort = split(aeAtHostPort , '@', 0); 371 if (aeHostPort[1] == null) 372 throw new ParseException(rb.getString("invalid-connect-opt")); 373 374 String[] hostPort = split(aeHostPort[1], ':', 0); 375 if (hostPort[1] == null) 376 throw new ParseException(rb.getString("invalid-connect-opt")); 377 378 rq.setCalledAET(aeHostPort[0]); 379 conn.setHostname(hostPort[0]); 380 conn.setPort(Integer.parseInt(hostPort[1])); 381 382 conn.setHttpProxy(cl.getOptionValue("proxy")); 383 384 if (cl.hasOption("user")) 385 rq.setUserIdentityRQ(cl.hasOption("user-pass") 386 ? new UserIdentityRQ(cl.getOptionValue("user"), 387 cl.getOptionValue("user-pass").toCharArray()) 388 : new UserIdentityRQ(cl.getOptionValue("user"), 389 cl.hasOption("user-rsp"))); 390 } 391 392 public static void configureBind(Connection conn, 393 ApplicationEntity ae, CommandLine cl) throws ParseException { 394 if (cl.hasOption("b")) { 395 String aeAtHostPort = cl.getOptionValue("b"); 396 String[] aeAtHostAndPort = split(aeAtHostPort, ':', 0); 397 String[] aeHost = split(aeAtHostAndPort[0], '@', 0); 398 ae.setAETitle(aeHost[0]); 399 if (aeHost[1] != null) 400 conn.setHostname(aeHost[1]); 401 if (aeAtHostAndPort[1] != null) 402 conn.setPort(Integer.parseInt(aeAtHostAndPort[1])); 403 } 404 } 405 406 public static void configureBindServer(Connection conn, 407 ApplicationEntity ae, CommandLine cl) throws ParseException { 408 if (!cl.hasOption("b")) 409 throw new MissingOptionException(rb.getString("missing-bind-opt")); 410 String aeAtHostPort = cl.getOptionValue("b"); 411 String[] aeAtHostAndPort = split(aeAtHostPort, ':', 1); 412 conn.setPort(Integer.parseInt(aeAtHostAndPort[1])); 413 if (aeAtHostAndPort[0] != null) { 414 String[] aeHost = split(aeAtHostAndPort[0], '@', 0); 415 ae.setAETitle(aeHost[0]); 416 if (aeHost[1] != null) 417 conn.setHostname(aeHost[1]); 418 } 419 } 420 421 private static String[] split(String s, char delim, int defPos) { 422 String[] s2 = new String[2]; 423 int pos = s.indexOf(delim); 424 if (pos != -1) { 425 s2[0] = s.substring(0, pos); 426 s2[1] = s.substring(pos + 1); 427 } else { 428 s2[defPos] = s; 429 } 430 return s2; 431 } 432 433 public static int priorityOf(CommandLine cl) { 434 return cl.hasOption("prior-high") 435 ? Priority.HIGH 436 : cl.hasOption("prior-low") 437 ? Priority.LOW 438 : Priority.NORMAL; 439 } 440 441 public static int getIntOption(CommandLine cl, String opt, int defVal) { 442 String optVal = cl.getOptionValue(opt); 443 if (optVal == null) 444 return defVal; 445 446 return optVal.endsWith("H") 447 ? Integer.parseInt(optVal.substring(0, optVal.length() - 1), 16) 448 : Integer.parseInt(optVal); 449 } 450 451 public static void configure(Connection conn, CommandLine cl) 452 throws ParseException, IOException { 453 conn.setReceivePDULength( 454 getIntOption(cl, "max-pdulen-rcv", Connection.DEF_MAX_PDU_LENGTH)); 455 conn.setSendPDULength( 456 getIntOption(cl, "max-pdulen-snd", Connection.DEF_MAX_PDU_LENGTH)); 457 if(cl.hasOption("not-async")) { 458 conn.setMaxOpsInvoked(1); 459 conn.setMaxOpsPerformed(1); 460 } else { 461 conn.setMaxOpsInvoked(getIntOption(cl, "max-ops-invoked", 0)); 462 conn.setMaxOpsPerformed(getIntOption(cl, "max-ops-performed", 0)); 463 } 464 conn.setPackPDV(!cl.hasOption("not-pack-pdv")); 465 conn.setConnectTimeout(getIntOption(cl, "connect-timeout", 0)); 466 conn.setRequestTimeout(getIntOption(cl, "request-timeout", 0)); 467 conn.setAcceptTimeout(getIntOption(cl, "accept-timeout", 0)); 468 conn.setReleaseTimeout(getIntOption(cl, "release-timeout", 0)); 469 conn.setResponseTimeout(getIntOption(cl, "response-timeout", 0)); 470 conn.setRetrieveTimeout(getIntOption(cl, "retrieve-timeout", 0)); 471 conn.setIdleTimeout(getIntOption(cl, "idle-timeout", 0)); 472 conn.setSocketCloseDelay(getIntOption(cl, "soclose-delay", 473 Connection.DEF_SOCKETDELAY)); 474 conn.setSendBufferSize(getIntOption(cl, "sosnd-buffer", 0)); 475 conn.setReceiveBufferSize(getIntOption(cl, "sorcv-buffer", 0)); 476 conn.setTcpNoDelay(!cl.hasOption("tcp-delay")); 477 configureTLS(conn, cl); 478 } 479 480 private static void configureTLS(Connection conn, CommandLine cl) 481 throws ParseException, IOException { 482 if (cl.hasOption("tls")) 483 conn.setTlsCipherSuites( 484 "SSL_RSA_WITH_NULL_SHA", 485 "TLS_RSA_WITH_AES_128_CBC_SHA", 486 "SSL_RSA_WITH_3DES_EDE_CBC_SHA"); 487 else if (cl.hasOption("tls-null")) 488 conn.setTlsCipherSuites("SSL_RSA_WITH_NULL_SHA"); 489 else if (cl.hasOption("tls-3des")) 490 conn.setTlsCipherSuites("SSL_RSA_WITH_3DES_EDE_CBC_SHA"); 491 else if (cl.hasOption("tls-aes")) 492 conn.setTlsCipherSuites( 493 "TLS_RSA_WITH_AES_128_CBC_SHA", 494 "SSL_RSA_WITH_3DES_EDE_CBC_SHA"); 495 else if (cl.hasOption("tls-cipher")) 496 conn.setTlsCipherSuites(cl.getOptionValues("tls-cipher")); 497 else 498 return; 499 500 if (cl.hasOption("tls12")) 501 conn.setTlsProtocols("TLSv1.2"); 502 else if (cl.hasOption("tls11")) 503 conn.setTlsProtocols("TLSv1.1"); 504 else if (cl.hasOption("tls1")) 505 conn.setTlsProtocols("TLSv1"); 506 else if (cl.hasOption("ssl3")) 507 conn.setTlsProtocols("SSLv3"); 508 else if (cl.hasOption("ssl2Hello")) 509 conn.setTlsProtocols("SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"); 510 else if (cl.hasOption("tls-protocol")) 511 conn.setTlsProtocols(cl.getOptionValues("tls-protocol")); 512 513 conn.setTlsNeedClientAuth(!cl.hasOption("tls-noauth")); 514 515 String keyStoreURL = cl.getOptionValue("key-store", "resource:key.jks"); 516 String keyStoreType = cl.getOptionValue("key-store-type", "JKS"); 517 String keyStorePass = cl.getOptionValue("key-store-pass", "secret"); 518 String keyPass = cl.getOptionValue("key-pass", keyStorePass); 519 String trustStoreURL = cl.getOptionValue("trust-store", "resource:cacerts.jks"); 520 String trustStoreType = cl.getOptionValue("trust-store-type", "JKS"); 521 String trustStorePass = cl.getOptionValue("trust-store-pass", "secret"); 522 523 Device device = conn.getDevice(); 524 try { 525 device.setKeyManager(SSLManagerFactory.createKeyManager( 526 keyStoreType, keyStoreURL, keyStorePass, keyPass)); 527 device.setTrustManager(SSLManagerFactory.createTrustManager( 528 trustStoreType, trustStoreURL, trustStorePass)); 529 } catch (GeneralSecurityException e) { 530 throw new IOException(e); 531 } 532 } 533 534 public static Properties loadProperties(String url, Properties p) 535 throws IOException { 536 if (p == null) 537 p = new Properties(); 538 InputStream in = StreamUtils.openFileOrURL(url); 539 try { 540 p.load(in); 541 } finally { 542 SafeClose.close(in); 543 } 544 return p; 545 } 546 547 @SuppressWarnings("static-access") 548 public static void addEncodingOptions(Options opts) { 549 opts.addOption(null, "group-len", false, rb.getString("group-len")); 550 OptionGroup sqlenGroup = new OptionGroup(); 551 sqlenGroup.addOption(OptionBuilder 552 .withLongOpt("expl-seq-len") 553 .withDescription(rb.getString("expl-seq-len")) 554 .create(null)); 555 sqlenGroup.addOption(OptionBuilder 556 .withLongOpt("undef-seq-len") 557 .withDescription(rb.getString("undef-seq-len")) 558 .create(null)); 559 opts.addOptionGroup(sqlenGroup); 560 OptionGroup itemlenGroup = new OptionGroup(); 561 itemlenGroup.addOption(OptionBuilder 562 .withLongOpt("expl-item-len") 563 .withDescription(rb.getString("expl-item-len")) 564 .create(null)); 565 itemlenGroup.addOption(OptionBuilder 566 .withLongOpt("undef-item-len") 567 .withDescription(rb.getString("undef-item-len")) 568 .create(null)); 569 opts.addOptionGroup(itemlenGroup); 570 } 571 572 public static DicomEncodingOptions encodingOptionsOf(CommandLine cl) 573 throws ParseException { 574 if (cl.hasOption("expl-item-len") && cl.hasOption("undef-item-len") 575 || cl.hasOption("expl-seq-len") && cl.hasOption("undef-seq-len")) 576 throw new ParseException( 577 rb.getString("conflicting-enc-opts")); 578 return new DicomEncodingOptions( 579 cl.hasOption("group-len"), 580 !cl.hasOption("expl-seq-len"), 581 cl.hasOption("undef-seq-len"), 582 !cl.hasOption("expl-item-len"), 583 cl.hasOption("undef-item-len")); 584 } 585 586 public static int[] toTags(String[] tagOrKeywords) { 587 int[] tags = new int[tagOrKeywords.length]; 588 for (int i = 0; i < tags.length; i++) 589 tags[i] = toTag(tagOrKeywords[i]); 590 return tags; 591 } 592 593 public static int toTag(String tagOrKeyword) { 594 try { 595 return Integer.parseInt(tagOrKeyword, 16); 596 } catch (IllegalArgumentException e) { 597 int tag = ElementDictionary.tagForKeyword(tagOrKeyword, null); 598 if (tag == -1) 599 throw new IllegalArgumentException(tagOrKeyword); 600 return tag; 601 } 602 } 603 604 @SuppressWarnings("static-access") 605 public static void addFilesetInfoOptions(Options opts) { 606 opts.addOption(OptionBuilder 607 .withLongOpt("fs-desc") 608 .hasArg() 609 .withArgName("txtfile") 610 .withDescription(rb.getString("fs-desc")) 611 .create()); 612 opts.addOption(OptionBuilder 613 .withLongOpt("fs-desc-cs") 614 .hasArg() 615 .withArgName("code") 616 .withDescription(rb.getString("fs-desc-cs")) 617 .create()); 618 opts.addOption(OptionBuilder 619 .withLongOpt("fs-id") 620 .hasArg() 621 .withArgName("id") 622 .withDescription(rb.getString("fs-id")) 623 .create()); 624 opts.addOption(OptionBuilder 625 .withLongOpt("fs-uid") 626 .hasArg() 627 .withArgName("uid") 628 .withDescription(rb.getString("fs-uid")) 629 .create()); 630 } 631 632 public static void configure(FilesetInfo fsInfo, CommandLine cl) { 633 fsInfo.setFilesetUID(cl.getOptionValue("fs-uid")); 634 fsInfo.setFilesetID(cl.getOptionValue("fs-id")); 635 if (cl.hasOption("fs-desc")) 636 fsInfo.setDescriptorFile(new File(cl.getOptionValue("fs-desc"))); 637 fsInfo.setDescriptorFileCharset(cl.getOptionValue("fs-desc-cs")); 638 } 639 640 @SuppressWarnings("static-access") 641 public static void addTransferSyntaxOptions(Options opts) { 642 OptionGroup group = new OptionGroup(); 643 group.addOption(OptionBuilder 644 .withLongOpt("explicit-vr") 645 .withDescription(rb.getString("explicit-vr")) 646 .create()); 647 group.addOption(OptionBuilder 648 .withLongOpt("big-endian") 649 .withDescription(rb.getString("big-endian")) 650 .create()); 651 group.addOption(OptionBuilder 652 .withLongOpt("implicit-vr") 653 .withDescription(rb.getString("implicit-vr")) 654 .create()); 655 opts.addOptionGroup(group); 656 } 657 658 private static String[] IVR_LE_FIRST = { 659 UID.ImplicitVRLittleEndian, 660 UID.ExplicitVRLittleEndian, 661 UID.ExplicitVRBigEndianRetired 662 }; 663 664 private static String[] EVR_LE_FIRST = { 665 UID.ExplicitVRLittleEndian, 666 UID.ExplicitVRBigEndianRetired, 667 UID.ImplicitVRLittleEndian 668 }; 669 670 private static String[] EVR_BE_FIRST = { 671 UID.ExplicitVRBigEndianRetired, 672 UID.ExplicitVRLittleEndian, 673 UID.ImplicitVRLittleEndian 674 }; 675 676 private static String[] IVR_LE_ONLY = { 677 UID.ImplicitVRLittleEndian 678 }; 679 680 public static String[] transferSyntaxesOf(CommandLine cl) { 681 if (cl.hasOption("explicit-vr")) 682 return EVR_LE_FIRST; 683 if (cl.hasOption("big-endian")) 684 return EVR_BE_FIRST; 685 if (cl.hasOption("implicit-vr")) 686 return IVR_LE_ONLY; 687 return IVR_LE_FIRST; 688 } 689 690 public static void addAttributes(Attributes attrs, int[] tags, String... ss) { 691 Attributes item = attrs; 692 for (int i = 0; i < tags.length-1; i++) { 693 int tag = tags[i]; 694 Sequence sq = item.getSequence(tag); 695 if (sq == null) 696 sq = item.newSequence(tag, 1); 697 if (sq.isEmpty()) 698 sq.add(new Attributes()); 699 item = sq.get(0); 700 } 701 int tag = tags[tags.length-1]; 702 VR vr = ElementDictionary.vrOf(tag, 703 item.getPrivateCreator(tag)); 704 if (ss.length == 0) 705 if (vr == VR.SQ) 706 item.newSequence(tag, 1).add(new Attributes(0)); 707 else 708 item.setNull(tag, vr); 709 else 710 item.setString(tag, vr, ss); 711 } 712 713 public static void addAttributes(Attributes attrs, String[] optVals) { 714 if (optVals != null) 715 for (int i = 1; i < optVals.length; i++, i++) 716 addAttributes(attrs, 717 toTags( 718 StringUtils.split(optVals[i-1], '/')), 719 StringUtils.split(optVals[i], '/')); 720 } 721 722 public static void addEmptyAttributes(Attributes attrs, String[] optVals) { 723 if (optVals != null) 724 for (int i = 0; i < optVals.length; i++) 725 addAttributes(attrs, 726 toTags(StringUtils.split(optVals[i], '/'))); 727 } 728 729 public static boolean updateAttributes(Attributes data, Attributes attrs, 730 String uidSuffix) { 731 if (attrs.isEmpty() && uidSuffix == null) 732 return false; 733 if (uidSuffix != null ) { 734 data.setString(Tag.StudyInstanceUID, VR.UI, 735 data.getString(Tag.StudyInstanceUID) + uidSuffix); 736 data.setString(Tag.SeriesInstanceUID, VR.UI, 737 data.getString(Tag.SeriesInstanceUID) + uidSuffix); 738 data.setString(Tag.SOPInstanceUID, VR.UI, 739 data.getString(Tag.SOPInstanceUID) + uidSuffix); 740 } 741 data.update(attrs, null); 742 return true; 743 } 744 745 public static String[] toUIDs(String s) { 746 if (s.equals("*")) 747 return new String[] { "*" }; 748 749 String[] uids = StringUtils.split(s, ','); 750 for (int i = 0; i < uids.length; i++) 751 uids[i] = toUID(uids[i]); 752 return uids ; 753 } 754 755 public static String toUID(String uid) { 756 uid = uid.trim(); 757 return (uid.equals("*") || Character.isDigit(uid.charAt(0))) 758 ? uid 759 : UID.forName(uid); 760 } 761}