_________________________________________________________________________
¿Qué es el Código Flexible?
¿Por qué escribir código flexible?
Escribir código flexible te brinda las siguientes ventajas:
• Es reutilizable.
• Es genérico.
• Evita nombres de objetos codificados.
• Es más fácil de mantener.
• Aumenta la productividad.
Ejemplo:
IF :SYSTEM.CURSOR_BLOCK = 'ORDERS' THEN
GO_BLOCK('ORDER_ITEMS');
ELSIF :SYSTEM.CURSOR_BLOCK = 'ORDER_ITEMS' THEN
GO_BLOCK('INVENTORIES');
ELSIF :SYSTEM.CURSOR_BLOCK = 'INVENTORIES' THEN
GO_BLOCK('ORDERS');
END IF;
Variables del sistema para localizar el foco del Trigger.
El Uso de las Variables de Enfoque del Trigger.
Variables de sistema para determinar el estado actual del Form.
BEGIN
ENTER;
IF :SYSTEM.BLOCK_STATUS = 'CHANGED' THEN
COMMIT_FORM;
END IF;
CLEAR_BLOCK;
END;
/*Este ejemplo muestra como determinar el Canvas que contiene el Item donde radica el foco de entrada.*/
Código Flexible: es todo código que puede ser reutilizado en distintos escenarios. El código flexible a menudo es un código genérico que puede usar en cualquier módulo Form en una aplicación. Por lo general, incluye el uso de variables del sistema en lugar de nombres de objetos codificados.
¿Por qué escribir código flexible?
Escribir código flexible te brinda las siguientes ventajas:
• Es reutilizable.
• Es genérico.
• Evita nombres de objetos codificados.
• Es más fácil de mantener.
• Aumenta la productividad.
______________________________________________________________________________________
Uso de Variables de Sistema para el Contexto Actual.
Variables del sistema para localizar el foco de entrada actual:
Variable de
|
Funcción
|
CURSOR_BLOCK |
Contiene el Bloque que tiene el foco de entrada.
|
CURSOR_RECORD
|
Contiene el registro que tiene el foco de entrada.
|
CURSOR_ITEM
|
Contiene el Item y Bloque que tiene el foco de entrada.
|
CURSOR_VALUE
|
Contiene el valor del Item que tiene el foco de entrada.
|
IF :SYSTEM.CURSOR_BLOCK = 'ORDERS' THEN
GO_BLOCK('ORDER_ITEMS');
ELSIF :SYSTEM.CURSOR_BLOCK = 'ORDER_ITEMS' THEN
GO_BLOCK('INVENTORIES');
ELSIF :SYSTEM.CURSOR_BLOCK = 'INVENTORIES' THEN
GO_BLOCK('ORDERS');
END IF;
/*El ejemplo anterior muestra un código que podría colocarse en un Trigger When-Button-Pressed para permitir a los usuarios navegar a otro bloque en el Form. Verifica el nombre del bloque actual, luego navega a otro en función del resultado.*/
Nota: asegúrese de establecer la propiedad Mouse Navigate del botón en No; de lo contrario, SYSTEM.CURSOR_BLOCK siempre será el bloque en el que se encuentra el botón.
Variables del sistema para localizar el foco del Trigger.
System Variable
|
Function
|
TRIGGER_BLOCK |
El bloque en el que estaba el foco de entrada cuando el Trigger se disparó inicialmente.
|
TRIGGER_RECORD
|
El número del registro que Forms está procesando.
|
TRIGGER_ITEM
|
El bloque y item en el que estaba el foco de entrada cuando el Trigger se disparó inicialmente.
|
Las variables para ubicar el foco del trigger son útiles para navegar de regreso al destino inicial una vez que se completa la ejecución del trigger . Por ejemplo, puede que durante la ejecución del trigger se requiere navegar a otros bloques, registros o items y así realizar acciones sobre ellos, y que después de la ejecución de dicho proceso se desee que el cursor retorne en la misma instancia inicial. Debido a que la navegación en el trigger se produce detrás de escenas, el usuario ni siquiera se dará cuenta.
Nota: la mejor manera de aprender sobre las variables del sistema es observar sus valores cuando se está ejecutando un Form. Puede examinar las variables del sistema utilizando el Depurador (Debugger).
Variables de sistema para determinar el estado actual del Form.
También puede usar las siguientes variables de sistema para realizar acciones de acuerdo al valor que estas contengan:
•SYSTEM.RECORD_STATUS
•SYSTEM.BLOCK_STATUS
•SYSTEM.FORM_STATUS
Ejemplo:BEGIN
ENTER;
IF :SYSTEM.BLOCK_STATUS = 'CHANGED' THEN
COMMIT_FORM;
END IF;
CLEAR_BLOCK;
END;
/*En el ejemplo anterior se valida si existen modificaciones en el bloque actual, si las hay se procede a guardar dichas modificaciones (COMMIT_FORM), posteriormente se procede a limpiar dicho bloque (CLEAR_BLOCK).*/
_________________________________________________________________________
El Uso Built-ins para codificación flexible.
Algunos de los Built-ins de Forms Builder proporcionan el mismo tipo de información que proporcionan las variables de sistema.
Algunos Built-ins:
• GET_APPLICATION_PROPERTY
• GET_FORM_PROPERTY
• GET_BLOCK_PROPERTY
• GET_RELATION_PROPERTY
• GET_RECORD_PROPERTY
• GET_ITEM_PROPERTY
• GET_ITEM_INSTANCE_PROPERTY
• GET_LOV_PROPERTY
• GET_RADIO_BUTTON_PROPERTY
• GET_MENU_ITEM_PROPERTY
• GET_CANVAS_PROPERTY
• GET_TAB_PAGE_PROPERTY
• GET_VIEW_PROPERTY
• GET_WINDOW_PROPERTY
• SET_APPLICATION_PROPERTY
• SET_FORM_PROPERTY
• SET_BLOCK_PROPERTY
• SET_RELATION_PROPERTY
• SET_RECORD_PROPERTY
• SET_ITEM_PROPERTY
• SET_ITEM_INSTANCE_PROPERTY
• SET_LOV_PROPERTY
• SET_RADIO_BUTTON_PROPERTY
• SET_MENU_ITEM_PROPERTY
• SET_CANVAS_PROPERTY
• SET_TAB_PAGE_PROPERTY
• SET_VIEW_PROPERTY
• SET_WINDOW_PROPERTY
Algunos Explicaciones:
• GET_APPLICATION_PROPERTY devuelve información sobre la aplicación Forms actual.
Ejemplo:
BEGIN
:GLOBAL.username := GET_APPLICATION_PROPERTY(USERNAME);
:GLOBAL.o_sys := GET_APPLICATION_PROPERTY(OPERATING_SYSTEM);
END;
/*El ejemplo anterior captura el nombre de usuario y la información del sistema operativo.*/
Nota: GET_APPLICATION_PROPERTY devuelve información sobre la aplicación Forms que se ejecuta en el nivel medio (Servidor Forms). Si necesita información sobre la máquina cliente, puede usar los JavaBean.
• GET_BLOCK_PROPERTY devuelve información sobre un bloque específico.
Ejemplo:
...GET_BLOCK_PROPERTY('blockname',top_record)...
/*Este ejemplo muestra como determinar el registro actual que está visible en la primera línea (superior) de un bloque.*/
• GET_ITEM_PROPERTY devuelve información sobre un item especificado.
Ejemplo:
DECLARE cv_name varchar2(30);
BEGIN cv_name := GET_ITEM_PROPERTY(:SYSTEM.CURSOR_ITEM,item_canvas);
...
BEGIN cv_name := GET_ITEM_PROPERTY(:SYSTEM.CURSOR_ITEM,item_canvas);
...
• SET_ITEM_INSTANCE_PROPERTY modifica la instancia del item en cuestión cambiando la propiedad especificada.
Ejemplo:
BEGIN
SET_ITEM_INSTANCE_PROPERTY(:SYSTEM.CURSOR_ITEM, VISUAL_ATTRIBUTE, CURRENT_RECORD, 'VA_CURR');
END;
/*El anterior ejemplo establece el atributo visual en VA_CURR para el registro actual del item en cuestión.*/
• SET_MENU_ITEM_PROPERTY modifica las propiedades dadas de un elemento de menú.
Ejemplo:
SET_MENU_ITEM_PROPERTY ('FILE.SAVE', ENABLED, PROPERTY_TRUE);
/*El ejemplo muestra como habilitar el Item SAVE.*/
.
/*El ejemplo muestra como habilitar el Item SAVE.*/
.
• SET_TAB_PAGE_PROPERTY establece las propiedades de la página de pestañas de la página de lienzo de pestañas especificada.
Ejemplo:
DECLARE
tbpg_id TAB_PAGE;
BEGIN
tbpg_id := FIND_TAB_PAGE('tab_page_1');
IF GET_TAB_PAGE_PROPERTY(tbpg_id, enabled) = 'FALSE' THEN
SET_TAB_PAGE_PROPERTY(tbpg_id, enabled,property_true);
END IF;
END;
/*El anterior ejemplo evalúa el estado de la pestaña 'tab_page_1' y en caso de estar inhabilitada procede a habilitarla.*/
_________________________________________________________________________
Haciendo Referencia a Objetos por el ID Interno.
Forms Builder asigna un ID a cada objeto creado. El ID de objeto es un valor interno que nunca se muestra. Puede obtener la ID de un objeto mediante el uso de los built-ins FIND_object. FIND_object requiere un nombre de objeto que recibe como parámetro.
Los valores de retorno de FIND_object (los ID de objeto) son de un tipo específico. Los tipos de ID de objeto están predefinidos en Forms Builder. Hay un tipo diferente para cada objeto.
¿Por Qué usar Identificadores de Objetos?
• Mejora del rendimiento (Forms busca el objeto una sola vez al llama al built-in FIND_object para obtener el ID. Cuando se refiere a un objeto por nombre en un trigger, Forms debe buscar la ID del objeto cada vez).
• Permite escribir un código más genérico y a la vez más dinámico.
• Permite probar si existe un objeto (usando la función ID_NULL y FIND_object).
Tipos de Objetos FIND_object:
Las Variables para Identificadores de Objetos.
Para usar un ID de objeto, primero debe asignarlo a una variable. La variable debe ser declarada del mismo tipo que la ID del objeto.
El siguiente ejemplo usa el buil-int FIND_ITEM para asignar el ID del item que tiene el foco de entrada a la variable id_var.
DECLARE
id_var item;0
BEGIN
id_var := FIND_ITEM(:SYSTEM.CURSOR_ITEM);
. . .
END;
Una vez que asigna un ID de objeto a una variable en un trigger o unidad de programa PL/SQL, puede usar esa variable para hacer referencia al objeto, en lugar de referirse al objeto por su nombre.
Los ejemplos siguientes muestran que puede pasar tanto el nombre de item como su ID al built-in SET_ITEM_PROPERTY. Las siguientes llamadas son lógicamente equivalentes:
Sin embargo, no puede usar un ID de objeto y un nombre de objeto para formar un nombre compuesto (nombre_de_bloque.nombre_de_elemento). La siguiente llamada es ilegal:
_________________________________________________________________________
ID de Objetos fuera del Bloque PL/SQL Inicial.
Hemos visto como hacer referencia a los ID de objeto dentro de un trigger o unidad de programa mediante variables PL/SQL. Puede hacer referencia a estas variables PL/SQL solo en el bloque PL/SQL actual; sin embargo, puede aumentar el alcance de un ID de objeto.
Para hacer referencia a una ID de objeto fuera del bloque PL/SQL inicial, debe convertir el ID a un formato numérico utilizando una extensión .id para su variable PL/SQL declarada, y luego asignarla a una variable global.
Ejemplo:
En el siguiente ejemplo se asigna la ID del objeto a una variable local de PL/SQL (item_var) inicialmente, luego a una variable global (global.item):
DECLARE
item_var item;
BEGIN
item_var := FIND_ITEM(:SYSTEM.CURSOR_ITEM);
:GLOBAL.item := item_var.id;
END;
Ahora puede pasar la variable global dentro de la aplicación. Para poder reutilizar la ID del objeto, debe volver a convertirla a su tipo de datos original.
Ejemplo:
El siguiente ejemplo muestra la conversión de la variable global a su tipo original de datos variables PL/SQL:
DECLARE
item_var item;
BEGIN
item_var.id := TO_NUMBER(:GLOBAL.item);
GO_ITEM(item_var);
END;
Ejemplo:
DECLARE
tbpg_id TAB_PAGE;
BEGIN
tbpg_id := FIND_TAB_PAGE('tab_page_1');
IF GET_TAB_PAGE_PROPERTY(tbpg_id, enabled) = 'FALSE' THEN
SET_TAB_PAGE_PROPERTY(tbpg_id, enabled,property_true);
END IF;
END;
/*El anterior ejemplo evalúa el estado de la pestaña 'tab_page_1' y en caso de estar inhabilitada procede a habilitarla.*/
_________________________________________________________________________
Haciendo Referencia a Objetos por el ID Interno.
Forms Builder asigna un ID a cada objeto creado. El ID de objeto es un valor interno que nunca se muestra. Puede obtener la ID de un objeto mediante el uso de los built-ins FIND_object. FIND_object requiere un nombre de objeto que recibe como parámetro.
Los valores de retorno de FIND_object (los ID de objeto) son de un tipo específico. Los tipos de ID de objeto están predefinidos en Forms Builder. Hay un tipo diferente para cada objeto.
¿Por Qué usar Identificadores de Objetos?
• Mejora del rendimiento (Forms busca el objeto una sola vez al llama al built-in FIND_object para obtener el ID. Cuando se refiere a un objeto por nombre en un trigger, Forms debe buscar la ID del objeto cada vez).
• Permite escribir un código más genérico y a la vez más dinámico.
• Permite probar si existe un objeto (usando la función ID_NULL y FIND_object).
Tipos de Objetos FIND_object:
Object Class
|
Subprogram
|
Return Type
|
Alertas
|
FIND_ALERT
|
ALERT
|
Bloques
|
FIND_BLOCK
|
BLOCK
|
Canvas
|
FIND_CANVAS
|
CANVAS
|
Editores
|
FIND_EDITOR
|
EDITOR
|
Forms
|
FIND_FORM
|
FORMMODULE
|
Items
|
FIND_ITEM
|
ITEM
|
LOVs
|
FIND_LOV
|
LOV
|
Relaciones
|
FIND_RELATION
|
RELATION
|
Vistas
|
FIND_VIEW
|
VIEWPORT
|
Windows
|
FIND_WINDOW
|
WINDOW
|
Para usar un ID de objeto, primero debe asignarlo a una variable. La variable debe ser declarada del mismo tipo que la ID del objeto.
El siguiente ejemplo usa el buil-int FIND_ITEM para asignar el ID del item que tiene el foco de entrada a la variable id_var.
DECLARE
id_var item;0
BEGIN
id_var := FIND_ITEM(:SYSTEM.CURSOR_ITEM);
. . .
END;
Una vez que asigna un ID de objeto a una variable en un trigger o unidad de programa PL/SQL, puede usar esa variable para hacer referencia al objeto, en lugar de referirse al objeto por su nombre.
Los ejemplos siguientes muestran que puede pasar tanto el nombre de item como su ID al built-in SET_ITEM_PROPERTY. Las siguientes llamadas son lógicamente equivalentes:
SET_ITEM_PROPERTY('ORDERS.order_id',position,50,35);
SET_ITEM_PROPERTY(id_var,position,50,35);
Puede usar identificadores de objetos o nombres de objetos en la misma lista de argumentos, siempre que cada argumento individual se refiera a un objeto distinto.Sin embargo, no puede usar un ID de objeto y un nombre de objeto para formar un nombre compuesto (nombre_de_bloque.nombre_de_elemento). La siguiente llamada es ilegal:
GO_ITEM(block_id.'item_name');
Nota: Es recomendable usar los built-ins FIND_object solo cuando se refiera a un objeto más de una vez en el mismo Trigger o unidad de programa PL/SQL._________________________________________________________________________
ID de Objetos fuera del Bloque PL/SQL Inicial.
Hemos visto como hacer referencia a los ID de objeto dentro de un trigger o unidad de programa mediante variables PL/SQL. Puede hacer referencia a estas variables PL/SQL solo en el bloque PL/SQL actual; sin embargo, puede aumentar el alcance de un ID de objeto.
Para hacer referencia a una ID de objeto fuera del bloque PL/SQL inicial, debe convertir el ID a un formato numérico utilizando una extensión .id para su variable PL/SQL declarada, y luego asignarla a una variable global.
Ejemplo:
En el siguiente ejemplo se asigna la ID del objeto a una variable local de PL/SQL (item_var) inicialmente, luego a una variable global (global.item):
DECLARE
item_var item;
BEGIN
item_var := FIND_ITEM(:SYSTEM.CURSOR_ITEM);
:GLOBAL.item := item_var.id;
END;
Ahora puede pasar la variable global dentro de la aplicación. Para poder reutilizar la ID del objeto, debe volver a convertirla a su tipo de datos original.
Ejemplo:
El siguiente ejemplo muestra la conversión de la variable global a su tipo original de datos variables PL/SQL:
DECLARE
item_var item;
BEGIN
item_var.id := TO_NUMBER(:GLOBAL.item);
GO_ITEM(item_var);
END;
_________________________________________________________________________
Haciendo Referencia a Items Indirectamente.
Al hacer referencia indirectamente a los item, puede escribir un código más genérico y reutilizable. Usando variables en lugar de nombres de item reales, puede escribir una unidad de programa PL/SQL para usar cualquier item cuyo nombre esté asignado a la variable indicada.
Puede hacer referencia indirecta a los item con los built-ins NAME_IN y COPY.
Nota: utilice referencias indirectas cuando cree procedimientos y funciones en un módulo de librería, ya que las referencias directas no se pueden resolver.
Haciendo Referencia a Items Indirectamente.
Al hacer referencia indirectamente a los item, puede escribir un código más genérico y reutilizable. Usando variables en lugar de nombres de item reales, puede escribir una unidad de programa PL/SQL para usar cualquier item cuyo nombre esté asignado a la variable indicada.
Puede hacer referencia indirecta a los item con los built-ins NAME_IN y COPY.
Nota: utilice referencias indirectas cuando cree procedimientos y funciones en un módulo de librería, ya que las referencias directas no se pueden resolver.
Usando el Built-in NAME_IN.
La función NAME_IN devuelve el valor contenido de la variable indicada. Las siguientes sentencias son equivalentes. La primera usa una referencia directa a customer.name, mientras que la segunda usa una referencia indirecta:
Usando el Built-in COPY.
El built-in COPY asigna un valor indicado a una variable o item especifico. A diferencia de la sentencia de asignación estándar de PL/SQL, usar COPY le permite hacer referencia indirectamente al item cuyo valor se está configurando.
Ejemplo:
Usando NAME_IN y COPY.
Utilice los built-ins COPY y NAME_IN para asignar indirectamente un valor a un item cuyo nombre se almacena en una variable global.
Ejemplo:
La función NAME_IN devuelve el valor contenido de la variable indicada. Las siguientes sentencias son equivalentes. La primera usa una referencia directa a customer.name, mientras que la segunda usa una referencia indirecta:
IF :CUSTOMERS.cust_last_name = 'Welles'...
En una librería, puede evitar esta referencia directa al usar:
IF NAME_IN('CUSTOMERS.cust_last_name') = 'Welles'...
El valor de retorno de NAME_IN siempre es una cadena de caracteres. Para usar NAME_IN para un item tipo fecha o numérico, convierta la cadena al tipo de datos deseado con la función de conversión adecuada. Por ejemplo:
date_var := TO_DATE(NAME_IN('ORDERS.order_date'));
Usando el Built-in COPY.
El built-in COPY asigna un valor indicado a una variable o item especifico. A diferencia de la sentencia de asignación estándar de PL/SQL, usar COPY le permite hacer referencia indirectamente al item cuyo valor se está configurando.
Ejemplo:
COPY('Welles','CUSTOMERS.cust_last_name');
Utilice los built-ins COPY y NAME_IN para asignar indirectamente un valor a un item cuyo nombre se almacena en una variable global.
Ejemplo:
COPY('Welles',NAME_IN('global.customer_name_item'));
_________________________________________________________________________
Resumen.
En esta publicación, debes haber aprendido que:
• El código flexible es un código genérico reutilizable que puede usar en cualquier módulo Forms de una aplicación.
• Con las variables del sistema, puede:
---Realizar acciones condicionalmente en función de la ubicación actual (SYSTEM.CURSOR_ [RECORD | ITEM | BLOCK]).
---Utilizar el valor de un item sin conocer su nombre (SYSTEM.CURSOR_VALUE).
---Navegar a la ubicación inicial después de que se complete la ejecución de un trigger: (SYSTEM.TRIGGER_ [RECORD | ITEM | BLOCK]).
---Realizar acciones condicionalmente en función del estado del COMMIT: SYSTEM. [RECORD | BLOCK| FORM] _STATUS.
• Los built-ins [GET | SET] _ <object> _PROPERTY son útil en la codificación flexible.
• El código que hace referencia a los objetos es más eficiente y genérico:
---Por ID interno: use FIND_ <object> built-ins.
---Indirectamente: usando lost built-ins COPY y NAME_IN incorporados.
_________________________________________________________________________• Con las variables del sistema, puede:
---Realizar acciones condicionalmente en función de la ubicación actual (SYSTEM.CURSOR_ [RECORD | ITEM | BLOCK]).
---Utilizar el valor de un item sin conocer su nombre (SYSTEM.CURSOR_VALUE).
---Navegar a la ubicación inicial después de que se complete la ejecución de un trigger: (SYSTEM.TRIGGER_ [RECORD | ITEM | BLOCK]).
---Realizar acciones condicionalmente en función del estado del COMMIT: SYSTEM. [RECORD | BLOCK| FORM] _STATUS.
• Los built-ins [GET | SET] _ <object> _PROPERTY son útil en la codificación flexible.
• El código que hace referencia a los objetos es más eficiente y genérico:
---Por ID interno: use FIND_ <object> built-ins.
---Indirectamente: usando lost built-ins COPY y NAME_IN incorporados.
Fuente: Oracle Forms Developer 10g: Build Internet Applications.