~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/core/FindWithCapabilities.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *    This program is free software; you can redistribute it and/or modify
 
3
 *    it under the terms of the GNU General Public License as published by
 
4
 *    the Free Software Foundation; either version 2 of the License, or
 
5
 *    (at your option) any later version.
 
6
 *
 
7
 *    This program is distributed in the hope that it will be useful,
 
8
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 *    GNU General Public License for more details.
 
11
 *
 
12
 *    You should have received a copy of the GNU General Public License
 
13
 *    along with this program; if not, write to the Free Software
 
14
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
15
 */
 
16
 
 
17
/*
 
18
 * FindWithCapabilities.java
 
19
 * Copyright (C) 2006 University of Waikato, Hamilton, New Zealand
 
20
 */
 
21
 
 
22
package weka.core;
 
23
 
 
24
import weka.core.Capabilities.Capability;
 
25
import weka.gui.GenericPropertiesCreator;
 
26
 
 
27
import java.io.BufferedReader;
 
28
import java.io.FileReader;
 
29
import java.util.Enumeration;
 
30
import java.util.Iterator;
 
31
import java.util.Properties;
 
32
import java.util.StringTokenizer;
 
33
import java.util.Vector;
 
34
 
 
35
/**
 
36
 * Locates all classes with certain capabilities. One should keep in mind, 
 
37
 * that works only with the default capabilities of a scheme and doesn't
 
38
 * take dependencies into account. E.g., a meta-classifier that could have
 
39
 * a base classifier handling numeric classes, but by default uses one with
 
40
 * a nominal class, will never show up in a search for schemes that handle
 
41
 * numeric classes.<p/>
 
42
 * 
 
43
 <!-- options-start -->
 
44
 * Valid options are: <p/>
 
45
 * 
 
46
 * <pre> All class and attribute options can be prefixed with 'not',
 
47
 * e.g., '-not-numeric-class'. This makes sure that the returned
 
48
 * schemes 'cannot' handle numeric classes.
 
49
 * </pre>
 
50
 * 
 
51
 * <pre> -num-instances &lt;num&gt;
 
52
 *  The minimum number of instances (default 1).</pre>
 
53
 * 
 
54
 * <pre> -unary-class
 
55
 *  Must handle unray classes.</pre>
 
56
 * 
 
57
 * <pre> -binary-class
 
58
 *  Must handle binary classes.</pre>
 
59
 * 
 
60
 * <pre> -nominal-class
 
61
 *  Must handle nominal classes.</pre>
 
62
 * 
 
63
 * <pre> -numeric-class
 
64
 *  Must handle numeric classes.</pre>
 
65
 * 
 
66
 * <pre> -string-class
 
67
 *  Must handle string classes.</pre>
 
68
 * 
 
69
 * <pre> -date-class
 
70
 *  Must handle date classes.</pre>
 
71
 * 
 
72
 * <pre> -relational-class
 
73
 *  Must handle relational classes.</pre>
 
74
 * 
 
75
 * <pre> -no-class
 
76
 *  Doesn't need a class.</pre>
 
77
 * 
 
78
 * <pre> -unary-atts
 
79
 *  Must handle unary attributes.</pre>
 
80
 * 
 
81
 * <pre> -binary-atts
 
82
 *  Must handle binary attributes.</pre>
 
83
 * 
 
84
 * <pre> -nominal-atts
 
85
 *  Must handle nominal attributes.</pre>
 
86
 * 
 
87
 * <pre> -numeric-atts
 
88
 *  Must handle numeric attributes.</pre>
 
89
 * 
 
90
 * <pre> -string-atts
 
91
 *  Must handle string attributes.</pre>
 
92
 * 
 
93
 * <pre> -date-atts
 
94
 *  Must handle date attributes.</pre>
 
95
 * 
 
96
 * <pre> -relational-atts
 
97
 *  Must handle relational attributes.</pre>
 
98
 * 
 
99
 * <pre> -only-multiinstance
 
100
 *  Must handle multi-instance data.</pre>
 
101
 * 
 
102
 * <pre> -W &lt;classname&gt;
 
103
 *  The Capabilities handler to base the handling on.
 
104
 *  The other parameters can be used to override the ones
 
105
 *  determined from the handler. Additional parameters for
 
106
 *  handler can be passed on after the '--'.
 
107
 *  Either '-W' or '-t' can be used.</pre>
 
108
 * 
 
109
 * <pre> -t &lt;file&gt;
 
110
 *  The dataset to base the capabilities on.
 
111
 *  The other parameters can be used to override the ones
 
112
 *  determined from the handler.
 
113
 *  Either '-t' or '-W' can be used.</pre>
 
114
 * 
 
115
 * <pre> -c &lt;num&gt;
 
116
 *  The index of the class attribute, -1 for none.
 
117
 *  'first' and 'last' are also valid.
 
118
 *  Only in conjunction with option '-t'.</pre>
 
119
 * 
 
120
 * <pre> -superclass
 
121
 *  Superclass to look for in the packages.
 
122
 * </pre>
 
123
 * 
 
124
 * <pre> -packages
 
125
 *  Comma-separated list of packages to search in.</pre>
 
126
 * 
 
127
 * <pre> -generic
 
128
 *  Retrieves the package list from the GenericPropertiesCreator
 
129
 *  for the given superclass. (overrides -packages &lt;list&gt;).</pre>
 
130
 * 
 
131
 * <pre> -misses
 
132
 *  Also prints the classname that didn't match the criteria.</pre>
 
133
 * 
 
134
 <!-- options-end -->
 
135
 * 
 
136
 * @author  fracpete (fracpete at waikato dot ac dot nz)
 
137
 * @version $Revision: 1.3 $
 
138
 * @see Capabilities
 
139
 * @see Capabilities.Capability
 
140
 * @see GenericPropertiesCreator
 
141
 */
 
142
public class FindWithCapabilities 
 
143
implements OptionHandler, CapabilitiesHandler {
 
144
 
 
145
  /** the capabilities to look for */
 
146
  protected Capabilities m_Capabilities = new Capabilities(this);
 
147
 
 
148
  /** the capabilities to look for to "not have" */
 
149
  protected Capabilities m_NotCapabilities = new Capabilities(this);
 
150
 
 
151
  /** the packages to search in */
 
152
  protected Vector m_Packages = new Vector();
 
153
 
 
154
  /** a capabilities handler to retrieve the capabilities from */
 
155
  protected CapabilitiesHandler m_Handler = null;
 
156
 
 
157
  /** a file the capabilities can be based on */
 
158
  protected String m_Filename = "";
 
159
 
 
160
  /** the class index, in case the capabilities are based on a file */
 
161
  protected SingleIndex m_ClassIndex = new SingleIndex();
 
162
 
 
163
  /** the superclass from the GenericPropertiesCreator to retrieve the packages from */
 
164
  protected String m_Superclass = "";
 
165
 
 
166
  /** whether to use the GenericPropertiesCreator with the superclass */
 
167
  protected boolean m_GenericPropertiesCreator = false;
 
168
 
 
169
  /** the classes that matched */
 
170
  protected Vector m_Matches = new Vector();
 
171
 
 
172
  /** the class that didn't match */
 
173
  protected Vector m_Misses = new Vector();
 
174
 
 
175
  /**
 
176
   * Returns an enumeration describing the available options.
 
177
   *
 
178
   * @return an enumeration of all the available options.
 
179
   */
 
180
  public Enumeration listOptions() {
 
181
    Vector result = new Vector();
 
182
 
 
183
    result.addElement(new Option(
 
184
        "", "", 0, 
 
185
        "All class and attribute options can be prefixed with 'not',\n"
 
186
        + "e.g., '-not-numeric-class'. This makes sure that the returned\n"
 
187
        + "schemes 'cannot' handle numeric classes."));
 
188
 
 
189
    result.addElement(new Option(
 
190
        "\tThe minimum number of instances (default 1).",
 
191
        "num-instances", 1, "-num-instances <num>"));
 
192
 
 
193
    result.addElement(new Option(
 
194
        "\tMust handle unray classes.",
 
195
        "unary-class", 0, "-unary-class"));
 
196
 
 
197
    result.addElement(new Option(
 
198
        "\tMust handle binary classes.",
 
199
        "binary-class", 0, "-binary-class"));
 
200
 
 
201
    result.addElement(new Option(
 
202
        "\tMust handle nominal classes.",
 
203
        "nominal-class", 0, "-nominal-class"));
 
204
 
 
205
    result.addElement(new Option(
 
206
        "\tMust handle numeric classes.",
 
207
        "numeric-class", 0, "-numeric-class"));
 
208
 
 
209
    result.addElement(new Option(
 
210
        "\tMust handle string classes.",
 
211
        "string-class", 0, "-string-class"));
 
212
 
 
213
    result.addElement(new Option(
 
214
        "\tMust handle date classes.",
 
215
        "date-class", 0, "-date-class"));
 
216
 
 
217
    result.addElement(new Option(
 
218
        "\tMust handle relational classes.",
 
219
        "relational-class", 0, "-relational-class"));
 
220
 
 
221
    result.addElement(new Option(
 
222
        "\tDoesn't need a class.",
 
223
        "no-class", 0, "-no-class"));
 
224
 
 
225
    result.addElement(new Option(
 
226
        "\tMust handle unary attributes.",
 
227
        "unary-atts", 0, "-unary-atts"));
 
228
 
 
229
    result.addElement(new Option(
 
230
        "\tMust handle binary attributes.",
 
231
        "binary-atts", 0, "-binary-atts"));
 
232
 
 
233
    result.addElement(new Option(
 
234
        "\tMust handle nominal attributes.",
 
235
        "nominal-atts", 0, "-nominal-atts"));
 
236
 
 
237
    result.addElement(new Option(
 
238
        "\tMust handle numeric attributes.",
 
239
        "numeric-atts", 0, "-numeric-atts"));
 
240
 
 
241
    result.addElement(new Option(
 
242
        "\tMust handle string attributes.",
 
243
        "string-atts", 0, "-string-atts"));
 
244
 
 
245
    result.addElement(new Option(
 
246
        "\tMust handle date attributes.",
 
247
        "date-atts", 0, "-date-atts"));
 
248
 
 
249
    result.addElement(new Option(
 
250
        "\tMust handle relational attributes.",
 
251
        "relational-atts", 0, "-relational-atts"));
 
252
 
 
253
    result.addElement(new Option(
 
254
        "\tMust handle multi-instance data.",
 
255
        "only-multiinstance", 0, "-only-multiinstance"));
 
256
 
 
257
    result.addElement(new Option(
 
258
        "\tThe Capabilities handler to base the handling on.\n"
 
259
        + "\tThe other parameters can be used to override the ones\n"
 
260
        + "\tdetermined from the handler. Additional parameters for\n"
 
261
        + "\thandler can be passed on after the '--'.\n"
 
262
        + "\tEither '-W' or '-t' can be used.",
 
263
        "W", 1, "-W <classname>"));
 
264
 
 
265
    result.addElement(new Option(
 
266
        "\tThe dataset to base the capabilities on.\n"
 
267
        + "\tThe other parameters can be used to override the ones\n"
 
268
        + "\tdetermined from the handler.\n"
 
269
        + "\tEither '-t' or '-W' can be used.",
 
270
        "t", 1, "-t <file>"));
 
271
 
 
272
    result.addElement(new Option(
 
273
        "\tThe index of the class attribute, -1 for none.\n"
 
274
        + "\t'first' and 'last' are also valid.\n"
 
275
        + "\tOnly in conjunction with option '-t'.",
 
276
        "c", 1, "-c <num>"));
 
277
 
 
278
    result.addElement(new Option(
 
279
        "\tSuperclass to look for in the packages.\n",
 
280
        "superclass", 1, "-superclass"));
 
281
 
 
282
    result.addElement(new Option(
 
283
        "\tComma-separated list of packages to search in.",
 
284
        "packages", 1, "-packages"));
 
285
 
 
286
    result.addElement(new Option(
 
287
        "\tRetrieves the package list from the GenericPropertiesCreator\n"
 
288
        + "\tfor the given superclass. (overrides -packages <list>).",
 
289
        "generic", 1, "-generic"));
 
290
 
 
291
    result.addElement(new Option(
 
292
        "\tAlso prints the classname that didn't match the criteria.",
 
293
        "misses", 0, "-misses"));
 
294
 
 
295
    return result.elements();
 
296
  }
 
297
 
 
298
  /**
 
299
   * Parses a given list of options. 
 
300
   *
 
301
   * @param options the list of options as an array of strings
 
302
   * @throws Exception if an option is not supported
 
303
   */
 
304
  public void setOptions(String[] options) throws Exception {
 
305
    String                      tmpStr;
 
306
    Class                       cls;
 
307
    CapabilitiesHandler         handler;
 
308
    boolean                     initialized;
 
309
    StringTokenizer             tok;
 
310
    GenericPropertiesCreator    creator;
 
311
    Properties                  props;
 
312
 
 
313
    m_Capabilities = new Capabilities(this);
 
314
    initialized    = false;
 
315
 
 
316
    tmpStr = Utils.getOption('W', options);
 
317
    if (tmpStr.length() != 0) {
 
318
      cls = Class.forName(tmpStr);
 
319
      if (ClassDiscovery.hasInterface(CapabilitiesHandler.class, cls)) {
 
320
        initialized = true;
 
321
        handler = (CapabilitiesHandler) cls.newInstance();
 
322
        if (handler instanceof OptionHandler)
 
323
          ((OptionHandler) handler).setOptions(Utils.partitionOptions(options));
 
324
        setHandler(handler);
 
325
      }
 
326
      else {
 
327
        throw new IllegalArgumentException("Class '" + tmpStr + "' is not a CapabilitiesHandler!");
 
328
      }
 
329
    }
 
330
    else {
 
331
      tmpStr = Utils.getOption('c', options);
 
332
      if (tmpStr.length() != 0)
 
333
        setClassIndex(tmpStr);
 
334
      else
 
335
        setClassIndex("last");
 
336
 
 
337
      tmpStr = Utils.getOption('t', options);
 
338
      setFilename(tmpStr);
 
339
    }
 
340
 
 
341
    tmpStr = Utils.getOption("num-instances", options);
 
342
    if (tmpStr.length() != 0)
 
343
      m_Capabilities.setMinimumNumberInstances(Integer.parseInt(tmpStr));
 
344
    else if (!initialized)
 
345
      m_Capabilities.setMinimumNumberInstances(1);
 
346
 
 
347
    // allowed
 
348
    if (Utils.getFlag("no-class", options))
 
349
      enable(Capability.NO_CLASS);
 
350
    // not allowed
 
351
    if (Utils.getFlag("not-no-class", options))
 
352
      enableNot(Capability.NO_CLASS);
 
353
 
 
354
    if (!m_Capabilities.handles(Capability.NO_CLASS)) {
 
355
      // allowed
 
356
      if (Utils.getFlag("nominal-class", options)) {
 
357
        enable(Capability.NOMINAL_CLASS);
 
358
        disable(Capability.BINARY_CLASS);
 
359
      }
 
360
      if (Utils.getFlag("binary-class", options)) {
 
361
        enable(Capability.BINARY_CLASS);
 
362
        disable(Capability.UNARY_CLASS);
 
363
      }
 
364
      if (Utils.getFlag("unary-class", options))
 
365
        enable(Capability.UNARY_CLASS);
 
366
      if (Utils.getFlag("numeric-class", options))
 
367
        enable(Capability.NUMERIC_CLASS);
 
368
      if (Utils.getFlag("string-class", options))
 
369
        enable(Capability.STRING_CLASS);
 
370
      if (Utils.getFlag("date-class", options))
 
371
        enable(Capability.DATE_CLASS);
 
372
      if (Utils.getFlag("relational-class", options))
 
373
        enable(Capability.RELATIONAL_CLASS);
 
374
    }
 
375
    // not allowed
 
376
    if (Utils.getFlag("not-nominal-class", options)) {
 
377
      enableNot(Capability.NOMINAL_CLASS);
 
378
      disableNot(Capability.BINARY_CLASS);
 
379
    }
 
380
    if (Utils.getFlag("not-binary-class", options)) {
 
381
      enableNot(Capability.BINARY_CLASS);
 
382
      disableNot(Capability.UNARY_CLASS);
 
383
    }
 
384
    if (Utils.getFlag("not-unary-class", options))
 
385
      enableNot(Capability.UNARY_CLASS);
 
386
    if (Utils.getFlag("not-numeric-class", options))
 
387
      enableNot(Capability.NUMERIC_CLASS);
 
388
    if (Utils.getFlag("not-string-class", options))
 
389
      enableNot(Capability.STRING_CLASS);
 
390
    if (Utils.getFlag("not-date-class", options))
 
391
      enableNot(Capability.DATE_CLASS);
 
392
    if (Utils.getFlag("not-relational-class", options))
 
393
      enableNot(Capability.RELATIONAL_CLASS);
 
394
 
 
395
    // allowed
 
396
    if (Utils.getFlag("nominal-atts", options)) {
 
397
      enable(Capability.NOMINAL_ATTRIBUTES);
 
398
      disable(Capability.BINARY_ATTRIBUTES);
 
399
    }
 
400
    if (Utils.getFlag("binary-atts", options)) {
 
401
      enable(Capability.BINARY_ATTRIBUTES);
 
402
      disable(Capability.UNARY_ATTRIBUTES);
 
403
    }
 
404
    if (Utils.getFlag("unary-atts", options))
 
405
      enable(Capability.UNARY_ATTRIBUTES);
 
406
    if (Utils.getFlag("numeric-atts", options))
 
407
      enable(Capability.NUMERIC_ATTRIBUTES);
 
408
    if (Utils.getFlag("string-atts", options))
 
409
      enable(Capability.STRING_ATTRIBUTES);
 
410
    if (Utils.getFlag("date-atts", options))
 
411
      enable(Capability.DATE_ATTRIBUTES);
 
412
    if (Utils.getFlag("relational-atts", options))
 
413
      enable(Capability.RELATIONAL_ATTRIBUTES);
 
414
    // not allowed
 
415
    if (Utils.getFlag("not-nominal-atts", options)) {
 
416
      enableNot(Capability.NOMINAL_ATTRIBUTES);
 
417
      disableNot(Capability.BINARY_ATTRIBUTES);
 
418
    }
 
419
    if (Utils.getFlag("not-binary-atts", options)) {
 
420
      enableNot(Capability.BINARY_ATTRIBUTES);
 
421
      disableNot(Capability.UNARY_ATTRIBUTES);
 
422
    }
 
423
    if (Utils.getFlag("not-unary-atts", options))
 
424
      enableNot(Capability.UNARY_ATTRIBUTES);
 
425
    if (Utils.getFlag("not-numeric-atts", options))
 
426
      enableNot(Capability.NUMERIC_ATTRIBUTES);
 
427
    if (Utils.getFlag("not-string-atts", options))
 
428
      enableNot(Capability.STRING_ATTRIBUTES);
 
429
    if (Utils.getFlag("not-date-atts", options))
 
430
      enableNot(Capability.DATE_ATTRIBUTES);
 
431
    if (Utils.getFlag("not-relational-atts", options))
 
432
      enableNot(Capability.RELATIONAL_ATTRIBUTES);
 
433
 
 
434
    if (Utils.getFlag("only-multiinstance", options))
 
435
      enable(Capability.ONLY_MULTIINSTANCE);
 
436
 
 
437
    tmpStr = Utils.getOption("superclass", options);
 
438
    if (tmpStr.length() != 0)
 
439
      m_Superclass = tmpStr;
 
440
    else
 
441
      throw new IllegalArgumentException("A superclass has to be specified!");
 
442
 
 
443
    tmpStr = Utils.getOption("packages", options);
 
444
    if (tmpStr.length() != 0) {
 
445
      tok        = new StringTokenizer(tmpStr, ",");
 
446
      m_Packages = new Vector();
 
447
      while (tok.hasMoreTokens())
 
448
        m_Packages.add(tok.nextToken());
 
449
    }
 
450
 
 
451
    if (Utils.getFlag("generic", options)) {
 
452
      creator    = new GenericPropertiesCreator();
 
453
      creator.execute(false);
 
454
      props      = creator.getInputProperties();
 
455
      tok        = new StringTokenizer(props.getProperty(m_Superclass), ",");
 
456
      m_Packages = new Vector();
 
457
      while (tok.hasMoreTokens())
 
458
        m_Packages.add(tok.nextToken());
 
459
    }
 
460
  }
 
461
 
 
462
  /**
 
463
   * Gets the current settings of this object.
 
464
   * 
 
465
   * @return an array of strings suitable for passing to setOptions
 
466
   */
 
467
  public String[] getOptions() {
 
468
    Vector      result;
 
469
    String[]    options;
 
470
    int         i;
 
471
 
 
472
    result = new Vector();
 
473
 
 
474
    result.add("-num-instances");
 
475
    result.add("" + m_Capabilities.getMinimumNumberInstances());
 
476
 
 
477
    if (isEnabled(Capability.NO_CLASS)) {
 
478
      result.add("-no-class");
 
479
    }
 
480
    else {
 
481
      if (isEnabled(Capability.UNARY_CLASS))
 
482
        result.add("-unary-class");
 
483
      if (isEnabled(Capability.BINARY_CLASS))
 
484
        result.add("-binary-class");
 
485
      if (isEnabled(Capability.NOMINAL_CLASS))
 
486
        result.add("-nominal-class");
 
487
      if (isEnabled(Capability.NUMERIC_CLASS))
 
488
        result.add("-numeric-class");
 
489
      if (isEnabled(Capability.STRING_CLASS))
 
490
        result.add("-string-class");
 
491
      if (isEnabled(Capability.DATE_CLASS))
 
492
        result.add("-date-class");
 
493
      if (isEnabled(Capability.RELATIONAL_CLASS))
 
494
        result.add("-relational-class");
 
495
    }
 
496
 
 
497
    if (isEnabled(Capability.UNARY_ATTRIBUTES))
 
498
      result.add("-unary-atts");
 
499
    if (isEnabled(Capability.BINARY_ATTRIBUTES))
 
500
      result.add("-binary-atts");
 
501
    if (isEnabled(Capability.NOMINAL_ATTRIBUTES))
 
502
      result.add("-nominal-atts");
 
503
    if (isEnabled(Capability.NUMERIC_ATTRIBUTES))
 
504
      result.add("-numeric-atts");
 
505
    if (isEnabled(Capability.STRING_ATTRIBUTES))
 
506
      result.add("-string-atts");
 
507
    if (isEnabled(Capability.DATE_ATTRIBUTES))
 
508
      result.add("-date-atts");
 
509
    if (isEnabled(Capability.RELATIONAL_ATTRIBUTES))
 
510
      result.add("-relational-atts");
 
511
 
 
512
    // not allowed
 
513
    if (isEnabledNot(Capability.NO_CLASS))
 
514
      result.add("-not-no-class");
 
515
    if (isEnabledNot(Capability.UNARY_CLASS))
 
516
      result.add("-not-unary-class");
 
517
    if (isEnabledNot(Capability.BINARY_CLASS))
 
518
      result.add("-not-binary-class");
 
519
    if (isEnabledNot(Capability.NOMINAL_CLASS))
 
520
      result.add("-not-nominal-class");
 
521
    if (isEnabledNot(Capability.NUMERIC_CLASS))
 
522
      result.add("-not-numeric-class");
 
523
    if (isEnabledNot(Capability.STRING_CLASS))
 
524
      result.add("-not-string-class");
 
525
    if (isEnabledNot(Capability.DATE_CLASS))
 
526
      result.add("-not-date-class");
 
527
    if (isEnabledNot(Capability.RELATIONAL_CLASS))
 
528
      result.add("-not-relational-class");
 
529
 
 
530
    if (isEnabledNot(Capability.UNARY_ATTRIBUTES))
 
531
      result.add("-not-unary-atts");
 
532
    if (isEnabledNot(Capability.BINARY_ATTRIBUTES))
 
533
      result.add("-not-binary-atts");
 
534
    if (isEnabledNot(Capability.NOMINAL_ATTRIBUTES))
 
535
      result.add("-not-nominal-atts");
 
536
    if (isEnabledNot(Capability.NUMERIC_ATTRIBUTES))
 
537
      result.add("-not-numeric-atts");
 
538
    if (isEnabledNot(Capability.STRING_ATTRIBUTES))
 
539
      result.add("-not-string-atts");
 
540
    if (isEnabledNot(Capability.DATE_ATTRIBUTES))
 
541
      result.add("-not-date-atts");
 
542
    if (isEnabledNot(Capability.RELATIONAL_ATTRIBUTES))
 
543
      result.add("-not-relational-atts");
 
544
 
 
545
    if (isEnabled(Capability.ONLY_MULTIINSTANCE))
 
546
      result.add("-only-multi-instance");
 
547
 
 
548
    if (getHandler() != null) {
 
549
      result.add("-W");
 
550
      result.add(getHandler().getClass().getName());
 
551
      if (getHandler() instanceof OptionHandler) {
 
552
        result.add("--");
 
553
        options = ((OptionHandler) getHandler()).getOptions();
 
554
        for (i = 0; i < options.length; i++)
 
555
          result.add(options[i]);
 
556
      }
 
557
    }
 
558
    else if (getFilename().length() != 0) {
 
559
      result.add("-t");
 
560
      result.add(getFilename());
 
561
      result.add("-c");
 
562
      result.add(m_ClassIndex.getSingleIndex());
 
563
    }
 
564
 
 
565
    if (m_Superclass.length() != 0) {
 
566
      result.add("-superclass");
 
567
      result.add(m_Superclass);
 
568
    }
 
569
    else {
 
570
      result.add("-packages");
 
571
      result.add(m_Packages.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
 
572
    }
 
573
 
 
574
    return (String[]) result.toArray(new String[result.size()]);
 
575
  }
 
576
 
 
577
  /**
 
578
   * sets the Capabilities handler to generate the data for
 
579
   */
 
580
  public void setHandler(CapabilitiesHandler value) {
 
581
    m_Handler = value;
 
582
    setCapabilities(m_Handler.getCapabilities());
 
583
  }
 
584
 
 
585
  /**
 
586
   * returns the current set CapabilitiesHandler to generate the dataset
 
587
   * for, can be null
 
588
   */
 
589
  public CapabilitiesHandler getHandler() {
 
590
    return m_Handler;
 
591
  }
 
592
 
 
593
  /**
 
594
   * Sets the dataset filename to base the capabilities on. It immediately
 
595
   * loads the dataset and retrieves the capabilities from it.
 
596
   */
 
597
  public void setFilename(String value) {
 
598
    Instances           insts;
 
599
 
 
600
    m_Filename = value;
 
601
 
 
602
    if (m_Filename.length() != 0) {
 
603
      try {
 
604
        insts  = new Instances(new BufferedReader(new FileReader(m_Filename)));
 
605
        m_ClassIndex.setUpper(insts.numAttributes());
 
606
        insts.setClassIndex(Integer.parseInt(getClassIndex()) - 1);
 
607
 
 
608
        setCapabilities(Capabilities.forInstances(insts));
 
609
      }
 
610
      catch (Exception e) {
 
611
        e.printStackTrace();
 
612
      }
 
613
    }
 
614
  }
 
615
 
 
616
  /**
 
617
   * returns the current filename for the dataset to base the capabilities on
 
618
   */
 
619
  public String getFilename() {
 
620
    return m_Filename;
 
621
  }
 
622
 
 
623
  /**
 
624
   * sets the class index, -1 for none, first and last are also valid
 
625
   */
 
626
  public void setClassIndex(String value) {
 
627
    if (value.equals("-1"))
 
628
      m_ClassIndex = null;
 
629
    else
 
630
      m_ClassIndex = new SingleIndex(value);
 
631
  }
 
632
 
 
633
  /**
 
634
   * returns the current current class index, -1 if no class attribute
 
635
   */
 
636
  public String getClassIndex() {
 
637
    if (m_ClassIndex == null)
 
638
      return "-1";
 
639
    else
 
640
      return "" + m_ClassIndex.getIndex();
 
641
  }
 
642
 
 
643
  /**
 
644
   * enables the given capability
 
645
   * 
 
646
   * @param c           the capability to enable
 
647
   */
 
648
  public void enable(Capability c) {
 
649
    m_Capabilities.enable(c);
 
650
  }
 
651
 
 
652
  /**
 
653
   * whether the given capability is enabled
 
654
   * 
 
655
   * @param c           the capability to enable
 
656
   * @return            true if the capability is enabled
 
657
   */
 
658
  public boolean isEnabled(Capability c) {
 
659
    return m_Capabilities.handles(c);
 
660
  }
 
661
 
 
662
  /**
 
663
   * disables the given capability
 
664
   * 
 
665
   * @param c           the capability to disable
 
666
   */
 
667
  public void disable(Capability c) {
 
668
    m_Capabilities.disable(c);
 
669
  }
 
670
 
 
671
  /**
 
672
   * enables the given "not to have" capability
 
673
   * 
 
674
   * @param c           the capability to enable
 
675
   */
 
676
  public void enableNot(Capability c) {
 
677
    m_NotCapabilities.enable(c);
 
678
  }
 
679
 
 
680
  /**
 
681
   * whether the given "not to have" capability is enabled
 
682
   * 
 
683
   * @param c           the capability to enable
 
684
   * @return            true if the capability is enabled
 
685
   */
 
686
  public boolean isEnabledNot(Capability c) {
 
687
    return m_NotCapabilities.handles(c);
 
688
  }
 
689
 
 
690
  /**
 
691
   * disables the given "not to have" capability
 
692
   * 
 
693
   * @param c           the capability to disable
 
694
   */
 
695
  public void disableNot(Capability c) {
 
696
    m_NotCapabilities.disable(c);
 
697
  }
 
698
 
 
699
  /**
 
700
   * returns true if the given capability can be handled
 
701
   * 
 
702
   * @param c           the capability to check
 
703
   * @return            true if the capability can be handled
 
704
   */
 
705
  public boolean handles(Capability c) {
 
706
    return m_Capabilities.handles(c);
 
707
  }
 
708
 
 
709
  /**
 
710
   * The capabilities to search for.
 
711
   *
 
712
   * @return            the capabilities to search for
 
713
   * @see               Capabilities
 
714
   */
 
715
  public Capabilities getCapabilities() {
 
716
    return m_Capabilities;
 
717
  }
 
718
 
 
719
  /**
 
720
   * Uses the given Capabilities for the search.
 
721
   * 
 
722
   * @param c           the capabilities to use for the search
 
723
   */
 
724
  public void setCapabilities(Capabilities c) {
 
725
    m_Capabilities = (Capabilities) c.clone();
 
726
  }
 
727
 
 
728
  /**
 
729
   * The "not to have" capabilities to search for.
 
730
   *
 
731
   * @return            the capabilities to search for
 
732
   * @see               Capabilities
 
733
   */
 
734
  public Capabilities getNotCapabilities() {
 
735
    return m_NotCapabilities;
 
736
  }
 
737
 
 
738
  /**
 
739
   * Uses the given "not to have" Capabilities for the search.
 
740
   * 
 
741
   * @param c           the capabilities to use for the search
 
742
   */
 
743
  public void setNotCapabilities(Capabilities c) {
 
744
    m_NotCapabilities = (Capabilities) c.clone();
 
745
  }
 
746
 
 
747
  /**
 
748
   * returns the matches from the last find call
 
749
   * 
 
750
   * @return            the matching classname from the last find run
 
751
   */
 
752
  public Vector getMatches() {
 
753
    return m_Matches;
 
754
  }
 
755
 
 
756
  /**
 
757
   * returns the misses from the last find call
 
758
   * 
 
759
   * @return            the classnames that didn't match from the last find run
 
760
   */
 
761
  public Vector getMisses() {
 
762
    return m_Misses;
 
763
  }
 
764
 
 
765
  /**
 
766
   * returns a list with all the classnames that fit the criteria
 
767
   * 
 
768
   * @return            contains all classnames that fit the criteria
 
769
   */
 
770
  public Vector find() {
 
771
    Vector              list;
 
772
    int                 i;
 
773
    Class               cls;
 
774
    Object              obj;
 
775
    CapabilitiesHandler handler;
 
776
    boolean             fits;
 
777
    Capabilities        caps;
 
778
 
 
779
    m_Matches = new Vector();
 
780
    m_Misses  = new Vector();
 
781
 
 
782
    list = ClassDiscovery.find(m_Superclass, (String[]) m_Packages.toArray(new String[m_Packages.size()]));
 
783
    for (i = 0; i < list.size(); i++) {
 
784
      try {
 
785
        cls = Class.forName((String) list.get(i));
 
786
        obj = cls.newInstance();
 
787
 
 
788
        // exclude itself
 
789
        if (cls == this.getClass())
 
790
          continue;
 
791
 
 
792
        // really a CapabilitiesHandler?
 
793
        if (!(obj instanceof CapabilitiesHandler))
 
794
          continue;
 
795
 
 
796
        // check capabilities enumeration
 
797
        handler = (CapabilitiesHandler) obj;
 
798
        caps    = handler.getCapabilities();
 
799
        fits    = true;
 
800
        for (Capability cap: Capability.values()) {
 
801
          if (m_Capabilities.handles(cap)) {
 
802
            if (!(caps.handles(cap))) {
 
803
              fits = false;
 
804
              break;
 
805
            }
 
806
          }
 
807
        }
 
808
        if (!fits) {
 
809
          m_Misses.add(list.get(i));
 
810
          continue;
 
811
        }
 
812
 
 
813
        // check "not" list
 
814
        for (Capability cap: Capability.values()) {
 
815
          if (m_NotCapabilities.handles(cap)) {
 
816
            if ((caps.handles(cap))) {
 
817
              fits = false;
 
818
              break;
 
819
            }
 
820
          }
 
821
        }
 
822
        if (!fits) {
 
823
          m_Misses.add(list.get(i));
 
824
          continue;
 
825
        }
 
826
 
 
827
        // other stuff
 
828
        if (caps.getMinimumNumberInstances() > m_Capabilities.getMinimumNumberInstances()) {
 
829
          m_Misses.add(list.get(i));
 
830
          continue;
 
831
        }
 
832
 
 
833
        // matches all criteria!
 
834
        m_Matches.add(list.get(i));
 
835
      }
 
836
      catch (Exception e) {
 
837
        // ignore
 
838
      }
 
839
    }
 
840
 
 
841
    return m_Matches;
 
842
  }
 
843
 
 
844
  /**
 
845
   * Executes the location of classes with parameters from the commandline.
 
846
   * 
 
847
   * @param args        the commandline parameters
 
848
   */
 
849
  public static void main(String[] args) {
 
850
    FindWithCapabilities        find;
 
851
    Vector                      list;
 
852
    String                      result;
 
853
    int                         i;
 
854
    boolean                     printMisses;
 
855
    Iterator                    iter;
 
856
    boolean                     first;
 
857
 
 
858
    printMisses = false;
 
859
 
 
860
    try {
 
861
      find = new FindWithCapabilities();
 
862
 
 
863
      try {
 
864
        printMisses = Utils.getFlag("misses", args);
 
865
        find.setOptions(args);
 
866
        Utils.checkForRemainingOptions(args);
 
867
      } 
 
868
      catch (Exception ex) {
 
869
        result = ex.getMessage() + "\n\n" + find.getClass().getName().replaceAll(".*\\.", "") + " Options:\n\n";
 
870
        Enumeration enm = find.listOptions();
 
871
        while (enm.hasMoreElements()) {
 
872
          Option option = (Option) enm.nextElement();
 
873
          result += option.synopsis() + "\n" + option.description() + "\n";
 
874
        }
 
875
        throw new Exception(result);
 
876
      }
 
877
 
 
878
      System.out.println("\nSearching for the following Capabilities:");
 
879
      // allowed
 
880
      System.out.print("- allowed: ");
 
881
      iter  = find.getCapabilities().capabilities();
 
882
      first = true;
 
883
      while (iter.hasNext()) {
 
884
        if (!first)
 
885
          System.out.print(", ");
 
886
        first = false;
 
887
        System.out.print(iter.next());
 
888
      }
 
889
      System.out.println();
 
890
      // not allowed
 
891
      System.out.print("- not allowed: ");
 
892
      iter  = find.getNotCapabilities().capabilities();
 
893
      first = true;
 
894
      if (iter.hasNext()) {
 
895
        while (iter.hasNext()) {
 
896
          if (!first)
 
897
            System.out.print(", ");
 
898
          first = false;
 
899
          System.out.print(iter.next());
 
900
        }
 
901
        System.out.println();
 
902
      }
 
903
      else {
 
904
        System.out.println("-");
 
905
      }
 
906
 
 
907
      find.find();
 
908
 
 
909
      // matches
 
910
      list = find.getMatches();
 
911
      if (list.size() == 1)
 
912
        System.out.println("\nFound " + list.size() + " class that matched the criteria:\n");
 
913
      else
 
914
        System.out.println("\nFound " + list.size() + " classes that matched the criteria:\n");
 
915
      for (i = 0; i < list.size(); i++)
 
916
        System.out.println(list.get(i));
 
917
 
 
918
      // misses
 
919
      if (printMisses) {
 
920
        list = find.getMisses();
 
921
        if (list.size() == 1)
 
922
          System.out.println("\nFound " + list.size() + " class that didn't match the criteria:\n");
 
923
        else
 
924
          System.out.println("\nFound " + list.size() + " classes that didn't match the criteria:\n");
 
925
        for (i = 0; i < list.size(); i++)
 
926
          System.out.println(list.get(i));
 
927
      }
 
928
      
 
929
      System.out.println();
 
930
    } 
 
931
    catch (Exception ex) {
 
932
      System.err.println(ex.getMessage());
 
933
    }
 
934
  }
 
935
}