KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > sendopts > OptionImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.sendopts;
21
22 import java.io.File JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.OutputStream JavaDoc;
25 import java.io.PrintWriter JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Locale JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Set JavaDoc;
34 import java.util.logging.Logger JavaDoc;
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 /** Internal representtion of an option. It is used in
43  * the implementation of the API package, the API shall
44  * be completely separated from the SPI by using this description
45  * of an option.
46  *
47  * @author Jaroslav Tulach
48  */

49 public abstract class OptionImpl implements Cloneable JavaDoc {
50     public static final Logger JavaDoc LOG = Logger.getLogger(OptionImpl.class.getName());
51     
52     public static final Object JavaDoc NO_DEFAULT = new Object JavaDoc();
53     static final String JavaDoc[] NO_VALUE = new String JavaDoc[0];
54     
55     /** the root option */
56     public final Option root;
57     
58     /** our peer option */
59     Option option;
60     /** 0 - no options
61      * 1 - one required option
62      * 2 - one voluntary option
63      */

64     final int argumentType;
65     /** provider that is supposed to process the value */
66     OptionProcessor provider;
67     /** mark appearance */
68     private Appearance appear;
69
70     /**
71      * Creates a new instance of OptionImpl
72      */

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 JavaDoc getLongName() {
85         return Trampoline.DEFAULT.getLongName(option);
86     }
87     
88     /** @return 0 for no argument option, 1 for required argument and 2 for optional argument */
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 JavaDoc obj) {
98         if (obj instanceof OptionImpl) {
99             return option.equals(((OptionImpl)obj).option);
100         }
101         return false;
102     }
103
104     /** Appends to the buffer description of the optionimpl. Called from Option.toString()
105      */

106     public final void append(StringBuffer JavaDoc sb) {
107         String JavaDoc 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 JavaDoc sb) {
115     }
116     
117     public String JavaDoc toString() {
118         return "Impl:" + option; // NOI18N
119
}
120     
121     /** Finds a possible name for this option.
122      * @param used if true then one is going to search for real occurence of the option in the command line
123      * otherwise any possible name will do
124      * @param args the command line
125      */

126     public String JavaDoc findName(boolean used, String JavaDoc[] args) {
127         if (used) {
128             for (int i = 0; i < args.length; i++) {
129                 if (args[i].startsWith("-" + (char)getShortName())) {
130                     return "-" + (char)getShortName(); // NOI18N
131
}
132                 if (args[i].startsWith("--" + getLongName())) {
133                     return "--" + getLongName(); // NOI18N
134
}
135             }
136         } else {
137             if (getLongName() != null) {
138                 return "--" + getLongName(); // NOI18N
139
}
140             if (getShortName() != -1) {
141                 return "-" + (char)getShortName(); // NOI18N
142
}
143         }
144         
145         return null;
146     }
147     
148     /** Obtains the option for this OptionImpl.
149      */

150     public Option getOption() {
151         return option;
152     }
153     
154     /** Provider associated with the Option Impl.
155      * @return the provider or null
156      */

157     public OptionProcessor getProvider() {
158         return provider;
159     }
160     
161     
162     @SuppressWarnings JavaDoc("unchecked")
163     private static <T extends OptionImpl> T doClone(T impl) {
164         try {
165             return (T)impl.clone();
166         } catch (CloneNotSupportedException JavaDoc ex) {
167             assert false;
168             return null;
169         }
170     }
171
172     /** Creates a clone of the option impl with new option.
173      */

174     public static OptionImpl cloneImpl(OptionImpl proto, Option option, OptionProcessor prov) {
175         OptionImpl n;
176         try {
177             n = (OptionImpl) proto.clone();
178         } catch (CloneNotSupportedException JavaDoc 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     /** Clones itself into a working copy option. For most options just add "this", for
190      * more complex ones override
191      * @return the reference to new itself
192      */

193     public final OptionImpl addWorkingCopy(Collection JavaDoc<OptionImpl> allOptions) {
194         if (allOptions.contains(this)) {
195             // find element that is equal
196
Iterator JavaDoc 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     /** Called to add this option to allOptions collection.
209      * It is guaranteed that the option is not there.
210      */

211     protected abstract OptionImpl handleAdd(Collection JavaDoc<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 JavaDoc errorMessage(String JavaDoc[] args) {
238             // you are allowed to call this method for on isError() Appearance!
239
return msg.errorMessage(args);
240         }
241         
242         public String JavaDoc toString() {
243             if (this == YES) return "YES"; // NOI18N
244
if (this == NO) return "NO"; // NOI18N
245
if (this == MAYBE) return "MAYBE"; // NOI18N
246
return "ERROR[" + errorMessage(new String JavaDoc[0]) + "]"; // NOI18N
247
}
248     } // end of Appearance
249

250     public static interface MessageFactory {
251         public String JavaDoc errorMessage(String JavaDoc[] args);
252     } // end of MessageFactory
253

254     
255     /** Consistency test, based on the list of leaf options present in the
256      * command line.
257      * @param present set of leaf options present in the command line
258      * @return Boolean - TRUE option is there, FALSE option is not there, null everything is broken
259      */

260     public abstract Appearance checkConsistent(Set JavaDoc<OptionImpl> presentOptions);
261     
262     /** Marks each optionimpl as ok, and used.
263      */

264     public void markConsistent(Appearance a) {
265         assert appear == null || appear == a;
266         appear = a;
267     }
268
269     /** Fills the map with an option that shall be processed.
270      */

271     public abstract void process(String JavaDoc[] additionalArgs, Map JavaDoc<Option,String JavaDoc[]> optionsAndTheirArgs) throws CommandException;
272
273     /** Associates this option with given value */
274     public abstract void associateValue(String JavaDoc value) throws CommandException;
275
276
277     public void usage(PrintWriter JavaDoc w, int max) {
278         Trampoline.DEFAULT.usage(w, option, max);
279     }
280
281     public OptionImpl findNotUsedOption(Set JavaDoc<OptionImpl> used) {
282         return appear == null && used.contains(this) ? this : null;
283     }
284     
285     /** Creates an impl that delegates to given option and NoArgumentProcessor processor.
286      */

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 JavaDoc[] additionalArgs, Map JavaDoc<Option,String JavaDoc[]> optionsAndTheirArgs) throws CommandException {
294                 optionsAndTheirArgs.put(option, NO_VALUE);
295             }
296             public void associateValue(String JavaDoc value) {
297                 throw new IllegalStateException JavaDoc();
298             }
299             
300             public Appearance checkConsistent(Set JavaDoc<OptionImpl> presentOptions) {
301                 return presentOptions.contains(this) ? Appearance.YES : Appearance.NO;
302             }
303             
304             protected OptionImpl handleAdd(Collection JavaDoc<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 JavaDoc arg;
316             
317             public OneOptionImpl(Option option, OptionProcessor p, int type, String JavaDoc value) {
318                 super(option, p, type);
319                 this.arg = value;
320             }
321
322             public void process(String JavaDoc[] additionalArgs, Map JavaDoc<Option,String JavaDoc[]> optionsAndTheirArgs) throws CommandException {
323                 if (arg != null) {
324                     optionsAndTheirArgs.put(option, new String JavaDoc[] { arg });
325                 } else {
326                     assert argumentType == 2;
327                     optionsAndTheirArgs.put(option, NO_VALUE);
328                 }
329             }
330
331             public void associateValue(String JavaDoc value) throws CommandException {
332                 this.arg = value;
333             }
334
335             public OptionImpl handleAdd(Collection JavaDoc<OptionImpl> allOptions) {
336                 OneOptionImpl one = doClone(this);
337                 allOptions.add(one);
338                 return one;
339             }
340
341             public Appearance checkConsistent(Set JavaDoc<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 JavaDoc[] additionalArgs, Map JavaDoc<Option,String JavaDoc[]> optionsAndTheirArgs) throws CommandException {
356                 optionsAndTheirArgs.put(option, additionalArgs);
357             }
358             public void associateValue(String JavaDoc value) throws CommandException {
359                 throw new IllegalStateException JavaDoc();
360             }
361             public Appearance checkConsistent(Set JavaDoc<OptionImpl> presentOptions) {
362                 return presentOptions.contains(this) ? Appearance.YES : Appearance.NO;
363             }
364             protected OptionImpl handleAdd(Collection JavaDoc<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     /** Finds impl for given option.
375      */

376     public static OptionImpl find(Option op) {
377         return Trampoline.DEFAULT.impl(op);
378     }
379
380     /** type of the option:
381      * 0 = oneOf
382      * 1 = allOf
383      * 2 = someOf
384      */

385     public static OptionImpl create(Option option, final int type, List JavaDoc<Option> alternatives) {
386         class AlternativeOptionsImpl extends OptionImpl {
387             /** array of options to select one from */
388             private List JavaDoc<OptionImpl> arr;
389             /** array of used options */
390             private List JavaDoc<OptionImpl> used;
391             /** set of missing options */
392             private Set JavaDoc<OptionImpl> missing;
393             
394             public AlternativeOptionsImpl(Option self, OptionProcessor p, List JavaDoc<OptionImpl> arr) {
395                 super(self, p, 0);
396                 this.arr = arr;
397             }
398
399             public Appearance checkConsistent(Set JavaDoc<OptionImpl> presentOptions) {
400                 int cnt = 0;
401                 
402                 used = new ArrayList JavaDoc<OptionImpl>();
403                 missing = new HashSet JavaDoc<OptionImpl>();
404
405                 Set JavaDoc<OptionImpl> maybe = new HashSet JavaDoc<OptionImpl>();
406                 for (int i = 0; i < arr.size(); i++) {
407                     Appearance check = arr.get(i).checkConsistent(presentOptions);
408                     if (check.isError()) {
409                         // not consistent
410
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                     // this option is not there
428
return type == 3 ? Appearance.MAYBE : Appearance.NO;
429                 }
430
431                 switch (type) {
432                     case 0: if (cnt == 1) {
433                         // ok, success => we have exactly one option
434
return Appearance.YES;
435                     }
436                     break;
437                     case 1: if (missing.isEmpty()) {
438                         used.addAll(maybe);
439                         // ok, success => we have all our options
440
return Appearance.YES;
441                     }
442                     break;
443                     case 3:
444                     case 2: if (cnt >= 1) {
445                         // ok, success => we have at least one
446
return Appearance.YES;
447                     }
448                     break;
449                 }
450                 
451                 class MF implements MessageFactory {
452                     public String JavaDoc errorMessage(String JavaDoc[] args) {
453                         switch (type) {
454                         case 0:
455                             assert used.size() >= 2 : "At least two: " + used;
456
457                             String JavaDoc n1 = used.get(0).findName(true, args);
458                             String JavaDoc 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 JavaDoc sb = new StringBuffer JavaDoc();
465                                 String JavaDoc 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 JavaDoc sb = new StringBuffer JavaDoc();
475                                 String JavaDoc 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 JavaDoc("Type: " + type);
485                         }
486                     }
487                 }
488                 
489                 
490                 // not everything is ok, more options present
491
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 JavaDoc<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 JavaDoc value) throws CommandException {
516             }
517             public OptionImpl handleAdd(Collection JavaDoc<OptionImpl> allOptions) {
518                 List JavaDoc<OptionImpl> copy = new ArrayList JavaDoc<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 JavaDoc[] additionalArgs, Map JavaDoc<Option,String JavaDoc[]> 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 JavaDoc findName(boolean usedOrAny, String JavaDoc[] args) {
537                 for (Iterator JavaDoc it = arr.iterator(); it.hasNext();) {
538                     OptionImpl elem = (OptionImpl) it.next();
539                     String JavaDoc n = elem.findName(usedOrAny, args);
540                     if (n != null) {
541                         return n;
542                     }
543                 }
544                 return null;
545             }
546         }
547         
548         ArrayList JavaDoc<OptionImpl> list = new ArrayList JavaDoc<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 JavaDoc ex) {
562                 ex.printStackTrace();
563             }
564         }
565         public abstract OptionImpl impl(Option o);
566         public abstract Env create(InputStream JavaDoc is, OutputStream JavaDoc os, OutputStream JavaDoc err, File JavaDoc currentDir);
567         public abstract void usage(PrintWriter JavaDoc w, Option o, int max);
568         public abstract Option[] getOptions(OptionProcessor p);
569         public abstract void process(OptionProcessor provider, Env env, Map JavaDoc<Option,String JavaDoc[]> options)
570         throws CommandException;
571         public abstract String JavaDoc getLongName(Option o);
572         public abstract int getShortName(Option o);
573         public abstract String JavaDoc getDisplayName(Option o, Locale JavaDoc l);
574     }
575 }
576
Popular Tags