public void encode()

in sdk/src/main/java/com/google/cloud/dataflow/sdk/coders/Coder.java [98:269]


  public void encode(T value, OutputStream outStream, Context context)
      throws CoderException, IOException;

  /**
   * Decodes a value of type {@code T} from the given input stream in
   * the given context.  Returns the decoded value.
   *
   * @throws IOException if reading from the {@code InputStream} fails
   * for some reason
   * @throws CoderException if the value could not be decoded for some reason
   */
  public T decode(InputStream inStream, Context context)
      throws CoderException, IOException;

  /**
   * If this is a {@code Coder} for a parameterized type, returns the
   * list of {@code Coder}s being used for each of the parameters, or
   * returns {@code null} if this cannot be done or this is not a
   * parameterized type.
   */
  public List<? extends Coder<?>> getCoderArguments();

  /**
   * Returns the {@link CloudObject} that represents this {@code Coder}.
   */
  public CloudObject asCloudObject();

  /**
   * Throw {@link NonDeterministicException} if the coding is not deterministic.
   *
   * <p>In order for a {@code Coder} to be considered deterministic,
   * the following must be true:
   * <ul>
   *   <li>two values that compare as equal (via {@code Object.equals()}
   *       or {@code Comparable.compareTo()}, if supported) have the same
   *       encoding.
   *   <li>the {@code Coder} always produces a canonical encoding, which is the
   *       same for an instance of an object even if produced on different
   *       computers at different times.
   * </ul>
   *
   * @throws Coder.NonDeterministicException if this coder is not deterministic.
   */
  public void verifyDeterministic() throws Coder.NonDeterministicException;

  /**
   * Returns true if whenever the encoded bytes of two values are equal, then the original values
   * are equal according to {@code Objects.equals()} (note that this is well-defined for
   * {@code null}). In other words, encoding is injective.
   *
   * <p>This condition is most notably false for arrays. More generally, this condition is false
   * whenever {@code equals()} compares object identity, rather than performing a
   * semantic/structural comparison.
   */
  public boolean consistentWithEquals();

  /**
   * Returns an object with an {@code Object.equals()} method that represents structural equality
   * on the argument.
   *
   * <p>For any two values {@code x} and {@code y} of type {@code T}, if their encoded bytes are the
   * same, then it must be the case that {@code structuralValue(x).equals(@code structuralValue(y)}.
   *
   * <p>Most notably:
   * <ul>
   *   <li>The structural value for an array coder should perform a structural comparison of the
   *   contents of the arrays, rather than the default behavior of comparing according to object
   *   identity.
   *   <li>The structural value for a coder accepting {@code null} should be a proper object with
   *   an {@code equals()} method, even if the input value is {@code null}.
   * </ul>
   *
   * <p>See also {@link #consistentWithEquals()}.
   */
  public Object structuralValue(T value) throws Exception;

  /**
   * Returns whether {@link #registerByteSizeObserver} cheap enough to
   * call for every element, that is, if this {@code Coder} can
   * calculate the byte size of the element to be coded in roughly
   * constant time (or lazily).
   *
   * <p>Not intended to be called by user code, but instead by
   * {@link com.google.cloud.dataflow.sdk.runners.PipelineRunner}
   * implementations.
   */
  public boolean isRegisterByteSizeObserverCheap(T value, Context context);

  /**
   * Notifies the {@code ElementByteSizeObserver} about the byte size
   * of the encoded value using this {@code Coder}.
   *
   * <p>Not intended to be called by user code, but instead by
   * {@link com.google.cloud.dataflow.sdk.runners.PipelineRunner}
   * implementations.
   */
  public void registerByteSizeObserver(
      T value, ElementByteSizeObserver observer, Context context)
      throws Exception;

  /**
   * An identifier for the binary format written by {@link #encode}.
   *
   * <p>This value, along with the fully qualified class name, forms an identifier for the
   * binary format of this coder. Whenever this value changes, the new encoding is considered
   * incompatible with the prior format: It is presumed that the prior version of the coder will
   * be unable to correctly read the new format and the new version of the coder will be unable to
   * correctly read the old format.
   *
   * <p>If the format is changed in a backwards-compatible way (the Coder can still accept data from
   * the prior format), such as by adding optional fields to a Protocol Buffer or Avro definition,
   * and you want Dataflow to understand that the new coder is compatible with the prior coder,
   * this value must remain unchanged. It is then the responsibility of {@link #decode} to correctly
   * read data from the prior format.
   */
  @Experimental(Kind.CODER_ENCODING_ID)
  public String getEncodingId();

  /**
   * A collection of encodings supported by {@link #decode} in addition to the encoding
   * from {@link #getEncodingId()} (which is assumed supported).
   *
   * <p><i>This information is not currently used for any purpose</i>. It is descriptive only,
   * and this method is subject to change.
   *
   * @see #getEncodingId()
   */
  @Experimental(Kind.CODER_ENCODING_ID)
  public Collection<String> getAllowedEncodings();

  /**
   * Exception thrown by {@link Coder#verifyDeterministic()} if the encoding is
   * not deterministic.
   */
  public static class NonDeterministicException extends Throwable {
    private Coder<?> coder;
    private List<String> reasons;

    public NonDeterministicException(
        Coder<?> coder, String reason, @Nullable NonDeterministicException e) {
      this(coder, Arrays.asList(reason), e);
    }

    public NonDeterministicException(Coder<?> coder, String reason) {
      this(coder, Arrays.asList(reason), null);
    }

    public NonDeterministicException(Coder<?> coder, List<String> reasons) {
      this(coder, reasons, null);
    }

    public NonDeterministicException(
        Coder<?> coder,
        List<String> reasons,
        @Nullable NonDeterministicException cause) {
      super(cause);
      Preconditions.checkArgument(reasons.size() > 0,
          "Reasons must not be empty.");
      this.reasons = reasons;
      this.coder = coder;
    }

    public Iterable<String> getReasons() {
      return reasons;
    }

    @Override
    public String getMessage() {
      return String.format("%s is not deterministic because:\n  %s",
          coder, Joiner.on("\n  ").join(reasons));
    }
  }