1 19 20 package org.netbeans.modules.sendopts; 21 22 import java.io.File ; 23 import java.io.InputStream ; 24 import java.io.OutputStream ; 25 import java.io.PrintWriter ; 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 import java.util.HashSet ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.Locale ; 32 import java.util.Map ; 33 import java.util.Set ; 34 import java.util.logging.Logger ; 35 import org.netbeans.api.sendopts.CommandException; 36 import org.netbeans.api.sendopts.CommandLine; 37 import org.netbeans.spi.sendopts.Env; 38 import org.netbeans.spi.sendopts.Option; 39 import org.netbeans.spi.sendopts.OptionProcessor; 40 import org.openide.util.NbBundle; 41 42 49 public abstract class OptionImpl implements Cloneable { 50 public static final Logger LOG = Logger.getLogger(OptionImpl.class.getName()); 51 52 public static final Object NO_DEFAULT = new Object (); 53 static final String [] NO_VALUE = new String [0]; 54 55 56 public final Option root; 57 58 59 Option option; 60 64 final int argumentType; 65 66 OptionProcessor provider; 67 68 private Appearance appear; 69 70 73 OptionImpl(Option o, OptionProcessor p, int a) { 74 this.root = o; 75 this.option = o; 76 this.provider = p; 77 this.argumentType = a; 78 } 79 80 public int getShortName() { 81 return Trampoline.DEFAULT.getShortName(option); 82 } 83 84 public String getLongName() { 85 return Trampoline.DEFAULT.getLongName(option); 86 } 87 88 89 public int getArgumentType() { 90 return this.argumentType; 91 } 92 93 public int hashCode() { 94 return option.hashCode(); 95 } 96 97 public boolean equals(Object obj) { 98 if (obj instanceof OptionImpl) { 99 return option.equals(((OptionImpl)obj).option); 100 } 101 return false; 102 } 103 104 106 public final void append(StringBuffer sb) { 107 String c = getClass().getName(); 108 int i = c.indexOf('$'); 109 assert i >= 0; 110 sb.append(c.substring(i + 1)); 111 appendInternals(sb); 112 } 113 114 void appendInternals(StringBuffer sb) { 115 } 116 117 public String toString() { 118 return "Impl:" + option; } 120 121 126 public String findName(boolean used, String [] args) { 127 if (used) { 128 for (int i = 0; i < args.length; i++) { 129 if (args[i].startsWith("-" + (char)getShortName())) { 130 return "-" + (char)getShortName(); } 132 if (args[i].startsWith("--" + getLongName())) { 133 return "--" + getLongName(); } 135 } 136 } else { 137 if (getLongName() != null) { 138 return "--" + getLongName(); } 140 if (getShortName() != -1) { 141 return "-" + (char)getShortName(); } 143 } 144 145 return null; 146 } 147 148 150 public Option getOption() { 151 return option; 152 } 153 154 157 public OptionProcessor getProvider() { 158 return provider; 159 } 160 161 162 @SuppressWarnings ("unchecked") 163 private static <T extends OptionImpl> T doClone(T impl) { 164 try { 165 return (T)impl.clone(); 166 } catch (CloneNotSupportedException ex) { 167 assert false; 168 return null; 169 } 170 } 171 172 174 public static OptionImpl cloneImpl(OptionImpl proto, Option option, OptionProcessor prov) { 175 OptionImpl n; 176 try { 177 n = (OptionImpl) proto.clone(); 178 } catch (CloneNotSupportedException ex) { 179 assert false; 180 return null; 181 } 182 n.option = option; 183 if (prov != null) { 184 n.provider = prov; 185 } 186 return n; 187 } 188 189 193 public final OptionImpl addWorkingCopy(Collection <OptionImpl> allOptions) { 194 if (allOptions.contains(this)) { 195 Iterator it = allOptions.iterator(); 197 for(;;) { 198 OptionImpl elem = (OptionImpl) it.next(); 199 if (elem.equals(this)) { 200 return (OptionImpl)elem; 201 } 202 } 203 } else { 204 return handleAdd(allOptions); 205 } 206 } 207 208 211 protected abstract OptionImpl handleAdd(Collection <OptionImpl> allOptions); 212 213 public static class Appearance { 214 private MessageFactory msg; 215 216 private Appearance() {} 217 218 public static final Appearance YES = new Appearance(); 219 public static final Appearance NO = new Appearance(); 220 public static final Appearance MAYBE = new Appearance(); 221 222 public static final Appearance createError(MessageFactory msg) { 223 Appearance a = new Appearance(); 224 a.msg = msg; 225 return a; 226 } 227 228 229 public final boolean isThere() { 230 return this == YES; 231 } 232 233 public boolean isError() { 234 return YES != this && NO != this && MAYBE != this; 235 } 236 237 public String errorMessage(String [] args) { 238 return msg.errorMessage(args); 240 } 241 242 public String toString() { 243 if (this == YES) return "YES"; if (this == NO) return "NO"; if (this == MAYBE) return "MAYBE"; return "ERROR[" + errorMessage(new String [0]) + "]"; } 248 } 250 public static interface MessageFactory { 251 public String errorMessage(String [] args); 252 } 254 255 260 public abstract Appearance checkConsistent(Set <OptionImpl> presentOptions); 261 262 264 public void markConsistent(Appearance a) { 265 assert appear == null || appear == a; 266 appear = a; 267 } 268 269 271 public abstract void process(String [] additionalArgs, Map <Option,String []> optionsAndTheirArgs) throws CommandException; 272 273 274 public abstract void associateValue(String value) throws CommandException; 275 276 277 public void usage(PrintWriter w, int max) { 278 Trampoline.DEFAULT.usage(w, option, max); 279 } 280 281 public OptionImpl findNotUsedOption(Set <OptionImpl> used) { 282 return appear == null && used.contains(this) ? this : null; 283 } 284 285 287 public static OptionImpl createNoArg(Option o) { 288 class NoArg extends OptionImpl { 289 public NoArg(Option o, OptionProcessor p, int t) { 290 super(o, p, 0); 291 } 292 293 public void process(String [] additionalArgs, Map <Option,String []> optionsAndTheirArgs) throws CommandException { 294 optionsAndTheirArgs.put(option, NO_VALUE); 295 } 296 public void associateValue(String value) { 297 throw new IllegalStateException (); 298 } 299 300 public Appearance checkConsistent(Set <OptionImpl> presentOptions) { 301 return presentOptions.contains(this) ? Appearance.YES : Appearance.NO; 302 } 303 304 protected OptionImpl handleAdd(Collection <OptionImpl> allOptions) { 305 NoArg n = doClone(this); 306 allOptions.add(n); 307 return n; 308 } 309 } 310 return new NoArg(o, null, 0); 311 } 312 313 public static OptionImpl createOneArg(Option option, boolean required) { 314 class OneOptionImpl extends OptionImpl { 315 private String arg; 316 317 public OneOptionImpl(Option option, OptionProcessor p, int type, String value) { 318 super(option, p, type); 319 this.arg = value; 320 } 321 322 public void process(String [] additionalArgs, Map <Option,String []> optionsAndTheirArgs) throws CommandException { 323 if (arg != null) { 324 optionsAndTheirArgs.put(option, new String [] { arg }); 325 } else { 326 assert argumentType == 2; 327 optionsAndTheirArgs.put(option, NO_VALUE); 328 } 329 } 330 331 public void associateValue(String value) throws CommandException { 332 this.arg = value; 333 } 334 335 public OptionImpl handleAdd(Collection <OptionImpl> allOptions) { 336 OneOptionImpl one = doClone(this); 337 allOptions.add(one); 338 return one; 339 } 340 341 public Appearance checkConsistent(Set <OptionImpl> presentOptions) { 342 return presentOptions.contains(this) ? Appearance.YES : Appearance.NO; 343 } 344 } 345 346 return new OneOptionImpl(option, null, required ? 1 : 2, null); 347 } 348 public static OptionImpl createAdd(Option option, final boolean defaultOption) { 349 class AddOptionImpl extends OptionImpl { 350 private boolean processed; 351 352 public AddOptionImpl(Option option, OptionProcessor p) { 353 super(option, p, defaultOption ? 4 : 3); 354 } 355 public void process(String [] additionalArgs, Map <Option,String []> optionsAndTheirArgs) throws CommandException { 356 optionsAndTheirArgs.put(option, additionalArgs); 357 } 358 public void associateValue(String value) throws CommandException { 359 throw new IllegalStateException (); 360 } 361 public Appearance checkConsistent(Set <OptionImpl> presentOptions) { 362 return presentOptions.contains(this) ? Appearance.YES : Appearance.NO; 363 } 364 protected OptionImpl handleAdd(Collection <OptionImpl> allOptions) { 365 AddOptionImpl n = doClone(this); 366 allOptions.add(n); 367 return n; 368 } 369 } 370 371 return new AddOptionImpl(option, null); 372 } 373 374 376 public static OptionImpl find(Option op) { 377 return Trampoline.DEFAULT.impl(op); 378 } 379 380 385 public static OptionImpl create(Option option, final int type, List <Option> alternatives) { 386 class AlternativeOptionsImpl extends OptionImpl { 387 388 private List <OptionImpl> arr; 389 390 private List <OptionImpl> used; 391 392 private Set <OptionImpl> missing; 393 394 public AlternativeOptionsImpl(Option self, OptionProcessor p, List <OptionImpl> arr) { 395 super(self, p, 0); 396 this.arr = arr; 397 } 398 399 public Appearance checkConsistent(Set <OptionImpl> presentOptions) { 400 int cnt = 0; 401 402 used = new ArrayList <OptionImpl>(); 403 missing = new HashSet <OptionImpl>(); 404 405 Set <OptionImpl> maybe = new HashSet <OptionImpl>(); 406 for (int i = 0; i < arr.size(); i++) { 407 Appearance check = arr.get(i).checkConsistent(presentOptions); 408 if (check.isError()) { 409 return check; 411 } 412 413 if (Appearance.NO == check) { 414 missing.add(arr.get(i)); 415 continue; 416 } 417 if (Appearance.MAYBE == check) { 418 maybe.add(arr.get(i)); 419 continue; 420 } 421 422 cnt++; 423 used.add(arr.get(i)); 424 } 425 426 if (cnt == 0) { 427 return type == 3 ? Appearance.MAYBE : Appearance.NO; 429 } 430 431 switch (type) { 432 case 0: if (cnt == 1) { 433 return Appearance.YES; 435 } 436 break; 437 case 1: if (missing.isEmpty()) { 438 used.addAll(maybe); 439 return Appearance.YES; 441 } 442 break; 443 case 3: 444 case 2: if (cnt >= 1) { 445 return Appearance.YES; 447 } 448 break; 449 } 450 451 class MF implements MessageFactory { 452 public String errorMessage(String [] args) { 453 switch (type) { 454 case 0: 455 assert used.size() >= 2 : "At least two: " + used; 456 457 String n1 = used.get(0).findName(true, args); 458 String n2 = used.get(1).findName(true, args); 459 assert n1 != null; 460 assert n2 != null; 461 462 return NbBundle.getMessage(CommandLine.class, "MSG_CannotTogether", n1, n2); 463 case 1: { 464 StringBuffer sb = new StringBuffer (); 465 String app = ""; 466 for (OptionImpl i : arr) { 467 sb.append(app); 468 sb.append(i.findName(false, args)); 469 app = ", "; 470 } 471 return NbBundle.getMessage(CommandLine.class, "MSG_MissingOptions", sb.toString()); 472 } 473 case 2: { 474 StringBuffer sb = new StringBuffer (); 475 String app = ""; 476 for (OptionImpl i : arr) { 477 sb.append(app); 478 sb.append(i.findName(false, args)); 479 app = ", "; 480 } 481 return NbBundle.getMessage(CommandLine.class, "MSG_NeedAtLeastOne", sb.toString()); 482 } 483 default: 484 throw new IllegalStateException ("Type: " + type); 485 } 486 } 487 } 488 489 490 return Appearance.createError(new MF()); 492 } 493 494 public void markConsistent(Appearance a) { 495 super.markConsistent(a); 496 for (OptionImpl i : arr) { 497 i.markConsistent(a); 498 } 499 } 500 501 public OptionImpl findNotUsedOption(Set <OptionImpl> used) { 502 OptionImpl me = super.findNotUsedOption(used); 503 if (me != null) { 504 return me; 505 } 506 for (OptionImpl i : arr) { 507 me = i.findNotUsedOption(used); 508 if (me != null) { 509 return me; 510 } 511 } 512 return null; 513 } 514 515 public void associateValue(String value) throws CommandException { 516 } 517 public OptionImpl handleAdd(Collection <OptionImpl> allOptions) { 518 List <OptionImpl> copy = new ArrayList <OptionImpl>(); 519 for (int i = 0; i < arr.size(); i++) { 520 copy.add(arr.get(i).addWorkingCopy(allOptions)); 521 } 522 523 AlternativeOptionsImpl alt = doClone(this); 524 alt.arr = copy; 525 allOptions.add(alt); 526 return alt; 527 } 528 529 public void process(String [] additionalArgs, Map <Option,String []> optionsAndTheirArgs) throws CommandException { 530 optionsAndTheirArgs.put(option, NO_VALUE); 531 for (OptionImpl i : used) { 532 i.process(additionalArgs, optionsAndTheirArgs); 533 } 534 } 535 536 public String findName(boolean usedOrAny, String [] args) { 537 for (Iterator it = arr.iterator(); it.hasNext();) { 538 OptionImpl elem = (OptionImpl) it.next(); 539 String n = elem.findName(usedOrAny, args); 540 if (n != null) { 541 return n; 542 } 543 } 544 return null; 545 } 546 } 547 548 ArrayList <OptionImpl> list = new ArrayList <OptionImpl>(); 549 for (int i = 0; i < alternatives.size(); i++) { 550 list.add(find(alternatives.get(i))); 551 } 552 553 return new AlternativeOptionsImpl(option, null, list); 554 } 555 556 public static abstract class Trampoline { 557 public static Trampoline DEFAULT; 558 static { 559 try { 560 Class.forName(Option.class.getName(), true, Trampoline.class.getClassLoader()); 561 } catch (Exception ex) { 562 ex.printStackTrace(); 563 } 564 } 565 public abstract OptionImpl impl(Option o); 566 public abstract Env create(InputStream is, OutputStream os, OutputStream err, File currentDir); 567 public abstract void usage(PrintWriter w, Option o, int max); 568 public abstract Option[] getOptions(OptionProcessor p); 569 public abstract void process(OptionProcessor provider, Env env, Map <Option,String []> options) 570 throws CommandException; 571 public abstract String getLongName(Option o); 572 public abstract int getShortName(Option o); 573 public abstract String getDisplayName(Option o, Locale l); 574 } 575 } 576 | Popular Tags |