Componente ProcessTrain

Este tutorial esta pensado para usuarios que tengan cierto conocimiento sobre el funcionamiento del framework ADF. Pues en este se usan terminos que no han sido explicados previamente y pueden resultar complejos para usuarios novatos.  

El componente processTrain es un componente ADF del tipo menú. Consiste en crear varias páginas JSF que están enlazadas entre sí. Este componente actualmente está en discusión entre los creadores de ADF, pues su lógica se realiza en el fichero de configuración faces-config.

Las clases que se necesitan realizar para que funcione el componente básicamente son dos. Una nombrada por ellos como MenuItem y otra TrainModelAdapter. Estas dos clases están hechas ya por oracle, simplemente definen algunas propiedades que tendremos que usar luego desde el faces-config a la hora de definir los managed-bean y desde las páginas JSF para algunos valores del componente.

Clase MenuItem.java:
public class MenuItem {

private String _label;
private String _outcome;
private String _viewId;
//extended security attributes
private boolean _readOnly = false;
private boolean _shown = true;
public void setLabel(String label) {
this._label = label;
}
public String getLabel() {
return _label;
}
public void setOutcome(String outcome) {
this._outcome = outcome;
}
public String getOutcome() {
return _outcome;
}
public void setViewId(String viewId) {
this._viewId = viewId;
}
public String getViewId() {
return _viewId;
}
public void setReadOnly(boolean readOnly) {
this._readOnly = readOnly;
}
public boolean isReadOnly() {
return _readOnly;
}
public void setShown(boolean shown) {
this._shown = shown;
}
public boolean isShown() {
return _shown;
}
}
Clase TrainModelAdapter.java:
public class TrainModelAdapter implements Serializable {
private String _propertyName = null;
private Object _instance = null;
private transient MenuModel _model = null;
private Object _maxPathKey = null;

public MenuModel getModel() {
if (_model == null){
try {
_model = new ProcessMenuModel(getInstance(),
getViewIdProperty();
getMaxPathKey());
} catch (IntrospectionException e) {
// TODO
}
}
return _model;
}

public String getViewIdProperty() {
return _propertyName;
}

/**
* Sets the property to use to get at view id
* @param propertyName
*/
public void setViewIdProperty(String propertyName) {
_propertyName = propertyName;
_model = null;
}
public Object getInstance() {
return _instance;
}
/**
* Sets the treeModel
* @param instance must be something that can be converted into a TreeModel
*/
public void setInstance(Object instance) {
_instance = instance;
_model = null;
}
public Object getMaxPathKey(){
return _maxPathKey;
}
public void setMaxPathKey(Object maxPathKey){
_maxPathKey = maxPathKey;
}
}

 
Una vez tengamos las páginas JSF que queramos meter en el menu, vamos al fichero faces-config y definimos los beans. Indicamos que el backing_bean es de tipo MenuItem y seteandole las propiedades por defecto. Un ejemplo sería el siguiente:

<managed-bean>
<managed-bean-name>paso1</managed-bean-name>
<managed-bean-class>view.backing.MenuItem</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<managed-property>
<property-name>label</property-name>
<value>Paso1</value>
</managed-property>
<managed-property>
<property-name>viewId</property-name>
<value>/paso1.jspx</value>
</managed-property>
<managed-property>
<property-name>outcome</property-name>
<value>paso1</value>
</managed-property>
</managed-bean>

Ahora debemos irnos al faces-config y definir en él un backing-bean. Este realmente no lo tenemos creado como una clase se genera en tiempo de ejecucion. Definiremos que este backing-bean sea de tipo ArrayList y tendrá como valor los backing_bean que estan asociados con las páginas que queremos mostrar en el processTrain.

<managed-bean>
<managed-bean-name>createTrainNodes</managed-bean-name>
<managed-bean-class>java.util.ArrayList</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<list-entries>
<value-class>view.backing.MenuItem</value-class>
<value>#{paso1}</value>
<value>#{paso2}</value>
<value>#{paso3}</value>
</list-entries>
</managed-bean>

Y por último definimos la clase TrainModelAdapter en el mismo fichero de configuración faces-config:

<managed-bean>
<managed-bean-name>createTrainMenuModel</managed-bean-name>
<managed-bean-class>view.backing.TrainModelAdapter</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<managed-property>
<property-name>viewIdProperty</property-name>
<value>viewId</value>
</managed-property>
<managed-property>
<property-name>instance</property-name>
<value>#{createTrainNodes}</value>
</managed-property>
</managed-bean>

 
Existen dos tipos de configuraciones para el componente processTrain, Plus One y Max Visited.
Si elejimos PlusOne el comportamiento será que el usuario puede avanzar los nodos de uno en uno de manera secuencial. Avanzaría del nodo 1 al 2, del 2 al 3, pero nunca del 1 al 5 por ejemplo. Pero si el usuario retrocede desde el nodo 5 al 1, cuando vuelva a avanzar tendría que pasar por todos los nodos anteriores.
Con MaxVisited el comportamiento sería semejante al anterior, pero se puede dirigir directamente a cualquier nodo que haya ya visitado.

Estos valores se definen en el managed-bean anterior, si ponemos la siguiente propiedad:

<managed-property>
<property-name>maxPathKey</property-name>
<value>TRAIN_DEMO_MAX_PATH_KEY</value>
</managed-property>

Aquí estaríamos usando la opción MaxVisited, si no pusieramos nada (null) usaría PlusOne.

Ya solo quedaría definir las reglas de navegación entre las páginas en el faces-config, la cadena que obtiene el componente para comprobar a donde se redirige se captura por la propiedad outcome definida para la clase MenuItem.

<navigation-rule>
<from-view-id>/paso2.jspx</from-view-id>
<navigation-case>
<from-outcome>paso1</from-outcome>
<to-view-id>/paso1.jspx</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>paso3</from-outcome>
<to-view-id>/paso3.jspx</to-view-id>
</navigation-case>
</navigation-rule>

Por último, en las páginas JSF, debemos de crear los componentes:

<af:processTrain var="train" value="#{createTrainMenuModel.model}">
<f:facet name="nodeStamp">
<af:commandMenuItem text="#{train.label}"
action="#{train.getOutcome}"
readOnly="#{createTrainMenuModel.model.readOnly}"
immediate="false"/>
</f:facet>
</af:processTrain>

El processTrain obtiene el modelo que se crea con la clase TrainModelAdapter y se lo setea como valor.

Él dinamicamente sabrá en cual página está y cual backing-bean usa en cada caso por la propiedad viewId.

Se puede añadir también a la página un componente processChoiceBar en el facet actions del panelPage. Este inserta en la parte superior e inferior de la página una guía de la navegación que tendría los mismos valores que el processTrain. Bastaría con añadir lo siguiente:

<f:facet name="actions">
<af:processChoiceBar var="choice"
value="#{createTrainMenuModel.model}">
<f:facet name="nodeStamp">
<af:commandMenuItem text="#{choice.label}"
action="#{choice.getOutcome}"
readOnly="#{createTrainMenuModel.model.readOnly}"
immediate="false"/>
</f:facet>
</af:processChoiceBar>
</f:facet>

Una vez completados estos pasos, si ejectusemos nuestra aplicación nos aparecería por pantalla el componente con las reglas de navegación que hayamos establecido anteriormente.

Tags:

Comments are closed.