package org.jcon.param.schema;

import org.jcon.param.Param;
import org.jcon.param.tree.Datum;

/**
 * Defines the structure of a DatumBranch, like an Entity
 * defines the structure of a Table. This allows Datums to
 * be defined, created, edited and validated in a reusable
 * manner.
 *
 * @author Jack Harich
 */
public abstract class Branch {

//---------- Protected Fields ----------------------------
protected String  name;
protected boolean isRequired;
protected Param   defParam;
protected BranchSchema schema;

//---------- Abstract Methods ----------------------------
/**
 * Returns the String identifying the Branch type. This
 * should be unique per system. Must be legal name.
 * Examples are PropList and LineList.
 */
public abstract String getBranchType();

/**
 * Uses its definition to validate the Datum. Returns
 * null for okay or a String describing why invalid. If the
 * Datum is a container it should validate its children.
 * Thus validating the root validates an entire tree if
 * recurse is true.
 * <p>
 * The Datum must be the same type as the DatumDef.
 * If recurse is true then the datum should be recusively
 * validated, ie its child containers should be validated.
 */
public abstract String validate(Datum datum, boolean recurse);

/**
 * Returns the default Datum used when a Datum is added.
 * This gives the user a starting point, saving time and
 * consternation. Returns null for no default, which should
 * be avoided.
 */
public abstract Datum getDefault(Datum parentDatum);

//---------- Properties ----------------------------------
//----- name
/**
 * Sets the String identifying the Branch. This
 * should be unique per schema. Must be legal name.
 * Examples are Family, RowFields, Entity.
 */
public void setName(String name) {
    this.name = name.intern();
}
public String getName() {
    return name;
}
//----- isRequired
/** public void setRequired(boolean isRequired) {
    this.isRequired = isRequired;
}
public boolean isRequired() {
    return isRequired;
} */
//----- param
/**
 * Sets the Param used to define the DatumDef and used
 * for validation, etc. The param must contain the properties
 * Name and DatumType, plus others.
 */
public void setParam(Param param) {
    defParam = param;
    setName(param.getString("BranchName"));

    // Assert correct DatumType
    String branchType = param.getString("BranchType");
    if (! branchType.equals(getBranchType()) ) {
        throw new IllegalArgumentException("Param contains " +
        "BranchType '" + branchType + "', should be the same " +
        "as my BranchType which is '" + getBranchType() + "'.");
    }
}
/** public Param getParam() {
    return defParam;
} */
//----- Other
public void setSchema(BranchSchema schema) {
    this.schema = schema;
}
//---------- Private Methods -----------------------------
//--- Std
private static void print(String text) {
    System.out.println("Branch" + text);
}

} // End class
