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. The characters "$0" 372 appearing in the replacement are replaced by the line matching 373 the regexp. The characters "$n", where n is a digit other than zero, 374 are replaced by the text matched by the corresponding backreference 375 expression (aka group). The special meaning of "$n" in this context 376 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. The characters "$0" 390 appearing in the replacement are replaced by the line matching 391 the regexp. The characters "$n", where n is a digit other than zero, 392 are replaced by the text matched by the corresponding backreference 393 expression (aka group). The special meaning of "$n" in this context 394 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. The characters "$0" 425 appearing in the replacement are replaced by the line matching 426 the regexp. The characters "$n", where n is a digit other than zero, 427 are replaced by the text matched by the corresponding backreference 428 expression (aka group). The special meaning of "$n" in this context 429 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: the 443 characters "$0" appearing in the replacement are replaced 444 by the line matching the regexp; the characters "$n", where n is a 445 digit other than zero, are replaced by the text matched by the 446 corresponding backreference expression (aka group). The special 447 meaning of "$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: the 469 characters "$0" appearing in the replacement are replaced 470 by the line matching the regexp; the characters "$n", where n is a 471 digit other than zero, are replaced by the text matched by the 472 corresponding backreference expression (aka group). The special 473 meaning of "$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: the 512 characters "$0" appearing in the replacement are replaced 513 by the line matching the regexp; the characters "$n", where n is a 514 digit other than zero, are replaced by the text matched by the 515 corresponding backreference expression (aka group). The special 516 meaning of "$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 The characters "$0" appearing in the replacement are replaced 670 by the line matching the regexp. The characters "$n", where n is a 671 digit other than zero, are replaced by the text matched by the 672 corresponding backreference expression (aka group). The special 673 meaning of "$n" in this context can be suppressed by preceding it 674 by a backslash. 675<p> 676 A line can be split by substituting a newline ('\n') into it. 677 <p> 678 A substitution is considered to have been performed even if the 679 replacement string is identical to the string that it replaces. 680 * 681 * @return true if the {@code --substitute} or {@code -s} option is set 682 */ 683 public boolean isSubstitute() { 684 return getOptions().isSet(SedOption.substitute); 685 } 686 /** 687 * Returns true if the {@code --}{@link SedOption#append append} option 688 * is set. The option is also known as {@code -}a option. 689 * <p> 690 * Description: Append string2 as a separate line after the matched line. 691 * 692 * @return true if the {@code --append} or {@code -a} option is set 693 */ 694 public boolean isAppend() { 695 return getOptions().isSet(SedOption.append); 696 } 697 /** 698 * Returns true if the {@code --}{@link SedOption#insert insert} option 699 * is set. The option is also known as {@code -}i option. 700 * <p> 701 * Description: Insert string2 as a separate line before the matched line. 702 * 703 * @return true if the {@code --insert} or {@code -i} option is set 704 */ 705 public boolean isInsert() { 706 return getOptions().isSet(SedOption.insert); 707 } 708 /** 709 * Returns true if the {@code --}{@link SedOption#change change} option 710 * is set. The option is also known as {@code -}c option. 711 * <p> 712 * Description: Write string2 as a separate line instead of the matched line. 713 * 714 * @return true if the {@code --change} or {@code -c} option is set 715 */ 716 public boolean isChange() { 717 return getOptions().isSet(SedOption.change); 718 } 719 /** 720 * Returns true if the {@code --}{@link SedOption#delete delete} option 721 * is set. The option is also known as {@code -}d option. 722 * <p> 723 * Description: Delete the matched line. 724 * 725 * @return true if the {@code --delete} or {@code -d} option is set 726 */ 727 public boolean isDelete() { 728 return getOptions().isSet(SedOption.delete); 729 } 730 /** 731 * Returns true if the {@code --}{@link SedOption#translate translate} option 732 * is set. The option is also known as {@code -}y option. 733 * <p> 734 * Description: Replace all occurrences of characters in string1 with the 735 corresponding characters in string2. If the number of characters in 736 the two strings are not equal, or if any of the characters in 737 string1 appear more than once, the results are undefined. 738 * 739 * @return true if the {@code --translate} or {@code -y} option is set 740 */ 741 public boolean isTranslate() { 742 return getOptions().isSet(SedOption.translate); 743 } 744 745 @Override 746 public String toString() { 747 // ok, we have options or arguments or both 748 final StringBuilder sb = new StringBuilder(); 749 750 if (argsIsSet) { 751 for (String arg : args) { 752 if (sb.length() > 0) sb.append(' '); 753 sb.append(arg); 754 } 755 } else { 756 757 // first the options 758 if (options.size() > 0) { 759 sb.append(DefaultOptionSet.toString(options)); 760 } 761 // operand: <script> 762 if (scriptIsSet) { 763 if (sb.length() > 0) sb.append(' '); 764 sb.append("--").append("script"); 765 sb.append(" ").append(toString(getScript())); 766 } 767 // operand: <regexp> 768 if (regexpIsSet) { 769 if (sb.length() > 0) sb.append(' '); 770 sb.append("--").append("regexp"); 771 sb.append(" ").append(toString(getRegexp())); 772 } 773 // operand: <string1> 774 if (string1IsSet) { 775 if (sb.length() > 0) sb.append(' '); 776 sb.append("--").append("string1"); 777 sb.append(" ").append(toString(getString1())); 778 } 779 // operand: <replacement> 780 if (replacementIsSet) { 781 if (sb.length() > 0) sb.append(' '); 782 sb.append("--").append("replacement"); 783 sb.append(" ").append(toString(getReplacement())); 784 } 785 // operand: <string2> 786 if (string2IsSet) { 787 if (sb.length() > 0) sb.append(' '); 788 sb.append("--").append("string2"); 789 sb.append(" ").append(toString(getString2())); 790 } 791 // operand: <occurrence> 792 if (occurrenceIsSet) { 793 if (sb.length() > 0) sb.append(' '); 794 sb.append("--").append("occurrence"); 795 sb.append(" ").append(toString(getOccurrence())); 796 } 797 // operand: <args> 798 if (argsIsSet) { 799 if (sb.length() > 0) sb.append(' '); 800 sb.append("--").append("args"); 801 sb.append(" ").append(toString(getArgs())); 802 } 803 } 804 805 return sb.toString(); 806 } 807 private static String toString(Object value) { 808 if (value != null && value.getClass().isArray()) { 809 return ArrayUtil.toString(value); 810 } 811 return String.valueOf(value); 812 } 813}