/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.beam.sdk.transforms;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import org.apache.beam.sdk.values.PInput;
import org.apache.beam.sdk.values.POutput;

/**
 * Represents the application of a {@link PTransform} to a specific input to produce
 * a specific output.
 *
 * <p>For internal use.
 *
 * @param <InputT> transform input type
 * @param <OutputT> transform output type
 * @param <TransformT> transform type
 */
public class AppliedPTransform
    <InputT extends PInput, OutputT extends POutput,
     TransformT extends PTransform<? super InputT, OutputT>> {

  private final String fullName;
  private final InputT input;
  private final OutputT output;
  private final TransformT transform;

  private AppliedPTransform(String fullName, InputT input, OutputT output, TransformT transform) {
    this.input = input;
    this.output = output;
    this.transform = transform;
    this.fullName = fullName;
  }

  public static <InputT extends PInput, OutputT extends POutput,
                 TransformT extends PTransform<? super InputT, OutputT>>
  AppliedPTransform<InputT, OutputT, TransformT> of(
      String fullName, InputT input, OutputT output, TransformT transform) {
    return new AppliedPTransform<InputT, OutputT, TransformT>(fullName, input, output, transform);
  }

  public String getFullName() {
    return fullName;
  }

  public InputT getInput() {
    return input;
  }

  public OutputT getOutput() {
    return output;
  }

  public TransformT getTransform() {
    return transform;
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(getFullName(), getInput(), getOutput(), getTransform());
  }

  @Override
  public boolean equals(Object other) {
    if (other instanceof AppliedPTransform) {
      AppliedPTransform<?, ?, ?> that = (AppliedPTransform<?, ?, ?>) other;
      return Objects.equal(this.getFullName(), that.getFullName())
          && Objects.equal(this.getInput(), that.getInput())
          && Objects.equal(this.getOutput(), that.getOutput())
          && Objects.equal(this.getTransform(), that.getTransform());
    } else {
      return false;
    }
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(getClass())
        .add("fullName", getFullName())
        .add("input", getInput())
        .add("output", getOutput())
        .add("transform", getTransform())
        .toString();
  }
}

@@ -862,70 +862,28 @@
 gle.
-common.base.MoreObjects;%0Aimport com.google.common.base.Objects
+auto.value.AutoValue
 ;%0Aim
@@ -1231,22 +1231,42 @@
 ype%0A */%0A
-public
+@AutoValue%0Apublic abstract
  class A
@@ -1406,394 +1406,65 @@
 %0A  p
-rivate final String fullName;%0A  private final InputT input;%0A  private final OutputT output;%0A  private final TransformT transform;%0A%0A  private AppliedPTransform(String fullName, InputT input, OutputT output, TransformT transform) %7B%0A    this.input = input;%0A    this.output = output;%0A    this.transform = transform;%0A    this.fullName = fullName;%0A  %7D%0A%0A  public static %3CInputT extends PInput,
+ublic static %3C%0A          InputT extends PInput,%0A         
  Out
@@ -1485,23 +1485,16 @@
 Output,%0A
-       
         
@@ -1551,16 +1551,20 @@
 tputT%3E%3E%0A
+    
   Applie
@@ -1608,16 +1608,20 @@
 mT%3E of(%0A
+    
       St
@@ -1704,16 +1704,26 @@
 urn new 
+AutoValue_
 AppliedP
@@ -1761,16 +1761,25 @@
 sformT%3E(
+%0A        
 fullName
@@ -1825,1059 +1825,145 @@
 lic 
-String getFullName() %7B%0A    return fullName;%0A  %7D%0A%0A  public InputT getInput() %7B%0A    return input;%0A  %7D%0A%0A  public OutputT getOutput() %7B%0A    return output;%0A  %7D%0A%0A  public TransformT getTransform() %7B%0A    return transform;%0A  %7D%0A%0A  @Override%0A  public int hashCode() %7B%0A    return Objects.hashCode(getFullName(), get
+abstract String getFullName();%0A%0A  public abstract 
 Input
-(),
+T
  get
-Out
+In
 put()
-, getTransform());%0A  %7D%0A%0A  @Override%0A  public boolean equals(Object other) %7B%0A    if (other instanceof AppliedPTransform) %7B%0A      AppliedPTransform%3C?, ?, ?%3E that = (AppliedPTransform%3C?, ?, ?%3E) other;%0A      return Objects.equal(this.getFullName(), that.getFullName())%0A          && Objects.equal(this.getInput(), that.getInput())%0A          && Objects.equal(this.getOutput(), that.getOutput())%0A          && Objects.equal(this.getTransform(), that.getTransform());%0A    %7D else %7B%0A      return false;%0A    %7D%0A  %7D%0A%0A  @Override%0A  public String toString() %7B%0A    return MoreObjects.toStringHelper(getClass())%0A        .add(%22fullName%22, getFullName())%0A        .add(%22input%22, getInput())%0A        .add(%22output%22, getOutput())%0A        .add(%22t
+;%0A%0A  public abstract OutputT getOutput();%0A%0A  public abstract T
 ransform
 %22, g
@@ -1962,10 +1962,9 @@
 form
-%22,
+T
  get
@@ -1978,33 +1978,8 @@
 rm()
-)%0A        .toString();%0A  %7D
+;
 %0A%7D%0A

Migrate AppliedPTransform to use AutoValue