package commons.application.core;
import commons.application.ctx.Context;
import commons.application.ctx.Contract;
import basics.utl.SUtl;
import basics.utl.SysUtl;
/**
 * A service is processed by the engine. A consists for (optional) checks (before and after
 * execution), of the serviceLabour, as defined by the derived concrete class, and may include
 * further services, that are triggered either before or after the labor is done.
 * @author ks
 */
public abstract class Command
{

protected Context         ctx      = null;
protected Contract        contract = null;
protected EngineInterface engine   = null;
private String            id       = null;
private String            docid       = null;
public int                DEBUG    = 0;

public Command()
{}

public void setContext (Context ctx)
{
   this.ctx = ctx;
}

public void setupDebug ()
{
   DEBUG = ctx.getr(this.getClass().getSimpleName(), -1);
   if (DEBUG == -1)
      DEBUG = ctx.getr("debug", 0);
}

public synchronized void debug (int level, String template, Object...objects)
{
   if (DEBUG >= level)
      SysUtl.traceB(1, SUtl.sprint(template, objects));
}

public boolean isDebugLevel (int level)
{
   return (DEBUG >= level);
}

/**
 * Overwrite this, if the service is being reused and must be reset before reuse. Reset is called
 * before every execution.
 */
public void init ()
{}

/**
 * Implementing class can sign a contract. The definition is made in the subclass.
 */
public abstract void signContract ();

/**
 * callback, called from inside the concrete class, thus setting the contract. precond and postcond
 * contain keys that the ctx must contain
 */
public void demand (String[] precond, String[] postcond)
{
   contract = new Contract(precond, postcond);
}

/**
 * precond and postcond contain keys that the ctx must contain strings are comma separated
 * @param precond
 * @param postcond
 */
public void demand (String precond, String postcond)
{
   contract = new Contract(precond, postcond);
}

/**
 * Diese Methode wird vom Benutzer implementiert, die definiert die Semantik des Prozesses. Der
 * Rueckgabewert steuert den weiteren Ablauf: solange false, wird weiter ausgefuehrt, bei true ist
 * Schluss.
 * @throws beliebige Exception
 */
protected abstract void process () throws Throwable;

public String getSignature ()
{
   return getId() + ">" + implName();
}

public String getId ()
{
   return id == null ? implName() : id;
}

public void setId (String id)
{
   this.id = id;
}

/**
 * overwrite in subclass, return service description
 * @return
 */
public String description ()
{
   return "Command";
}

public String implName ()
{
   return this.getClass().getSimpleName();
}


public String getDocId()
{
   return docid;
}


public void setDocId(String docid)
{
   this.docid = docid;
}
}
