class PrivateSetDemo implements Application<List<List<Boolean>>, ProtocolBuilderBinary> {

  public static <T extends ResourcePoolImpl> void main(String[] args) throws IOException {
    CmdLineUtil<T, ProtocolBuilderBinary> util = new CmdLineUtil<>();
    Boolean[] key;
    int[] inputs;

    util.addOption(Option.builder("key")
        .desc("The key to use for encryption. " + "A " + INPUT_LENGTH
            + " char hex string. Required for player 1 and 2. "
            + "For both players this is interpreted as the AES key. ")
        .longOpt("key").hasArg().build());

    util.addOption(Option.builder("in")
        .desc("The list of integers to use as input for the set intersection problem. "
            + "A comma separated list of integers. Required for player 1 and 2. "
            + "The lists must be of equal length for each player. ")
        .longOpt("input").hasArg().build());

    CommandLine cmd = util.parse(args);
    NetworkConfiguration networkConfiguration = util.getNetworkConfiguration();

    // Get and validate the AES specific input.
    if (networkConfiguration.getMyId() == 1 || networkConfiguration.getMyId() == 2) {
      if (!cmd.hasOption("in")) {
        throw new IllegalArgumentException("Player 1 and 2 must submit inputs");
      }
      if (!cmd.hasOption("key") || cmd.getOptionValue("key").length() != INPUT_LENGTH) {
        throw new IllegalArgumentException("Player 1 and 2 must submit keys "
            + "(hex string of length " + INPUT_LENGTH + ")");
      }
      key = ByteAndBitConverter.toBoolean(cmd.getOptionValue("key"));

      for (Option o : cmd.getOptions()) {
        System.out.println("option: " + o.getOpt() + " : " + o.getValue());
      }
      inputs = arrayFromString(cmd.getOptionValue("in"));

    } else {
      throw new IllegalArgumentException("Only 2 parties are supported");
    }

    // Do the secure computation using config from property files.
    PrivateSetDemo privateSetDemo = new PrivateSetDemo(networkConfiguration.getMyId(), key, inputs);
    ProtocolSuite<T, ProtocolBuilderBinary> psConf = util.getProtocolSuite();
    SecureComputationEngine<T, ProtocolBuilderBinary> sce =
        new SecureComputationEngineImpl<>(psConf, util.getEvaluator());

    List<List<Boolean>> psiResult;
    T resourcePool = util.getResourcePool();
    psiResult = sce.runApplication(privateSetDemo, resourcePool, util.getNetwork());
    util.closeNetwork();
    // Print result.
    System.out.println("The resulting ciphertexts are:");
    boolean[][] res = new boolean[psiResult.size()][BLOCK_SIZE];
    for (int j = 0; j < psiResult.size(); j++) {
      for (int i = 0; i < BLOCK_SIZE; i++) {
        res[j][i] = psiResult.get(j).get(i);
      }
      System.out.println("result(" + j + "): " + ByteAndBitConverter.toHex(res[j]));
    }

  }

  public  PrivateSetDemo(int id, Boolean[] key, int[] set);

}