package build.pluto.dependency;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import build.pluto.builder.BuildRequest;

/**
 * Collection of BuildRequests from which other files originate.
 * 
 * @author seba
 */
public class Origin implements Serializable {

  private static final long serialVersionUID = 4754106394706480006L;
  
  private final Set<? extends BuildRequest<?, ?, ?, ?>> reqs;
  
  private Origin(Set<? extends BuildRequest<?, ?, ?, ?>> reqs) {
    if (reqs.isEmpty())
      throw new IllegalArgumentException("Origin requirements must be non-empty. Use a null object instead of the empty Origin.");
    this.reqs = Collections.unmodifiableSet(reqs);
  }
  
  public Collection<? extends BuildRequest<?, ?, ?, ?>> getReqs() {
    return reqs;
  }
  
  @Override
  public int hashCode() {
    return reqs.hashCode();
  }
  
  @Override
  public boolean equals(Object other) {
    return other == null || other instanceof Origin && ((Origin) other).reqs.equals(reqs);
  }
  
  @Override
  public String toString() {
    return "Origin(" + reqs.toString() + ")";
  }
  
  public static Origin from(BuildRequest<?, ?, ?, ?>... reqs) {
    return Builder().add(reqs).get();
  }
  
  public static Builder Builder() { return new Builder(); }
  public static class Builder {
    private Set<BuildRequest<?, ?, ?, ?>> reqs = new HashSet<>();
    private Origin result = null;
    
    public Origin get() {
      if (result != null)
        return result;
      if (reqs.isEmpty())
        return null;
      return new Origin(reqs);
    }
    
    public Builder add(BuildRequest<?, ?, ?, ?>... reqs) {
      result = null;
      for (BuildRequest<?, ?, ?, ?> req : reqs)
        this.reqs.add(req);
      return this;
    }
    
    public Builder add(Origin origin) {
      result = null;
      if (origin != null)
        this.reqs.addAll(origin.reqs);
      return this;
    }
  }
}

@@ -203,16 +203,134 @@
 Request;
+%0Aimport build.pluto.builder.BuilderFactory;%0Aimport build.pluto.output.Output;%0Aimport build.pluto.output.OutputStamper;
 %0A%0A/**%0A *
@@ -1749,32 +1749,774 @@
 qs);%0A    %7D%0A    %0A
+    public %0A  //@formatter:off%0A    %3CIn_ extends Serializable, %0A     Out_ extends Output, %0A     B_ extends build.pluto.builder.Builder%3CIn_, Out_%3E, %0A     F_ extends BuilderFactory%3CIn_, Out_, B_%3E, %0A     SubIn_ extends In_%3E%0A  //@formatter:on%0A    Builder add(F_ factory, In_ input) %7B%0A      add(new BuildRequest%3C%3E(factory, input));%0A      return this;%0A    %7D%0A%0A    public %0A  //@formatter:off%0A    %3CIn_ extends Serializable, %0A     Out_ extends Output, %0A     B_ extends build.pluto.builder.Builder%3CIn_, Out_%3E, %0A     F_ extends BuilderFactory%3CIn_, Out_, B_%3E, %0A     SubIn_ extends In_%3E%0A  //@formatter:on%0A    Builder add(F_ factory, In_ input, OutputStamper%3COut_%3E stamper) %7B%0A      add(new BuildRequest%3C%3E(factory, input, stamper));%0A      return this;%0A    %7D%0A%0A
     public Build

extend Origin API