PCollectionList implements PInput, POutput { public static <T> PCollectionList<T> of(PCollection<T> pc) { return new PCollectionList<T>(pc.getPipeline()).and(pc); } PCollectionList(Pipeline pipeline);   PCollectionList(Pipeline pipeline, List<TaggedPValue> values); static PCollectionList<T> empty(Pipeline pipeline); static PCollectionList<T> of(PCollection<T> pc); static PCollectionList<T> of(Iterable<PCollection<T>> pcs); PCollectionList<T> and(PCollection<T> pc); PCollectionList<T> and(Iterable<PCollection<T>> pcs); int size(); PCollection<T> get(int index); List<PCollection<T>> getAll(); OutputT apply(PTransform<PCollectionList<T>, OutputT> t); OutputT apply(
      String name, PTransform<PCollectionList<T>, OutputT> t); @Override Pipeline getPipeline(); @Override Map<TupleTag<?>, PValue> expand(); @Override void finishSpecifyingOutput(
      String transformName, PInput input, PTransform<?, ?> transform); @Override boolean equals(@Nullable Object other); @Override int hashCode();  }
@Test public void testEmptyListFailure() { try { PCollectionList.of(Collections.<PCollection<String>>emptyList()); fail("should have failed"); } catch (IllegalArgumentException exn) { assertThat( exn.toString(), containsString( "must either have a non-empty list of PCollections, " + "or must first call empty(Pipeline)")); } }