All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.rinde.rinsim.io.FileProviderCli Maven / Gradle / Ivy

There is a newer version: 4.4.6
Show newest version
/*
 * Copyright (C) 2011-2017 Rinde van Lon, imec-DistriNet, KU Leuven
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.rinde.rinsim.io;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newLinkedHashMap;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

import com.github.rinde.rinsim.cli.ArgHandler;
import com.github.rinde.rinsim.cli.ArgumentParser;
import com.github.rinde.rinsim.cli.Menu;
import com.github.rinde.rinsim.cli.Option;
import com.github.rinde.rinsim.cli.Option.OptionArg;
import com.github.rinde.rinsim.io.FileProvider.Builder;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;

/**
 * Defines a command-line interface for {@link FileProvider}.
 * @author Rinde van Lon
 */
public final class FileProviderCli {

  private static final ArgHandler> ADD =
    new ArgHandler>() {
      @Override
      public void execute(FileProvider.Builder ref,
          Optional> value) {
        final List paths = value.get();
        for (final String p : paths) {
          ref.add(Paths.get(p));
        }
      }
    };

  private static final ArgHandler FILTER =
    new ArgHandler() {
      @Override
      public void execute(FileProvider.Builder ref, Optional value) {
        ref.filter(value.get());
      }
    };

  private FileProviderCli() {}

  static Optional execute(FileProvider.Builder builder, String[] args) {
    return createDefaultMenu(builder).execute(args);
  }

  /**
   * Creates the default {@link com.github.rinde.rinsim.cli.Menu.Builder} for
   * creating the {@link Menu} instances.
   * @param builder The {@link FileProvider.Builder} that should be controlled
   *          via CLI.
   * @return The new menu builder.
   */
  public static Menu createDefaultMenu(
      FileProvider.Builder builder) {
    final Map pathMap = createPathMap(builder);
    final Menu.Builder cliBuilder = Menu.builder()
      .addHelpOption("h", "help", "Print this message")
      .add(createAddOption(), builder, ADD)
      .add(createFilterOption(builder), builder, FILTER);

    if (!pathMap.isEmpty()) {
      cliBuilder
        .openGroup()
        .add(createIncludeOption(pathMap, builder), builder,
          new IncludeHandler(pathMap))
        .add(createExcludeOption(pathMap, builder), builder,
          new ExcludeHandler(pathMap))
        .closeGroup();
    }
    return cliBuilder.build();
  }

  private static ImmutableMap createPathMap(Builder b) {
    final Map pathMap = newLinkedHashMap();
    for (int i = 0; i < b.paths.size(); i++) {
      pathMap.put("p" + i, b.paths.get(i));
    }
    return ImmutableMap.copyOf(pathMap);
  }

  static OptionArg> createIncludeOption(
      Map pathMap,
      Builder builder) {
    final StringBuilder sb = new StringBuilder();
    printPathOptions(pathMap, sb);
    sb.append("This option can not be used together with --exclude.");
    return Option
      .builder("i", ArgumentParser.stringListParser())
      .longName("include")
      .description(sb.toString())
      .build();
  }

  static void printPathOptions(Map pathMap, StringBuilder sb) {
    sb.append(
      "The following paths can be excluded. If this option is not used all "
        + "paths are automatically "
        + "included. The current paths:\n");
    Joiner.on("\n").withKeyValueSeparator(" = ").appendTo(sb, pathMap);
    sb.append("\nThe options should be given as a comma ',' separated list.");
  }

  static OptionArg> createExcludeOption(
      Map pathMap,
      Builder builder) {
    final StringBuilder sb = new StringBuilder();
    printPathOptions(pathMap, sb);
    sb.append("This option can not be used together with --include.");
    return Option.builder("e", ArgumentParser.stringListParser())
      .longName("exclude")
      .description(sb.toString())
      .build();
  }

  static OptionArg> createAddOption() {
    return Option
      .builder("a", ArgumentParser.stringListParser())
      .longName("add")
      .description(
        "Adds the specified paths. A path may be a file or a directory. "
          + "If it is a directory it will be searched recursively.")
      .build();
  }

  static OptionArg createFilterOption(Builder ref) {
    return Option
      .builder("f", ArgumentParser.stringParser())
      .longName("filter")
      .description(
        "Sets a filter of which paths to include. The filter is a string "
          + "of the form 'syntax:pattern', where 'syntax' is either "
          + "'glob' or 'regex'.  The current filter is '"
          + ref.pathPredicate
          + "', there are "
          + ref.getNumberOfFiles()
          + " files that satisfy this filter. For more information about"
          + " the supported syntax please review the documentation of the"
          + " java.nio.file.FileSystem.getPathMatcher(String) method.")
      .build();
  }

  abstract static class PathSelectorHandler implements
      ArgHandler> {
    final Map pathMap;

    PathSelectorHandler(Map map) {
      pathMap = map;
    }

    @Override
    public void execute(Builder ref, Optional> value) {
      final List keys = value.get();
      final List paths = newArrayList();
      checkArgument(
        keys.size() <= pathMap.size(),
        "Too many paths, at most %s paths can be selected.",
        pathMap.size());
      for (final String k : keys) {
        checkArgument(pathMap.containsKey(k),
          "The key '%s' is not valid. Valid keys: %s.", k, pathMap.keySet());
        paths.add(pathMap.get(k));
      }
      execute(ref, paths);
    }

    abstract void execute(Builder ref, List paths);
  }

  static class IncludeHandler extends PathSelectorHandler {
    IncludeHandler(Map map) {
      super(map);
    }

    @Override
    void execute(Builder ref, List paths) {
      ref.paths.retainAll(paths);
    }
  }

  static class ExcludeHandler extends PathSelectorHandler {
    ExcludeHandler(Map map) {
      super(map);
    }

    @Override
    void execute(Builder ref, List paths) {
      ref.paths.removeAll(paths);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy