001package org.unix4j.unix.sed; 002 003import java.util.List; 004import java.util.Map; 005import java.util.Arrays; 006 007import org.unix4j.command.Arguments; 008import org.unix4j.context.ExecutionContext; 009import org.unix4j.convert.ValueConverter; 010import org.unix4j.option.DefaultOptionSet; 011import org.unix4j.util.ArgsUtil; 012import org.unix4j.util.ArrayUtil; 013import org.unix4j.variable.Arg; 014import org.unix4j.variable.VariableContext; 015 016import org.unix4j.unix.Sed; 017 018/** 019 * Arguments and options for the {@link Sed sed} command. 020 */ 021public final class SedArguments implements Arguments<SedArguments> { 022 023 private final SedOptions options; 024 025 026 // operand: <script> 027 private String script; 028 private boolean scriptIsSet = false; 029 030 // operand: <regexp> 031 private String regexp; 032 private boolean regexpIsSet = false; 033 034 // operand: <string1> 035 private String string1; 036 private boolean string1IsSet = false; 037 038 // operand: <replacement> 039 private String replacement; 040 private boolean replacementIsSet = false; 041 042 // operand: <string2> 043 private String string2; 044 private boolean string2IsSet = false; 045 046 // operand: <occurrence> 047 private int[] occurrence; 048 private boolean occurrenceIsSet = false; 049 050 // operand: <args> 051 private String[] args; 052 private boolean argsIsSet = false; 053 054 /** 055 * Constructor to use if no options are specified. 056 */ 057 public SedArguments() { 058 this.options = SedOptions.EMPTY; 059 } 060 061 /** 062 * Constructor with option set containing the selected command options. 063 * 064 * @param options the selected options 065 * @throws NullPointerException if the argument is null 066 */ 067 public SedArguments(SedOptions options) { 068 if (options == null) { 069 throw new NullPointerException("options argument cannot be null"); 070 } 071 this.options = options; 072 } 073 074 /** 075 * Returns the options set containing the selected command options. Returns 076 * an empty options set if no option has been selected. 077 * 078 * @return set with the selected options 079 */ 080 public SedOptions getOptions() { 081 return options; 082 } 083 084 /** 085 * Constructor string arguments encoding options and arguments, possibly 086 * also containing variable expressions. 087 * 088 * @param args string arguments for the command 089 * @throws NullPointerException if args is null 090 */ 091 public SedArguments(String... args) { 092 this(); 093 this.args = args; 094 this.argsIsSet = true; 095 } 096 private Object[] resolveVariables(VariableContext context, String... unresolved) { 097 final Object[] resolved = new Object[unresolved.length]; 098 for (int i = 0; i < resolved.length; i++) { 099 final String expression = unresolved[i]; 100 if (Arg.isVariable(expression)) { 101 resolved[i] = resolveVariable(context, expression); 102 } else { 103 resolved[i] = expression; 104 } 105 } 106 return resolved; 107 } 108 private <V> V convertList(ExecutionContext context, String operandName, Class<V> operandType, List<Object> values) { 109 if (values.size() == 1) { 110 final Object value = values.get(0); 111 return convert(context, operandName, operandType, value); 112 } 113 return convert(context, operandName, operandType, values); 114 } 115 116 private Object resolveVariable(VariableContext context, String variable) { 117 final Object value = context.getValue(variable); 118 if (value != null) { 119 return value; 120 } 121 throw new IllegalArgumentException("cannot resolve variable " + variable + 122 " in command: sed " + this); 123 } 124 private <V> V convert(ExecutionContext context, String operandName, Class<V> operandType, Object value) { 125 final ValueConverter<V> converter = context.getValueConverterFor(operandType); 126 final V convertedValue; 127 if (converter != null) { 128 convertedValue = converter.convert(value); 129 } else { 130 if (SedOptions.class.equals(operandType)) { 131 convertedValue = operandType.cast(SedOptions.CONVERTER.convert(value)); 132 } else { 133 convertedValue = null; 134 } 135 } 136 if (convertedValue != null) { 137 return convertedValue; 138 } 139 throw new IllegalArgumentException("cannot convert --" + operandName + 140 " value '" + value + "' into the type " + operandType.getName() + 141 " for sed command"); 142 } 143 144 @Override 145 public SedArguments getForContext(ExecutionContext context) { 146 if (context == null) { 147 throw new NullPointerException("context cannot be null"); 148 } 149 if (!argsIsSet || args.length == 0) { 150 //nothing to resolve 151 return this; 152 } 153 154 //check if there is at least one variable 155 boolean hasVariable = false; 156 for (final String arg : args) { 157 if (arg != null && arg.startsWith("$")) { 158 hasVariable = true; 159 break; 160 } 161 } 162 //resolve variables 163 final Object[] resolvedArgs = hasVariable ? resolveVariables(context.getVariableContext(), this.args) : this.args; 164 165 //convert now 166 final List<String> defaultOperands = Arrays.asList("script"); 167 final Map<String, List<Object>> map = ArgsUtil.parseArgs("options", defaultOperands, resolvedArgs); 168 final SedOptions.Default options = new SedOptions.Default(); 169 final SedArguments argsForContext = new SedArguments(options); 170 for (final Map.Entry<String, List<Object>> e : map.entrySet()) { 171 if ("script".equals(e.getKey())) { 172 173 final String value = convertList(context, "script", String.class, e.getValue()); 174 argsForContext.setScript(value); 175 } else if ("regexp".equals(e.getKey())) { 176 177 final String value = convertList(context, "regexp", String.class, e.getValue()); 178 argsForContext.setRegexp(value); 179 } else if ("string1".equals(e.getKey())) { 180 181 final String value = convertList(context, "string1", String.class, e.getValue()); 182 argsForContext.setString1(value); 183 } else if ("replacement".equals(e.getKey())) { 184 185 final String value = convertList(context, "replacement", String.class, e.getValue()); 186 argsForContext.setReplacement(value); 187 } else if ("string2".equals(e.getKey())) { 188 189 final String value = convertList(context, "string2", String.class, e.getValue()); 190 argsForContext.setString2(value); 191 } else if ("occurrence".equals(e.getKey())) { 192 193 final int[] value = convertList(context, "occurrence", int[].class, e.getValue()); 194 argsForContext.setOccurrence(value); 195 } else if ("args".equals(e.getKey())) { 196 throw new IllegalStateException("invalid operand '" + e.getKey() + "' in sed command args: " + Arrays.toString(args)); 197 } else if ("options".equals(e.getKey())) { 198 199 final SedOptions value = convertList(context, "options", SedOptions.class, e.getValue()); 200 options.setAll(value); 201 } else { 202 throw new IllegalStateException("invalid operand '" + e.getKey() + "' in sed command args: " + Arrays.toString(args)); 203 } 204 } 205 return argsForContext; 206 } 207 208 /** 209 * Returns the {@code <script>} operand value (variables are NOT resolved): Sed script as one string, such as "s/original/replacement/g". 210 * 211 * @return the {@code <script>} operand value (variables are not resolved) 212 * @throws IllegalStateException if this operand has never been set 213 * @see #getScript(ExecutionContext) 214 */ 215 public String getScript() { 216 if (scriptIsSet) { 217 return script; 218 } 219 throw new IllegalStateException("operand has not been set: " + script); 220 } 221 /** 222 * Returns the {@code <script>} (variables are resolved): Sed script as one string, such as "s/original/replacement/g". 223 * 224 * @param context the execution context used to resolve variables 225 * @return the {@code <script>} operand value after resolving variables 226 * @throws IllegalStateException if this operand has never been set 227 * @see #getScript() 228 */ 229 public String getScript(ExecutionContext context) { 230 final String value = getScript(); 231 if (Arg.isVariable(value)) { 232 final Object resolved = resolveVariable(context.getVariableContext(), value); 233 final String converted = convert(context, "script", String.class, resolved); 234 return converted; 235 } 236 return value; 237 } 238 239 /** 240 * Returns true if the {@code <script>} operand has been set. 241 * <p> 242 * Note that this method returns true even if {@code null} was passed to the 243 * {@link #setScript(String)} method. 244 * 245 * @return true if the setter for the {@code <script>} operand has 246 * been called at least once 247 */ 248 public boolean isScriptSet() { 249 return scriptIsSet; 250 } 251 /** 252 * Sets {@code <script>}: Sed script as one string, such as "s/original/replacement/g". 253 * 254 * @param script the value for the {@code <script>} operand 255 */ 256 public void setScript(String script) { 257 this.script = script; 258 this.scriptIsSet = true; 259 } 260 /** 261 * Returns the {@code <regexp>} operand value (variables are NOT resolved): Regular expression matched against a line. 262 * 263 * @return the {@code <regexp>} operand value (variables are not resolved) 264 * @throws IllegalStateException if this operand has never been set 265 * @see #getRegexp(ExecutionContext) 266 */ 267 public String getRegexp() { 268 if (regexpIsSet) { 269 return regexp; 270 } 271 throw new IllegalStateException("operand has not been set: " + regexp); 272 } 273 /** 274 * Returns the {@code <regexp>} (variables are resolved): Regular expression matched against a line. 275 * 276 * @param context the execution context used to resolve variables 277 * @return the {@code <regexp>} operand value after resolving variables 278 * @throws IllegalStateException if this operand has never been set 279 * @see #getRegexp() 280 */ 281 public String getRegexp(ExecutionContext context) { 282 final String value = getRegexp(); 283 if (Arg.isVariable(value)) { 284 final Object resolved = resolveVariable(context.getVariableContext(), value); 285 final String converted = convert(context, "regexp", String.class, resolved); 286 return converted; 287 } 288 return value; 289 } 290 291 /** 292 * Returns true if the {@code <regexp>} operand has been set. 293 * <p> 294 * Note that this method returns true even if {@code null} was passed to the 295 * {@link #setRegexp(String)} method. 296 * 297 * @return true if the setter for the {@code <regexp>} operand has 298 * been called at least once 299 */ 300 public boolean isRegexpSet() { 301 return regexpIsSet; 302 } 303 /** 304 * Sets {@code <regexp>}: Regular expression matched against a line. 305 * 306 * @param regexp the value for the {@code <regexp>} operand 307 */ 308 public void setRegexp(String regexp) { 309 this.regexp = regexp; 310 this.regexpIsSet = true; 311 } 312 /** 313 * Returns the {@code <string1>} operand value (variables are NOT resolved): Regular expression matched against a line for all commands except 314 for command y where string1 contains the source characters for the 315 translation. 316 * 317 * @return the {@code <string1>} operand value (variables are not resolved) 318 * @throws IllegalStateException if this operand has never been set 319 * @see #getString1(ExecutionContext) 320 */ 321 public String getString1() { 322 if (string1IsSet) { 323 return string1; 324 } 325 throw new IllegalStateException("operand has not been set: " + string1); 326 } 327 /** 328 * Returns the {@code <string1>} (variables are resolved): Regular expression matched against a line for all commands except 329 for command y where string1 contains the source characters for the 330 translation. 331 * 332 * @param context the execution context used to resolve variables 333 * @return the {@code <string1>} operand value after resolving variables 334 * @throws IllegalStateException if this operand has never been set 335 * @see #getString1() 336 */ 337 public String getString1(ExecutionContext context) { 338 final String value = getString1(); 339 if (Arg.isVariable(value)) { 340 final Object resolved = resolveVariable(context.getVariableContext(), value); 341 final String converted = convert(context, "string1", String.class, resolved); 342 return converted; 343 } 344 return value; 345 } 346 347 /** 348 * Returns true if the {@code <string1>} operand has been set. 349 * <p> 350 * Note that this method returns true even if {@code null} was passed to the 351 * {@link #setString1(String)} method. 352 * 353 * @return true if the setter for the {@code <string1>} operand has 354 * been called at least once 355 */ 356 public boolean isString1Set() { 357 return string1IsSet; 358 } 359 /** 360 * Sets {@code <string1>}: Regular expression matched against a line for all commands except 361 for command y where string1 contains the source characters for the 362 translation. 363 * 364 * @param string1 the value for the {@code <string1>} operand 365 */ 366 public void setString1(String string1) { 367 this.string1 = string1; 368 this.string1IsSet = true; 369 } 370 /** 371 * Returns the {@code <replacement>} operand value (variables are NOT resolved): Replacement string for substitute command. An ampersand ('&') 372 appearing in the replacement string is replaced by the string 373 matching the regular expression. The characters "\n", where n is a 374 digit, are replaced by the text matched by the corresponding 375 backreference expression. The special meaning of '&' and "\n" in 376 this context can be suppressed by preceding it by a backslash. 377 * 378 * @return the {@code <replacement>} operand value (variables are not resolved) 379 * @throws IllegalStateException if this operand has never been set 380 * @see #getReplacement(ExecutionContext) 381 */ 382 public String getReplacement() { 383 if (replacementIsSet) { 384 return replacement; 385 } 386 throw new IllegalStateException("operand has not been set: " + replacement); 387 } 388 /** 389 * Returns the {@code <replacement>} (variables are resolved): Replacement string for substitute command. An ampersand ('&') 390 appearing in the replacement string is replaced by the string 391 matching the regular expression. The characters "\n", where n is a 392 digit, are replaced by the text matched by the corresponding 393 backreference expression. The special meaning of '&' and "\n" in 394 this context can be suppressed by preceding it by a backslash. 395 * 396 * @param context the execution context used to resolve variables 397 * @return the {@code <replacement>} operand value after resolving variables 398 * @throws IllegalStateException if this operand has never been set 399 * @see #getReplacement() 400 */ 401 public String getReplacement(ExecutionContext context) { 402 final String value = getReplacement(); 403 if (Arg.isVariable(value)) { 404 final Object resolved = resolveVariable(context.getVariableContext(), value); 405 final String converted = convert(context, "replacement", String.class, resolved); 406 return converted; 407 } 408 return value; 409 } 410 411 /** 412 * Returns true if the {@code <replacement>} operand has been set. 413 * <p> 414 * Note that this method returns true even if {@code null} was passed to the 415 * {@link #setReplacement(String)} method. 416 * 417 * @return true if the setter for the {@code <replacement>} operand has 418 * been called at least once 419 */ 420 public boolean isReplacementSet() { 421 return replacementIsSet; 422 } 423 /** 424 * Sets {@code <replacement>}: Replacement string for substitute command. An ampersand ('&') 425 appearing in the replacement string is replaced by the string 426 matching the regular expression. The characters "\n", where n is a 427 digit, are replaced by the text matched by the corresponding 428 backreference expression. The special meaning of '&' and "\n" in 429 this context can be suppressed by preceding it by a backslash. 430 * 431 * @param replacement the value for the {@code <replacement>} operand 432 */ 433 public void setReplacement(String replacement) { 434 this.replacement = replacement; 435 this.replacementIsSet = true; 436 } 437 /** 438 * Returns the {@code <string2>} operand value (variables are NOT resolved): Replacement string for substitute command s; appended, inserted or 439 changed text for a, i and c command; destination characters for 440 translate command y; ignored by all other commands. 441 <p> 442 If string2 is a replacement string for the substitute command: an 443 ampersand ('&') appearing in the replacement string is replaced 444 by the string matching the regular expression; the characters "\n", 445 where n is a digit, are replaced by the text matched by the 446 corresponding backreference expression. The special meaning of 447 '&' and "\n" in this context can be suppressed by preceding it 448 by a backslash. 449<p> 450 (This operand only applies to the commands s, a, i, c and y and is 451 ignored by all other commands). 452 * 453 * @return the {@code <string2>} operand value (variables are not resolved) 454 * @throws IllegalStateException if this operand has never been set 455 * @see #getString2(ExecutionContext) 456 */ 457 public String getString2() { 458 if (string2IsSet) { 459 return string2; 460 } 461 throw new IllegalStateException("operand has not been set: " + string2); 462 } 463 /** 464 * Returns the {@code <string2>} (variables are resolved): Replacement string for substitute command s; appended, inserted or 465 changed text for a, i and c command; destination characters for 466 translate command y; ignored by all other commands. 467 <p> 468 If string2 is a replacement string for the substitute command: an 469 ampersand ('&') appearing in the replacement string is replaced 470 by the string matching the regular expression; the characters "\n", 471 where n is a digit, are replaced by the text matched by the 472 corresponding backreference expression. The special meaning of 473 '&' and "\n" in this context can be suppressed by preceding it 474 by a backslash. 475<p> 476 (This operand only applies to the commands s, a, i, c and y and is 477 ignored by all other commands). 478 * 479 * @param context the execution context used to resolve variables 480 * @return the {@code <string2>} operand value after resolving variables 481 * @throws IllegalStateException if this operand has never been set 482 * @see #getString2() 483 */ 484 public String getString2(ExecutionContext context) { 485 final String value = getString2(); 486 if (Arg.isVariable(value)) { 487 final Object resolved = resolveVariable(context.getVariableContext(), value); 488 final String converted = convert(context, "string2", String.class, resolved); 489 return converted; 490 } 491 return value; 492 } 493 494 /** 495 * Returns true if the {@code <string2>} operand has been set. 496 * <p> 497 * Note that this method returns true even if {@code null} was passed to the 498 * {@link #setString2(String)} method. 499 * 500 * @return true if the setter for the {@code <string2>} operand has 501 * been called at least once 502 */ 503 public boolean isString2Set() { 504 return string2IsSet; 505 } 506 /** 507 * Sets {@code <string2>}: Replacement string for substitute command s; appended, inserted or 508 changed text for a, i and c command; destination characters for 509 translate command y; ignored by all other commands. 510 <p> 511 If string2 is a replacement string for the substitute command: an 512 ampersand ('&') appearing in the replacement string is replaced 513 by the string matching the regular expression; the characters "\n", 514 where n is a digit, are replaced by the text matched by the 515 corresponding backreference expression. The special meaning of 516 '&' and "\n" in this context can be suppressed by preceding it 517 by a backslash. 518<p> 519 (This operand only applies to the commands s, a, i, c and y and is 520 ignored by all other commands). 521 * 522 * @param string2 the value for the {@code <string2>} operand 523 */ 524 public void setString2(String string2) { 525 this.string2 = string2; 526 this.string2IsSet = true; 527 } 528 /** 529 * Returns the {@code <occurrence>} operand value: Substitute for the given occurrences only of the regexp found within 530 the matched string; the occurrence indices are one-based. If empty 531 or omitted, all occurrences are substituted. 532 <p> 533 (This operand only applies to the substitute command and is ignored 534 by all other commands). 535 * 536 * @return the {@code <occurrence>} operand value (variables are not resolved) 537 * @throws IllegalStateException if this operand has never been set 538 * 539 */ 540 public int[] getOccurrence() { 541 if (occurrenceIsSet) { 542 return occurrence; 543 } 544 throw new IllegalStateException("operand has not been set: " + occurrence); 545 } 546 547 /** 548 * Returns true if the {@code <occurrence>} operand has been set. 549 * <p> 550 * Note that this method returns true even if {@code null} was passed to the 551 * {@link #setOccurrence(int[])} method. 552 * 553 * @return true if the setter for the {@code <occurrence>} operand has 554 * been called at least once 555 */ 556 public boolean isOccurrenceSet() { 557 return occurrenceIsSet; 558 } 559 /** 560 * Sets {@code <occurrence>}: Substitute for the given occurrences only of the regexp found within 561 the matched string; the occurrence indices are one-based. If empty 562 or omitted, all occurrences are substituted. 563 <p> 564 (This operand only applies to the substitute command and is ignored 565 by all other commands). 566 * 567 * @param occurrence the value for the {@code <occurrence>} operand 568 */ 569 public void setOccurrence(int... occurrence) { 570 this.occurrence = occurrence; 571 this.occurrenceIsSet = true; 572 } 573 /** 574 * Returns the {@code <args>} operand value: String arguments defining the options and operands for the command. 575 Options can be specified by acronym (with a leading dash "-") or by 576 long name (with two leading dashes "--"). Operands other than the 577 default "--script" operand have to be prefixed with the operand name 578 (e.g. "--occurrence" for subsequent occurrence indices). 579 * 580 * @return the {@code <args>} operand value (variables are not resolved) 581 * @throws IllegalStateException if this operand has never been set 582 * 583 */ 584 public String[] getArgs() { 585 if (argsIsSet) { 586 return args; 587 } 588 throw new IllegalStateException("operand has not been set: " + args); 589 } 590 591 /** 592 * Returns true if the {@code <args>} operand has been set. 593 * 594 * @return true if the setter for the {@code <args>} operand has 595 * been called at least once 596 */ 597 public boolean isArgsSet() { 598 return argsIsSet; 599 } 600 601 /** 602 * Returns true if the {@code --}{@link SedOption#quiet quiet} option 603 * is set. The option is also known as {@code -}n option. 604 * <p> 605 * Description: Suppress the default output (in which each line, after it is 606 examined for editing, is written to standard output). Only lines 607 explicitly selected for output are written. 608 * 609 * @return true if the {@code --quiet} or {@code -n} option is set 610 */ 611 public boolean isQuiet() { 612 return getOptions().isSet(SedOption.quiet); 613 } 614 /** 615 * Returns true if the {@code --}{@link SedOption#global global} option 616 * is set. The option is also known as {@code -}g option. 617 * <p> 618 * Description: Globally substitute for all non-overlapping instances of the regexp 619 rather than just the first one. 620 <p> 621 (This option is ignored if the occurrence operand is specified). 622 * 623 * @return true if the {@code --global} or {@code -g} option is set 624 */ 625 public boolean isGlobal() { 626 return getOptions().isSet(SedOption.global); 627 } 628 /** 629 * Returns true if the {@code --}{@link SedOption#print print} option 630 * is set. The option is also known as {@code -}p option. 631 * <p> 632 * Description: Write the matched line to standard output. 633 * 634 * @return true if the {@code --print} or {@code -p} option is set 635 */ 636 public boolean isPrint() { 637 return getOptions().isSet(SedOption.print); 638 } 639 /** 640 * Returns true if the {@code --}{@link SedOption#lineNumber lineNumber} option 641 * is set. The option is also known as {@code -}l option. 642 * <p> 643 * Description: Writes the current line number on a separate line to the standard 644 output. 645 * 646 * @return true if the {@code --lineNumber} or {@code -l} option is set 647 */ 648 public boolean isLineNumber() { 649 return getOptions().isSet(SedOption.lineNumber); 650 } 651 /** 652 * Returns true if the {@code --}{@link SedOption#ignoreCase ignoreCase} option 653 * is set. The option is also known as {@code -}I option. 654 * <p> 655 * Description: Use case insensitive pattern matching. 656 * 657 * @return true if the {@code --ignoreCase} or {@code -I} option is set 658 */ 659 public boolean isIgnoreCase() { 660 return getOptions().isSet(SedOption.ignoreCase); 661 } 662 /** 663 * Returns true if the {@code --}{@link SedOption#substitute substitute} option 664 * is set. The option is also known as {@code -}s option. 665 * <p> 666 * Description: Substitutes the replacement string for instances of the regexp in 667 the matched line. 668 <p> 669 An ampersand ('&') appearing in the replacement is be replaced 670 by the line matching the regexp. The characters "\n", where n is a 671 digit, are replaced by the text matched by the corresponding 672 backreference expression. The special meaning of '&' and "\n" 673 in this context can be suppressed by preceding it by a backslash. 674<p> 675 A line can be split by substituting a newline ('\n') into it. 676 <p> 677 A substitution is considered to have been performed even if the 678 replacement string is identical to the string that it replaces. 679 * 680 * @return true if the {@code --substitute} or {@code -s} option is set 681 */ 682 public boolean isSubstitute() { 683 return getOptions().isSet(SedOption.substitute); 684 } 685 /** 686 * Returns true if the {@code --}{@link SedOption#append append} option 687 * is set. The option is also known as {@code -}a option. 688 * <p> 689 * Description: Append string2 as a separate line after the matched line. 690 * 691 * @return true if the {@code --append} or {@code -a} option is set 692 */ 693 public boolean isAppend() { 694 return getOptions().isSet(SedOption.append); 695 } 696 /** 697 * Returns true if the {@code --}{@link SedOption#insert insert} option 698 * is set. The option is also known as {@code -}i option. 699 * <p> 700 * Description: Insert string2 as a separate line before the matched line. 701 * 702 * @return true if the {@code --insert} or {@code -i} option is set 703 */ 704 public boolean isInsert() { 705 return getOptions().isSet(SedOption.insert); 706 } 707 /** 708 * Returns true if the {@code --}{@link SedOption#change change} option 709 * is set. The option is also known as {@code -}c option. 710 * <p> 711 * Description: Write string2 as a separate line instead of the matched line. 712 * 713 * @return true if the {@code --change} or {@code -c} option is set 714 */ 715 public boolean isChange() { 716 return getOptions().isSet(SedOption.change); 717 } 718 /** 719 * Returns true if the {@code --}{@link SedOption#delete delete} option 720 * is set. The option is also known as {@code -}d option. 721 * <p> 722 * Description: Delete the matched line. 723 * 724 * @return true if the {@code --delete} or {@code -d} option is set 725 */ 726 public boolean isDelete() { 727 return getOptions().isSet(SedOption.delete); 728 } 729 /** 730 * Returns true if the {@code --}{@link SedOption#translate translate} option 731 * is set. The option is also known as {@code -}y option. 732 * <p> 733 * Description: Replace all occurrences of characters in string1 with the 734 corresponding characters in string2. If the number of characters in 735 the two strings are not equal, or if any of the characters in 736 string1 appear more than once, the results are undefined. 737 * 738 * @return true if the {@code --translate} or {@code -y} option is set 739 */ 740 public boolean isTranslate() { 741 return getOptions().isSet(SedOption.translate); 742 } 743 744 @Override 745 public String toString() { 746 // ok, we have options or arguments or both 747 final StringBuilder sb = new StringBuilder(); 748 749 if (argsIsSet) { 750 for (String arg : args) { 751 if (sb.length() > 0) sb.append(' '); 752 sb.append(arg); 753 } 754 } else { 755 756 // first the options 757 if (options.size() > 0) { 758 sb.append(DefaultOptionSet.toString(options)); 759 } 760 // operand: <script> 761 if (scriptIsSet) { 762 if (sb.length() > 0) sb.append(' '); 763 sb.append("--").append("script"); 764 sb.append(" ").append(toString(getScript())); 765 } 766 // operand: <regexp> 767 if (regexpIsSet) { 768 if (sb.length() > 0) sb.append(' '); 769 sb.append("--").append("regexp"); 770 sb.append(" ").append(toString(getRegexp())); 771 } 772 // operand: <string1> 773 if (string1IsSet) { 774 if (sb.length() > 0) sb.append(' '); 775 sb.append("--").append("string1"); 776 sb.append(" ").append(toString(getString1())); 777 } 778 // operand: <replacement> 779 if (replacementIsSet) { 780 if (sb.length() > 0) sb.append(' '); 781 sb.append("--").append("replacement"); 782 sb.append(" ").append(toString(getReplacement())); 783 } 784 // operand: <string2> 785 if (string2IsSet) { 786 if (sb.length() > 0) sb.append(' '); 787 sb.append("--").append("string2"); 788 sb.append(" ").append(toString(getString2())); 789 } 790 // operand: <occurrence> 791 if (occurrenceIsSet) { 792 if (sb.length() > 0) sb.append(' '); 793 sb.append("--").append("occurrence"); 794 sb.append(" ").append(toString(getOccurrence())); 795 } 796 // operand: <args> 797 if (argsIsSet) { 798 if (sb.length() > 0) sb.append(' '); 799 sb.append("--").append("args"); 800 sb.append(" ").append(toString(getArgs())); 801 } 802 } 803 804 return sb.toString(); 805 } 806 private static String toString(Object value) { 807 if (value != null && value.getClass().isArray()) { 808 return ArrayUtil.toString(value); 809 } 810 return String.valueOf(value); 811 } 812}