miércoles, 5 de julio de 2017

Guia de Implementación de EXTENSIONES GENEXUS - PARTE 5

Crear Objetos GeneXus



  Para cumplir con los objetivos de la extensión en ocasiones se necesita crear objetos GeneXus mediante código fuente, en los siguientes ejemplos se muestran la creación de los objetos: folder, procedure, structured data type, dataprovider, dominio y external object.

Objeto Folder

  Referenciar las siguientes librerias:
Artech.Architecture.Common.Objects
Artech.Architecture.UI.Framework.Services
  Antes de crear cualquier objeto se necesita comprobar si la base de conocimientos está disponible, con el siguiente código:
 if(UIServices.KB != null && UIServices.KB.CurrentModel != null){}

Así se comprueba que la KB y el Modelo están disponibles, entonces puede recién crearse objetos.
  Para crear un folder en el árbol del Folder View de GeneXus:
Se comprueba si el nombre “iQueries” para el Folder existe:
Folder folder = folder = Folder.Get(UIServices.KB.CurrentModel, “iQueries”);
if (folder == null){}
 Entonces se pregunta si el folder (en éste caso “iQueries”) no existe, se procede a crear el folder:
 folder = new Folder(UIServices.KB.CurrentModel);
 folder.Parent = Folder.GetRoot(UIServices.KB.CurrentModel);
 folder.Name = “iQueries”;
 folder.Save();

Objeto Procedure
  Referenciar las siguientes librerias:
 Artech.Architecture.Common.Objects
Artech.Architecture.UI.Framework.Services
Artech.Genexus.Common.Objects
Artech.Genexus.Common

  En el paso anterior se creó el objeto folder, el siguiente procedure que será creado se colocará ahí:

 Recuperar el folder “iQueries”:
 Folder folder = Folder.Get(UIServices.KB.CurrentModel, “iQueries”);

 Comprobar que el procedure no existe:
 Procedure procedure = Procedure.Get(UIServices.KB.CurrentModel, “MiProcedimiento”);
if(procedure == null){}

Se crea y coloca el procedure en el Folder:
procedure = new Procedure(UIServices.KB.CurrentModel);
procedure.Name = “MiProcedimiento”;
procedure.Parent = folder;
procedure.Save();


  NOTA: Para que el objeto procedure aparezca directamente en el árbol de folder view de GeneXus Ev2, se establece la propiedad parent del procedure del siguiente modo:
 procedure.Parent = Folder.GetRoot(UIServices.KB.CurrentModel);
Variables

  Para agregar variables al objeto procedure anterior el siguiente código ayuda a hacerlo:

 Variable variable = new Variable(procedure.Variables);
variable.Name = “query”;
variable.Type = eDBType.VARCHAR; //definimos el tipo
variable.Length = 9999;          //definimos el tamaño                procedure.Variables.Add(var);
procedure.Save();
Source

  Para escribir directamente en el source del procedure, el siguiente código ayuda a hacerlo:

 Utilizando la variable anteriormente creada:

 string source = “&query = ‘Hola mundo con procedure’”;
procedure.ProcedurePart.Source = source;
procedure.Save();
Rules

  Para agregar las rules de in u out en un objeto procedure el siguiente código ejemplifica como hacerlo:

 procedure.Rules.Source = “parm(out:&variable);”;
procedure.Save();

  En la regla se establece a la variable anteriormente creada que será un parámetro out, en caso de querer que sea una rule de in solo se debe sustituir el out por el in.

Structured Data Type

  Referenciar las siguientes librerías:
 Artech.Architecture.Common.Objects
Artech.Architecture.UI.Framework.Services
Artech.Genexus.Common.Objects
Artech.Genexus.Common.Parts.SDT
 Recuperar el folder:
 Folder folder = Folder.Get(UIServices.KB.CurrentModel, “iQueries”);
 Comprobar si el objeto no existe:
 SDT miSdt = SDT.Get(UIServices.KB.CurrentModel, “miSdt”);
if(miSdt == null){}

 Crear y colocar el objeto en el folder:
 miSdt = new SDT(UIServices.KB.CurrentModel);
miSdt.Parent = folder;
miSdt.Name = “miSdt”;

  Agregar un nivel al objeto Structured Data Type y establecer la propiedad IsCollection a True:

 SDTLevel sdtLevel = miSdt.SDTStructure.Root;
sdtLevel.Name = “Item”;
sdtLevel.Items.Clear();
sdtLevel.IsCollection = true;
sdtLevel.CollectionItemName = “Item”;
 Crear y agregar items al level recién creado:
 SDTItem item = new SDTItem(sdtLevel.SDTStructure);
item.Name = “item1”;
item.Type = eDBType.VARCHAR; //definimos el tipo
item.Length = 9999;          //definimos el tamaño
item.IsCollection = false;
sdtLevel.AddItem(item);
miSdt.Save();

DataProvider

  Referenciar las siguientes librerias:
 Artech.Architecture.Common.Objects
Artech.Architecture.UI.Framework.Services
Artech.Genexus.Common.Objects
 Recupera el folder:
 Folder folder = Folder.Get(UIServices.KB.CurrentModel, “iQueries”);
 Comprobar si existe el DataProvider:
 DataProvider dataProvider = DataProvider.Get(UIServices.KB.CurrentModel, “MiDataProvider”);
 if(dataProvider == null){}
 Crear y colocar el DataProvider en el folder:
 dataProvider = new DataProvider(UIServices.KB.CurrentModel);
dataProvider.Name = “MiDataProvider”;
dataProvider.Parent = folder;
dataProvider.Save();

Source

  En éste ejemplo se debe suponer que se tiene el siguiente objeto structured data type como muestra la figura 7:





Figura 7. SDTEjemplo. Fuente. Elaboración propia.

  En la propiedad source del objeto dataprovider establecer la estructura del structured data type, de la siguiente forma:

 dataProvider.DataProviderSource.Source = “jqSelectData\r\n{ Item\r\n { \r\n Id = ‘1’\r\n Descr = ‘Opción 1’ \r\n Selected = False \r\n } \r\n }”;
dataProvider.Save();

Propiedades

  El objeto dataprovider cuenta con el método setpropertyvalue para establecer sus propiedades mediante código fuente, de la siguiente forma:

Propiedad: Expose as Web Service: dataProvider.SetPropertyValue(Properties.DPRV.ExposeAsWebService, true);
Propiedad: CollectioName: dataProvider.SetPropertyValue(Properties.DPRV.CollectionName, “jqSelectData”);

Propiedad: Output:
dataProvider.SetPropertyValue(Properties.DPRV.Output, new KBObjectReference(jqSelectData.Key));       
       
Dominio
  El siguiente código ayuda a crear dominios:
 Recuperar el folder:

 Folder folder = Folder.Get(UIServices.KB.CurrentModel, “iQueries”);
 Comprobar si existe el Dominio:
 Domain miDominio = Domain.Get(UIServices.KB.CurrentModel, “MiDominio”);
 if(miDominio == null){}

 Crear y colocar el Dominio en el folder:
 Domain miDominio = new Domain(UIServices.KB.CurrentModel);
miDominio.Name = “miDominio”;
miDominio.Parent = folder;
miDominio.Type = eDBType.VARCHAR;
miDominio.Length = 256;
miDominio.Save();

External Object

  El objeto External Object (EO) permite al desarrollador agregar funcionalidad a su aplicación. El EO debe tener asociado alguna librería que respalde su comportamiento, la librería debe ser realizada en el mismo lenguaje que la aplicación principal está siendo compilada por GeneXus Ev2.

  Por ejemplo para el caso que la aplicación esté siendo compilada en Java, entonces la librería debería ser un .jar. Del mismo modo para el caso que la aplicación esté siendo compilada en C#, la librería debe ser .dll. De éste modo no se producirá ningún conflicto al momento de compilar la aplicación completa.

  Para crear un external object se debe tener un proyecto que nos genere .dll o .jar según sea el caso.

  El siguiente ejemplo mostrará una clase llamada CLauncher, el cual está hecha en C#, y el nombre del ensamblado es iLauncher.

 namespace iLauncher
{
 public class CLauncher
 {
  public string server;
  public string dbname;
  public string dbmsport;
  public string user;
  public string password;
  public string trusted;
  public string parent;
  public string child;
  public string ns;
   private DataSet dataSet;
  private SqlDataAdapter dataAdapter;
  public CLauncher(){}
   public String ExecuteQueryToXml(string query){
    //Lógica del método
   }
 }
}

 En la lógica del método se puede definir el comportamiento del EO.
  Agregar la librería a GeneXus Ev2, ir al menú Tools, menú contextual Application Integration, el cual muestra las siguientes opciones:

 .Net Assembly Import
 Java Class Import
 WSDL Import
 XML Schema Import

  Para el ejemplo se elegirá la opción .Net Assembly Import, mostrará el siguiente cuadro de diálogo y buscar la ruta donde se encuentra la librería, como muestra la figura 8:



Figura 8. Importación de external object paso 1. Fuente: Elaboración propia.


Presionar Next y mostrará el siguiente cuadro de diálogo como se muestra en la figura 9:



Figura 9. Importación de external object paso 2. Fuente: Elaboración propia.

  No es necesario que se establezcan valores a los campos Prefix y Folder, presionar Next y se muestra el siguiente cuadro de diálogo como se ve en la figura 10:


Figura 10. Importación de external object paso 3. Fuente: Elaboración propia.

  En éste cuadro de diálogo muestra el contenido de la librería, se indica que la librería tiene tres clases definidas: CCondition, CLauncher y CMain. Puede elegirse cuál de ellos se importe en el external object, por cada clase se creará un external object, una vez elegido la clase puede elegirse los atributos y métodos a importar. Luego presionar Import.
  NOTA: Para que los atributos o métodos se muestren tienen que ser declarados como public en la librería, caso contrario se le declaran como private.

 La siguiente figura 11 muestra el external object creado de la clase CLauncher:



Figura 11. External object importado. Fuente: Elaboración propia.

 Note que por cada atributo en la clase se creó una propiedad en el external object y por cada método se creó uno. Observe que los siguientes atributos no se importaron en el external object:

 private DataSet dataSet;
 private SqlDataAdapter dataAdapter;
 Fíjese en la figura 12 las propiedades del external object, el Name, el Namespace y el AssemblyName son las mismas que la librería.



Figura 12: Propiedades del external object importado. Fuente: Elaboración propia.

  NOTA: Una vez agregado el external object es necesario que la librería (en éste caso iLauncher.dll) se copie a la carpeta bin del proyecto:

 Ejemplo: D:\Tesis\Proyecto\Rostros\CSharpModel\web\bin

 Donde:

D:\Tesis\Proyecto: Es el directorio donde está ubicado el proyecto.

Rostros: Nombre del proyecto.

  Luego de importar el external object es necesario que se haga un Rebuild All en el proyecto principal.

¿Cómo utilizamos el External Object?

  Se crea una variable del tipo de external object que se ah importado, en el objeto web panel, como se muestra en la figura 13:



Figura 13: Variable del external object en un web panel. Fuente: Elaboración propia.

En la parte Events del Web Panel:

Establecer valores para las propiedades de la nueva variable.
 &clauncher.parent = ‘SdtQueryRos’
&clauncher.child = ‘SdtQueryRos.Item’
&clauncher.ns = ‘Rostros’
&sqlQuery = ‘select * from ros’

Invocar al método de la variable.

 &sqlResult = &clauncher.ExecuteQueryToXml(&sqlQuery)

martes, 4 de julio de 2017

Guia de Implementación de EXTENSIONES GENEXUS - PARTE 4

Programando Mi Extensión 




¿Cómo crear un menú?
Para la creación de un menú agregar las siguientes referencias al proyecto (Marcos Crispino, 2008).
 Artech.Architecture.UI.Framework
Artech.Common
Artech.Common.Framework
System.Drawing 
En el archivo Package.cs agregar las siguientes directivas:
 using Artech.Architecture.Common.Packages;
using Artech.Architecture.Common.Services;
using Artech.Architecture.UI.Framework.Packages;
using System.Runtime.InteropServices;
using System;
Asegurarse que la clase Package.cs herede de la clase AbstractPackageUI.
public class Package : AbstractPackageUI
Agregar en la clase Package.cs el siguiente atributo: 
public static Guid guid = typeof(Package).GUID;
Crear la clase CommandKeys.cs
Agregar la siguiente directiva:
  using Artech.Common.Framework.Commands;
Agregar el siguiente atributo:
  private static CommandKey cmdMiComando = 
  new CommandKey(Package.guid, “MiPrimerMenu”);
Agregar la siguiente propiedad:
  public static CommandKey MiPrimerMenu {
   get { return cmdMiComando; }
  }

Crear la clase CommandManager.cs
Agregar las siguientes directivas:
  using Artech.Architecture.UI.Framework.Helper;
 using Artech.Architecture.UI.Framework.Services;
 using Artech.Common.Framework.Commands;
 using System.Windows.Forms;
Asegurarse que la clase CommandManager.cs herede de la clase CommandDelegator:
  class CommandManager:CommandDelegator
Crear los métodos siguientes:
  public bool ExecMiComando(CommandData data){
   MessageBox.Show(“Mi primer Menú!”); return true;
  }
  private bool QueryMiComando(CommandData data, 
  ref CommandStatus status) {
   status.State = CommandState.Disabled;
   if(UIServices.KB != null && UIServices.KB.CurrentKB != null){
    status.State = CommandState.Enabled;
   }
  return true;
  }
Crear el constructor y agregar el método AddCommand().
  public CommandManager() {
   AddCommand(CommandKeys.MiPrimerMenu, 
   new ExecHandler(ExecMiComando), 
   new QueryHandler(QueryMiComando));
  }

En el archivo Package.cs agregar la siguiente línea:
 public override void Initialize(IGxServiceProvider services){
  base.Initialize(services);
  AddCommandTarget(new CommandManager());
 }
Por último en el archivo GeneXusPackage.package agregar:
<Commands>
 <CommandDefinition id=’MiPrimerMenu’></CommandDefinition>
</Commands>
<Menus>
 <Menu type=’menubar’>
  <Popup id=’MiPrimerMenu’ name=’MiPrimerMenu’ insertBefore=’Help’>
   <Command refid=’MiPrimerMenu’/>
  </Popup>
 </Menu>
 </Menus>

  Para ver el resultado (ver figura 5) generar la solución del proyecto y abrir directamente el GeneXus Ev2 o presionar F5 (Modo depuración) desde la IDE de Microsoft Visual C# 2005 Express Edition.







Figura 5. Mi primer menú integrado a la IDE GeneXus Ev2. Fuente: Elaboración propia.







¿Cómo llamar una ventana desde el menú contextual?
  Para el desarrollo de la extensión es necesario invocarlo desde la IDE de GeneXus Ev2. En éste caso se invocará a la ventana principal de la extensión desde el menú contextual de Other Tool Windows, para ello ir al menú View y la opción Other Tool Windows del menú contextual.

Agregar las siguientes referencias al proyecto:
 Artech.Architecture.Common
Artech.Architecture.UI.Framework
Artech.Common
Artech.Common.Framework
Artech.Common.Properties
Artech.FrameworkDE
Artech.Udm.Framework
System
System.Drawing
System.Windows.Forms
Crear la clase MiPrimeraVentana.cs
Agregar las siguientes directivas:
  using System;
 using System.Windows.Forms;
 using System.Drawing;
 using Artech.FrameworkDE;
 using Artech.Architecture.UI.Framework.Packages;
 using Artech.Architecture.UI.Framework.Services;
 using Artech.Common.Framework.Commands;
 using Artech.Common.Framework.Selection;
 using System.Runtime.InteropServices;

Conseguir el identificador único global. 
Agregar el identificador único global:
  namespace Identificador.Packages.MiPrimeraExtension
  {
  [Guid(“64984d1c-72f2-4e69-9440-654c9a08eee9”)]
  public class MiPrimeraVentana{}
  }
Asegurarse que la clase herede de las siguientes clases:
AbstractToolWindow, ISelectionListener.
public class MiPrimeraVentana : AbstractToolWindow,ISelectionListener{}

Agregar los siguientes atributos:
private Label mensaje;
public static Guid guid;

En el constructor de la clase agregar la siguiente línea:
public MiPrimeraVentana(){
 this.InitializeComponent();
 UIServices.TrackSelection.Subscribe(Guid.NewGuid(), this);
}

Agregar el siguiente constructor statico:
static MiPrimeraVentana(){
MiPrimeraVentana.guid = typeof(MiPrimeraVentana).GUID;
}

Agregar el método InitializeComponent:

public void InitializeComponent(){
this.mensaje = new Label();
this.mensaje.Name = “lblMensaje”;
this.mensaje.Text = “Mi primera ventana!”;
this.mensaje.Location = new Point(5, 20);
this.mensaje.Font = new Font(“Verdana”, 16F,  System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point,  ((byte)(0)));
this.mensaje.Size = new Size(100, 30);
this.Controls.Add(this.mensaje);
this.SuspendLayout();
this.ResumeLayout(false);
this.PerformLayout();
}

Por último agregar el siguiente método:
public bool OnSelectChange(ISelectionContainer sc){return true;}

Crear la clase CommandKeys.cs
Agregar la siguiente directiva:
  using Artech.Common.Framework.
Commands;

Agregar el siguiente atributo:
  private static CommandKey cmdMiComando = 
  new CommandKey(MiPrimeraVentana.guid, “MiPrimeraVentana”);

Agregar la siguiente propiedad:
  public static CommandKey PrimeraVentana {
   get { return cmdMiComando; }
  }

Crear la clase CommandManager.cs
Agregar las siguientes directivas:
  using Artech.Architecture.UI.Framework.Helper;
 using Artech.Architecture.UI.Framework.Services;
 using Artech.Common.Framework.Commands;
Asegurarse que herede de la clase: CommandDelegator
  class CommandManager:CommandDelegator{}
Agregar los siguientes métodos:

public bool ExecMiComando(CommandData data){
UIServices.ToolWindows.SelectToolWindow(MiPrimeraVentana.guid);
return true;
}
  private bool QueryMiComando(CommandData data, ref CommandStatus  status){
  status.State = CommandState.Disabled;
  if (UIServices.KB != null && UIServices.KB.CurrentKB != null){
   status.State = CommandState.Enabled;
  }
  return true;
 }
Agregar el constructor:
  public CommandManager(){
   AddCommand(CommandKeys.PrimeraVentana, 
   new ExecHandler(ExecMiComando), 
   new QueryHandler(QueryMiComando));
  }
Editar la clase Package.cs
Agregar las siguientes directivas:
  using Artech.Architecture.Common.Packages;
 using Artech.Architecture.Common.Services;
 using Artech.Architecture.UI.Framework.Packages;
 using Artech.Architecture.UI.Framework.Services;
 using Artech.Common.Framework.Selection;
 using System.Runtime.InteropServices;
 using Artech.Architecture.UI.Framework.Controls;
 using System;
Asegurarse que la clase herede de: AbstractPackageUI
public class Package : AbstractPackageUI{}

Agregar el siguiente atributo:
private MiPrimeraVentana ventana;

Agregar la propiedad sobrecargado Name:
  public override string Name{
  get { return “MiPrimeraExtension”; }
 }

Agregar el método sobrecargado CreateToolWindow:
  public override IToolWindow CreateToolWindow(Guid toolWindowId){
   if (toolWindowId.Equals(MiPrimeraVentana.guid)){
    if (ventana == null){
     ventana = new MiPrimeraVentana();
    }
   return ventana;
   }
  return base.CreateToolWindow(toolWindowId);
  }
Editar el archivo GeneXusPackage.package
Agregar la siguientes líneas:
  <ToolWindows>
   <ToolWindow id =’64984d1c-72f2-4e69-9440-  654c9a08eee9’ title=’MiPrimeraVentana’ mdi=’true’/>
 </ToolWindows>


  NOTA: El identificador único global que aparece en la clase MiPrimeraVentana.cs debe coincidir con el identificador único global del id del ToolWindow en el archivo GeneXusPackage.package.
  Para ver el resultado en la IDE de GeneXus Ev2 (ver figura 6), vamos al menú View,  Other Tool Windows, opción MiPrimeraVentana.




Figura 6. MiPrimeraVentana. Fuente: Elaboración propia.


martes, 22 de noviembre de 2016

Guia de Implementación de EXTENSIONES GENEXUS - PARTE 3

  1. Crear Un Proyecto De Extensiones


Iniciar el Microsoft Visual C# 2005 Express Edition. Hacer click en el menú File, en el menú contextual click en Nuevo proyecto, aparecerá el siguiente cuadro de diálogo como se muestra en la figura 3:
D:\Tesis\Imágenes\NP.jpgFigura 3. Crear proyecto extensión paso 1. Fuente: Elaboración propia.
Elegir la plantilla GeneXus Package, colocar nombre al proyecto de extensión y Aceptar, la siguiente figura 4 muestra el siguiente paso.
D:\Tesis\Imágenes\NP2.jpg
Figura 4.  Crear proyecto extensión paso 2. Fuente: Elaboración propia.

Colocar algún identificador, éste aparecerá como el fabricante de la extensión, presionar finalizar.


martes, 15 de noviembre de 2016

Guia de Implementación de EXTENSIONES GENEXUS - PARTE 2

  1. Instalación Genexus X Platform Sdk.

Para descargar el instalador visite el download center de GeneXus (GXtechnical, 2012).
Aquí el enlace para la descarga:
Al instalar se crearán las siguientes carpetas en el directorio de instalación (CommunityWiki, 2006):
  • Bin: Contiene las librerías que pueden ser referenciadas por las extensiones.
  • PackageBuilder: Asistente integrado a Visual Studio 2005 o Visual C# 2005 Express Edition para crear proyectos para el desarrollo de extensiones.
  • PatternBuilder: Asistente integrado a Visual Studio 2005 o Visual C# 2005 Express Edition para crear proyectos para el desarrollo de patterns.
  • Patterns: Contiene las librerías que pueden ser referenciadas en proyectos de desarrollo de patterns.
  • Samples: Conjunto de proyectos que muestran diferentes posibilidades de extensiones.
  • Schemas: Contiene el archivo en formato de lenguaje de marcas extensible (XML por sus siglas en inglés eXtensible Markup Language)  que posee las diferentes configuraciones que la extensión puede tomar al acoplarse al Entorno de Desarrollo Integrado (IDE) de GeneXus Ev2.

        Resultado de imagen para genexus extensions