class PacketHeaderConstraints {

  @Nullable
  @VisibleForTesting
  static IntegerSpace resolvePorts(
      @Nullable IntegerSpace ports, @Nullable Set<Application> applications) {
    @Nullable
    IntegerSpace portsFromApplications =
        firstNonNull(applications, ImmutableSet.of()).stream()
            .filter(application -> application instanceof PortsApplication)
            .flatMap(application -> ((PortsApplication) application).getPorts().stream())
            .map(IntegerSpace::of)
            .reduce(IntegerSpace::union)
            .orElse(null);
    return intersectNullable(ports, portsFromApplications);
  }

  private  PacketHeaderConstraints(
      @Nullable IntegerSpace dscps,
      @Nullable IntegerSpace ecns,
      @Nullable IntegerSpace packetLengths,
      @Nullable IntegerSpace fragmentOffsets,
      @Nullable Set<IpProtocol> ipProtocols,
      @Nullable String srcIp,
      @Nullable String dstIp,
      @Nullable IntegerSpace icmpCode,
      @Nullable IntegerSpace icmpType,
      @Nullable IntegerSpace srcPorts,
      @Nullable IntegerSpace dstPorts,
      @Nullable String applications,
      @Nullable Set<TcpFlagsMatchConditions> tcpFlags);

}