public static Set<Port> parse(List<String> ports) throws NumberFormatException {
    Set<Port> result = new HashSet<>();

    for (String port : ports) {
      Matcher matcher = portPattern.matcher(port);

      if (!matcher.matches()) {
        throw new NumberFormatException(
            "Invalid port configuration: '"
                + port
                + "'. Make sure the port is a single number or a range of two numbers separated "
                + "with a '-', with or without protocol specified (e.g. '<portNum>/tcp' or "
                + "'<portNum>/udp').");
      }

      // Parse protocol
      int min = Integer.parseInt(matcher.group(1));
      int max = min;
      if (!Strings.isNullOrEmpty(matcher.group(2))) {
        max = Integer.parseInt(matcher.group(2));
      }
      String protocol = matcher.group(3);

      // Error if configured as 'max-min' instead of 'min-max'
      if (min > max) {
        throw new NumberFormatException(
            "Invalid port range '" + port + "'; smaller number must come first.");
      }

      // Warn for possibly invalid port numbers
      if (min < 1 || max > 65535) {
        throw new NumberFormatException(
            "Port number '" + port + "' is out of usual range (1-65535).");
      }

      for (int portNumber = min; portNumber <= max; portNumber++) {
        result.add(Port.parseProtocol(portNumber, protocol));
      }
    }

    return result;
  }
@Test
  public void testParse() {
    List<String> goodInputs =
        Arrays.asList("1000", "2000-2003", "3000-3000", "4000/tcp", "5000/udp", "6000-6002/udp");
    ImmutableSet<Port> expected =
        new ImmutableSet.Builder<Port>()
            .add(
                Port.tcp(1000),
                Port.tcp(2000),
                Port.tcp(2001),
                Port.tcp(2002),
                Port.tcp(2003),
                Port.tcp(3000),
                Port.tcp(4000),
                Port.udp(5000),
                Port.udp(6000),
                Port.udp(6001),
                Port.udp(6002))
            .build();
    Set<Port> result = Ports.parse(goodInputs);
    Assert.assertEquals(expected, result);

    List<String> badInputs = Arrays.asList("abc", "/udp", "1000/abc", "a100/tcp", "20/udpabc");
    for (String input : badInputs) {
      try {
        Ports.parse(Collections.singletonList(input));
        Assert.fail();
      } catch (NumberFormatException ex) {
        Assert.assertEquals(
            "Invalid port configuration: '"
                + input
                + "'. Make sure the port is a single number or a range of two numbers separated "
                + "with a '-', with or without protocol specified (e.g. '<portNum>/tcp' or "
                + "'<portNum>/udp').",
            ex.getMessage());
      }
    }

    try {
      Ports.parse(Collections.singletonList("4002-4000"));
      Assert.fail();
    } catch (NumberFormatException ex) {
      Assert.assertEquals(
          "Invalid port range '4002-4000'; smaller number must come first.", ex.getMessage());
    }

    badInputs = Arrays.asList("0", "70000", "0-400", "1-70000");
    for (String input : badInputs) {
      try {
        Ports.parse(Collections.singletonList(input));
        Assert.fail();
      } catch (NumberFormatException ex) {
        Assert.assertEquals(
            "Port number '" + input + "' is out of usual range (1-65535).", ex.getMessage());
      }
    }
  }