Tree.java
package progen.kernel.tree;
import java.io.Serializable;
import java.util.Map;
import progen.context.ProGenContext;
import progen.context.UnknownPropertyException;
import progen.kernel.grammar.Grammar;
import progen.userprogram.UserProgram;
/**
* Clase que representa un árbol y los distintos métodos de acceso a él.
*
* @author jirsis
*
*/
public class Tree implements Cloneable, Serializable {
private static final String HALF_HALF_LITERAL = "half&half";
private static final long serialVersionUID = 5043645528729444176L;
/** Nodo raíz del árbol. */
private Node root;
/** Método de inicialización del árbol. */
private InitializeTreeMethod initMethod;
/**
* Constructor de copia que recibe por parámetro otro árbol del que copiar los
* datos.
*
* @param tree
* El árbol a copiar.
*/
public Tree(Tree tree) {
this.initMethod = tree.initMethod;
this.root = tree.root.clone();
}
/**
* Constructor de la clase. Se configura el método de inicialización
* definiendo en el fichero de configuración del usuario la propiedad
* <code>progen.population.init-mode</code>, admitiendo como valores válidos:
* <ul>
* <li>full</li>
* <li>grow</li>
* <li>half&half</li>
* </ul>
*
*/
public Tree() {
final String init = ProGenContext.getOptionalProperty("progen.population.init-mode", HALF_HALF_LITERAL);
if ("full".equals(init)) {
initMethod = new Full();
} else if ("grow".equals(init)) {
initMethod = new Grow();
} else if (HALF_HALF_LITERAL.equals(init)) {
initMethod = new HalfAndHalf();
} else {
throw new UnknownPropertyException(init + "? progen.population.init-method=grow|full|half&half");
}
root = null;
}
/**
* Forma de generar un árbol a partir de una gramática pasada por parámetro.
*
* @param grammar
* de la que se usarán las producciones para generar el árbol.
*/
public void generate(Grammar grammar) {
root = new Node(grammar.getAxiom());
initMethod.generate(grammar, root);
}
/**
* Devuelve el nodo raíz del árbol.
*
* @return <code>Node</code> raíz del árbol.
*/
public Node getRoot() {
return getNode(0);
}
/**
* Representación del árbol como si fuera un programa de Lisp
*
* @return <code>String</code> con la representación del árbol con formato de
* Lisp
*/
public String toString() {
return root.toString();
}
/**
* Evalúa el árbol de tal forma que se devuelve el valor después de ejecutar
* todo el programa almacenado en este árbol.
*
* @param userProgram
* Definición concreta del dominio del problema que necesitará el
* árbol para ser evaluado.
* @param returnAddr
* Dirección de retorno de las llamadas a ADFs.
* @return <code>Object</code> con el valor de la ejecución del programa.
*/
public Object evaluate(UserProgram userProgram, Map<String, Object> returnAddr) {
return root.evaluate(userProgram, returnAddr);
}
/**
* Devuelve el nodo que está en la posición en preorden indicada como
* parámetro.
*
* @param position
* La posición dentro del árbol.
* @return El nodo que está en la posición solicitada o <code>null</code> la
* posición está fuera de los rangos válidos.
*/
public Node getNode(int position) {
Node node = null;
if (root != null) {
node = root.getNode(position);
}
return node;
}
@Override
public Tree clone() {
try {
super.clone();
} catch (CloneNotSupportedException e) {
// ignore this exception
}
return new Tree(this);
}
/**
* Devuelve el método que se utilizó para generar este árbol.
*
* @return El método de inicialización del árbol.
*/
public InitializeTreeMethod getInitializeTreeMethod() {
return initMethod;
}
}