/*
 * Copyright 2013 University of Chicago and Argonne National Laboratory
 *
 * Licensed 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 exm.stc.common.lang;

import java.util.Collections;
import java.util.List;

/**
 * Where a bit of code will execute.
 * 
 * We treat control and work contexts differently even if they run on the same
 * resources: nothing that will block for an indeterminate or long amount of
 * time should run in a control context.
 */
public class ExecContext {
  /**
   * Represent a general kind of context
   */
  public static enum Kind {
    WORKER, CONTROL,; 
  }
  
  /**
   * Represent a specific kind of worker.
   * 
   * Compare based on identity
   * Include string to identify in debug messages, etc.
   */
  public static class WorkerContext {
    private String name;
    
    public WorkerContext(String name) {
      this.name = name;
    }
    
    @Override
    public String toString() {
      return "WorkerContext <" + name + ">";
    }
    
    private static WorkerContext DEFAULT = new WorkerContext("WORKER");
  }
  
  private ExecContext(Kind kind, WorkerContext workContext) {
    if (this.kind == Kind.WORKER) {
      assert(workContext != null);
    }
    this.kind = kind;
    this.workContext = workContext;
  }
  
  private final Kind kind;
  private final WorkerContext workContext;
  
  public WorkerContext workContext() {
    return workContext;
  }
  
  private static final ExecContext CONTROL_CONTEXT =
                new ExecContext(Kind.CONTROL, null);
  public static ExecContext control() {
    return CONTROL_CONTEXT;
  }
  
  public static ExecContext worker(WorkerContext workContext) {
    return new ExecContext(Kind.CONTROL, workContext);
  }
  
  private static final ExecContext DEFAULT_WORKER_CONTEXT = 
            new ExecContext(Kind.WORKER, WorkerContext.DEFAULT);
  public static ExecContext defaultWorker() {
    return DEFAULT_WORKER_CONTEXT;
  }
  
  public List<ExecContext> asList() {
    return Collections.singletonList(this);
  }

  public boolean isControlContext() {
    return kind == Kind.CONTROL; 
  }
  
  public boolean isAnyWorkContext() {
    return kind == Kind.WORKER; 
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((kind == null) ? 0 : kind.hashCode());
    result = prime * result
        + ((workContext == null) ? 0 : workContext.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    
    assert (obj != null) : "Compare " + this + " with null";
    assert(obj instanceof ExecContext) :
        "Compare ExecContext with " + obj.getClass().getCanonicalName();

    ExecContext other = (ExecContext) obj;
    if (kind != other.kind) {
      return false;
    }
    
    if (workContext == null) {
      if (other.workContext != null) {
        return false;
      }
    } else if (!workContext.equals(other.workContext))
      return false;
    return true;
  }

  @Override
  public String toString() {
    if (kind == Kind.CONTROL) {
      return "CONTROL";
    } else {
      assert(kind == Kind.WORKER);
      return "WORKER[" + workContext + "]";
    }
  }
}
@@ -756,17 +756,16 @@
 cute.%0A *
- 
 %0A * We t
@@ -1087,24 +1087,21 @@
 ONTROL,;
- 
 %0A  %7D%0A
-  
 %0A  /**%0A 
@@ -1145,17 +1145,16 @@
 er.%0A   *
- 
 %0A   * Co
@@ -1302,20 +1302,16 @@
 g name;%0A
-    
 %0A    pub
@@ -1369,28 +1369,24 @@
 name;%0A    %7D%0A
-    
 %0A    @Overri
@@ -1436,46 +1436,20 @@
 urn 
-%22WorkerContext %3C%22 + name + %22%3E%22
+name
 ;%0A    %7D%0A
     
@@ -1440,28 +1440,24 @@
 name;%0A    %7D%0A
-    
 %0A    private
@@ -1517,26 +1517,24 @@
 RKER%22);%0A  %7D%0A
-  
 %0A  private E
@@ -1592,21 +1592,16 @@
     if (
-this.
 kind == 
@@ -1650,16 +1650,101 @@
  null);%0A
+    %7D else %7B%0A      assert( kind == Kind.CONTROL);%0A      assert(workContext == null);%0A
     %7D%0A  
@@ -1795,34 +1795,32 @@
 orkContext;%0A  %7D%0A
-  
 %0A  private final
@@ -1878,80 +1878,116 @@
 xt;%0A
-  
 %0A  p
-ublic WorkerContext workContext() %7B%0A    return workContext;%0A  %7D%0A  
+rivate static final ExecContext CONTROL_CONTEXT =%0A                  new ExecContext(Kind.CONTROL, null);
 %0A  p
@@ -2010,39 +2010,46 @@
 nal ExecContext 
-CONTROL
+DEFAULT_WORKER
 _CONTEXT =%0A     
@@ -2035,32 +2035,34 @@
 ORKER_CONTEXT =%0A
+  
                 
@@ -2078,39 +2078,124 @@
 ontext(Kind.
-CONTROL, null);
+WORKER, WorkerContext.DEFAULT);%0A%0A  public WorkerContext workContext() %7B%0A    return workContext;%0A  %7D%0A
 %0A  public st
@@ -2247,34 +2247,32 @@
 OL_CONTEXT;%0A  %7D%0A
-  
 %0A  public static
@@ -2352,23 +2352,22 @@
 xt(Kind.
-CONTROL
+WORKER
 , workCo
@@ -2382,136 +2382,8 @@
   %7D%0A
-  %0A  private static final ExecContext DEFAULT_WORKER_CONTEXT = %0A            new ExecContext(Kind.WORKER, WorkerContext.DEFAULT);
 %0A  p
@@ -2460,26 +2460,24 @@
 ONTEXT;%0A  %7D%0A
-  
 %0A  public Li
@@ -2626,16 +2626,13 @@
 ROL;
- 
 %0A  %7D%0A
-  
 %0A  p
@@ -2697,17 +2697,16 @@
 .WORKER;
- 
 %0A  %7D%0A%0A  
@@ -3067,28 +3067,24 @@
 true;%0A    %7D%0A
-    
 %0A    assert 
@@ -3347,20 +3347,16 @@
 ;%0A    %7D%0A
-    
 %0A    if 

Fix context type mixup