Exemple #1
0
  @Override
  public Iterator<T> iterator() {
    final ArrayDeque<T> ts = new ArrayDeque<>();

    SnocList<T> current = this;
    while (true) {
      ts.push(current.last);

      if (current.init.isPresent()) {
        current = current.init.get();
      } else {
        break;
      }
    }

    return ts.iterator();
  }
Exemple #2
0
  /**
   * Parse command line options.
   *
   * @param params command line parameters
   * @return -1 to proceed, otherwise process exit value
   */
  public int parseOptions(ArrayDeque<String> params) {

    // Special logic to automate the demo when no flags are given
    if (params.isEmpty() && DEMO_XML_FILE.exists() && DEMO_SUBDIR.exists()) {
      params.add("--xml");
      params.add(DEMO_XML_FILE.toString());
      params.add("--classpath");
      params.add(DEMO_SUBDIR.toString());
      params.add("--model-pkg");
      params.add("org.jsimpledb.demo");
      final StringBuilder buf = new StringBuilder();
      for (String param : params) buf.append(' ').append(param);
      System.err.println(
          this.getName()
              + ": automatically configuring demo database using the following flags:\n "
              + buf);
    }

    // Parse --classpath options prior to searching classpath for key/value implementations
    for (Iterator<String> i = params.iterator(); i.hasNext(); ) {
      final String param = i.next();
      if (param.equals("-cp") || param.equals("--classpath")) {
        i.remove();
        if (!i.hasNext()) this.usageError();
        if (!this.appendClasspath(i.next())) return 1;
        i.remove();
      }
    }

    // Parse (and remove) options supported by key/value implementations
    for (KVImplementation availableKVImplementation : KVImplementation.getImplementations()) {
      final Object config;
      try {
        config = availableKVImplementation.parseCommandLineOptions(params);
      } catch (IllegalArgumentException e) {
        System.err.println(this.getName() + ": " + (e.getMessage() != null ? e.getMessage() : e));
        return 1;
      }
      if (config != null) this.kvConfigMap.put(availableKVImplementation, config);
    }

    // Parse options supported by this class
    final LinkedHashSet<String> modelPackages = new LinkedHashSet<>();
    final LinkedHashSet<String> typePackages = new LinkedHashSet<>();
    while (!params.isEmpty() && params.peekFirst().startsWith("-")) {
      final String option = params.removeFirst();
      if (option.equals("-h") || option.equals("--help")) {
        this.usageMessage();
        return 0;
      } else if (option.equals("-ro") || option.equals("--read-only")) this.readOnly = true;
      else if (option.equals("--verbose")) this.verbose = true;
      else if (option.equals("-v") || option.equals("--schema-version")) {
        if (params.isEmpty()) this.usageError();
        final String vstring = params.removeFirst();
        try {
          this.schemaVersion = Integer.parseInt(vstring);
          if (this.schemaVersion < 0)
            throw new IllegalArgumentException("schema version is negative");
        } catch (Exception e) {
          System.err.println(
              this.getName() + ": invalid schema version `" + vstring + "': " + e.getMessage());
          return 1;
        }
      } else if (option.equals("--model-pkg")) {
        if (params.isEmpty()) this.usageError();
        modelPackages.add(params.removeFirst());
      } else if (option.equals("--type-pkg")) {
        if (params.isEmpty()) this.usageError();
        typePackages.add(params.removeFirst());
      } else if (option.equals("-p") || option.equals("--pkg")) {
        if (params.isEmpty()) this.usageError();
        final String packageName = params.removeFirst();
        modelPackages.add(packageName);
        typePackages.add(packageName);
      } else if (option.equals("--new-schema")) this.allowNewSchema = true;
      else if (option.equals("--")) break;
      else if (!this.parseOption(option, params)) {
        System.err.println(this.getName() + ": unknown option `" + option + "'");
        this.usageError();
        return 1;
      }
    }

    // Decode what key/value implementations where specified and how they nest, if at all
    final Iterator<KVImplementation> i = this.kvConfigMap.keySet().iterator();
    switch (this.kvConfigMap.size()) {
      case 0:
        System.err.println(
            this.getName() + ": no key/value database specified; use one of `--arraydb', etc.");
        this.usageError();
        return 1;

      case 1:
        this.kvImplementation = i.next();
        final Object config = this.kvConfigMap.get(this.kvImplementation);
        if (this.kvImplementation.requiresAtomicKVStore(config)
            || this.kvImplementation.requiresKVDatabase(config)) {
          System.err.println(
              this.getName()
                  + ": "
                  + this.kvImplementation.getDescription(config)
                  + " requires the configuration of an underlying key/value technology; use one of `--arraydb', etc.");
          return 1;
        }
        break;

      case 2:

        // Put them in proper order: inner first, outer second
        final KVImplementation[] kvis = new KVImplementation[] {i.next(), i.next()};
        final Object[] configs =
            new Object[] {this.kvConfigMap.get(kvis[0]), this.kvConfigMap.get(kvis[1])};
        if (kvis[0].requiresAtomicKVStore(configs[0]) || kvis[0].requiresKVDatabase(configs[0])) {
          Collections.reverse(Arrays.asList(kvis));
          Collections.reverse(Arrays.asList(configs));
        }

        // Sanity check nesting requirements
        if ((kvis[0].requiresAtomicKVStore(configs[0]) || kvis[0].requiresKVDatabase(configs[0]))
            || !(kvis[1].requiresAtomicKVStore(configs[1])
                || kvis[1].requiresKVDatabase(configs[1]))) {
          System.err.println(
              this.getName()
                  + ": incompatible combination of "
                  + kvis[0].getDescription(configs[0])
                  + " and "
                  + kvis[1].getDescription(configs[1]));
          return 1;
        }

        // Nest them as required
        if (kvis[1].requiresAtomicKVStore(configs[1])) this.requiredAtomicKVStore = kvis[0];
        else this.requiredKVDatabase = kvis[0];
        this.kvImplementation = kvis[1];
        break;

      default:
        System.err.println(this.getName() + ": too many key/value store(s) specified");
        return 1;
    }

    // Scan for model and type classes
    final LinkedHashSet<String> emptyPackages = new LinkedHashSet<>();
    emptyPackages.addAll(modelPackages);
    emptyPackages.addAll(typePackages);
    for (String packageName : modelPackages) {
      if (this.scanModelClasses(packageName) > 0) emptyPackages.remove(packageName);
    }
    for (String packageName : typePackages) {
      if (this.scanTypeClasses(packageName) > 0) emptyPackages.remove(packageName);
    }

    // Warn if we didn't find anything
    for (String packageName : emptyPackages) {
      final boolean isModel = modelPackages.contains(packageName);
      final boolean isType = typePackages.contains(packageName);
      if (isModel && isType)
        this.log.warn(
            "no Java model or custom FieldType classes found under package `" + packageName + "'");
      else if (isModel)
        this.log.warn("no Java model classes found under package `" + packageName + "'");
      else this.log.warn("no custom FieldType classes found under package `" + packageName + "'");
    }

    // Done
    return -1;
  }