Secciones

Artículos para tus primeros pasos

Si estás empezando a introducirte en el mundo de Groovy y Grails, no te pierdas nuestros artículos básicos: 

Entrevistas con los expertos
 

Los protagonistas te cuentan de qué van los proyectos más importantes del mundo Groovy:


Un proyecto de:
ImaginaWorks
Campus Escuela de Groovy

Groovy: primeros pasos

Evaluación de GStrings a la carta

Pablo Riesgo - jueves 10/07/2008

Hola,

Quiero crear un GString del estilo "hola ${variableMundo}" pero de tal manera que variableMundo no sea evaluada al declararla, si no que pueda ser controlada con un método del tipo GString.evaluate() o .toString()

El código sería parecido al siguiente, y este da un error en la declaracion del GString por no encontrar la variable para evaluarla.

class HolaMundo {

  static def holaMundo = "hola ${variableMundo}"

  statiic def diHolaMundo (String variableMundo)

  {

          // esta es la instruccion ficticia

       println holaMundo.evaluate()

  }

}

 

Si alguien tiene idea de como hacerlo o sabe algo sobre le tema, agradecería que me echara una mano.

 

Un saludo.

Re: Evaluación de GStrings a la carta

Nacho - jueves 10/07/2008

Hola Pablo,

dentro de un bloque ${} puedes poner código Groovy arbitrario, incluyendo llamadas a funciones, así que puedes hacer algo así:

def variable = "Pablo"

def holaMundo = "hola ${diHolaMundo(variable)}"

 

Saludos,

Re: Evaluación de GStrings a la carta

Pablo Riesgo - lunes 14/07/2008

Hola Nacho.

 De entrada gracias por responder. Con el ejemplo que puse intente simplificar el problema para hacerlo mas sencillo e ir al grano.

Sin embargo, lo que realmente necesito es poder evaluar un GString en tiempo de ejecución.

Voy a tratar de explicar como surgió esta necesidad:

Tengo una clase con sus respectivos métodos que devuelven código SMIL, el cúal mezcla unos videos e introduce bloques de texto sobre estos. Estos bloques de texto los he introducido en una variable map para aislar estos bloques de texto de la programación en SMIL

static def mensajes = [

       smil1:[titulo:"Titulo 1", cuerpo:"Cuerpo 1"],

       smil2:[titulo:"Titulo 2", cuerpo:"Cuerpo 2"]

     ]

 

Pero en estos bloques de texto quiero introducir valores pasados como parámetro a los métodos, de manera que:

static def mensajes = [

       smil1:[titulo:"Titulo 1: ${usuario}", cuerpo:"Cuerpo 1"],

       smil2:[titulo:"Titulo 2: ${usuario}", cuerpo:"Cuerpo 2"]

     ]

static metodo1 (String usuario)

{

     return """<!-- codigo SMIL -->

<!-- bloque de texto -->

${mensajes.smil1.titulo}

<!-- bloque de texto -->

 ${mensajes.smil1.cuerpo}

<!-- fin codigo SMIL -->"""

}

 

Este código da un error al compilar por la introducción de la variable sin declarar usuario dentro de mensajes.

Por supuesto, siempre puedo meter ${usuario} a parte dentro del método pero solo queria saber si era posible de alguna manera para conseguir mantener la separación entre mensajes de texto y logica SMIL.

Espero que lo que acabo de escribir no sea incompresible :) y otra vez gracias de antemano.

 

Un saludo,

Pablo.

 

 

Re: Evaluación de GStrings a la carta

srcarro - viernes 18/07/2008

Me da la sensación que estás intentando complicarlo demasiado. No soy un master del GString
(ya quisiese yo...), pero es posible que para lo que necesitas puedas tirar del "obsoleto"
Java y su java.text.MessageFormat. Vamos, algo así como:

------------------------------------------
class Clase {
    static mensajes = [
       smil1:[titulo:"Titulo 1: {0}", cuerpo:"Cuerpo 1"],
       smil2:[titulo:"Titulo 2: {0}", cuerpo:"Cuerpo 2"]
    ]
    
    static fmt(String msg, String valor) {
        java.text.MessageFormat.format(msg, valor)
    }
    
    static metodo(String usuario) {
       return """<!-- codigo SMIL -->
<!-- bloque de texto -->
${fmt(mensajes.smil1.titulo,usuario)}
<!-- bloque de texto -->
 ${fmt(mensajes.smil1.cuerpo,usuario)}
<!-- fin codigo SMIL -->"""
    }
}

println Clase.metodo("luis")

------------------------------------------

He intentado montar algo parecido a lo que tú pretendes: como no tenemos la variable
'usuario', he creado otra, de trabajo, 'usuarioInterno'. Sin embargo, una vez creado
el GString, modificar el valor de dicha variable interna no tiene ningún efecto. Me
da a mi que el hecho de que las Cadenas sean inmutables en Java tiene algo que ver:


------------------------------------------

class Clase {
    static def usuarioInterno = "pepe"
    static def mensajes = [
        smil1:[titulo:"Titulo 1: ${usuarioInterno}", cuerpo:"Cuerpo 1"],
        smil2:[titulo:"Titulo 2: ${usuarioInterno}", cuerpo:"Cuerpo 2"]
    ]

    static metodo(String usuario) {
        usuarioInterno = usuario
        return """<!-- codigo SMIL -->
<!-- bloque de texto -->
${mensajes.smil1.titulo} ${usuarioInterno}
<!-- bloque de texto -->
 ${mensajes.smil1.cuerpo}
<!-- fin codigo SMIL -->"""
}

}

Clase.metodo("Luisito")  // Como si pasas 'jaimito', lo mismo da...

------------------------------------------

Es posible que, utilizando un objeto algo más dinámico para 'usuarioInterno', se pueda
conseguir algo...

Por último, he montado algo con closures. Mi escasa experiencia en Groovy no me permite
asurarlo, pero creo que el rendimiento de esto no es excesivamente bueno. Ahora, eso si,
es casi casi lo que querías:


------------------------------------------

def closMsgs = {usuario ->
   static def mensajes = [
      smil1:[titulo:"Titulo 1: ${usuario}", cuerpo:"Cuerpo 1"],
      smil2:[titulo:"Titulo 2: ${usuario}", cuerpo:"Cuerpo 2"]
   ]
  return mensajes
}

println closMsgs('pepe').smil1.titulo
println closMsgs('paco').smil1.titulo

------------------------------------------

Un saludo,

Enrique

Re: Evaluación de GStrings a la carta

GreenEyed - domingo 20/07/2008

Hola,

Justamente hace unos dias estuve mirandome eso para poder hacer unos logs en los cuales pudiera pasar el formato dinamicamente añadiendo variables por nombre y no por orden, como hace Java. La buena noticia es que al final lo conseguí :)

La cosa acabó así:

messagePattern = .... // Yo lo leo de un fichero de propiedades, pero en fin: un String, que no un GString todavia para que no se ejecute.

def binding =  ["usuario": variableUsuario, "otraVariable": otraVariable... ] // Aqui definimos las variables que vamos a usar para la "sustitucion"

// Se crea un template a partir del texto y el binding usando el SimpleTemplateEngine
SimpleTemplateEngine engine = new SimpleTemplateEngine()
def template = engine.createTemplate(messagePattern).make(binding)

// Obtenemos el valor con un simple toString
mensaje = template.toString()

Y voilà. Lo encontré en un artículo de IBM AlphaWorks perdido.

Saludos

Re: Evaluación de GStrings a la carta

Pablo Riesgo - jueves 24/07/2008

Hola,

Muchas gracias por vuestra ayuda, acabo de leer las soluciones que proponéis.

La solución del closure, Enrique, era mas o menos lo que tenía en la punta de los dedos y no me salía, voy a ver que tal va en cuanto a rendimiento y tal.

Respecto a la última solución por supuesto ni se me había pasado por la cabeza, es una pena que no sea mas accesible desde un GString. Me podrías pasar la URL del articulo del que hablas.

Un saludo,

Pablo.

Re: Evaluación de GStrings a la carta

GreenEyed - domingo 10/08/2008

Hola,

Perdona el retraso pero la verdad es que no frecuento mucho estos foros :).

El artículo donde lo encontré es este:

http://www.ibm.com/developerworks/java/library/j-pg02155/index.html

y buscándolo encontré también este:

http://www.javabeat.net/articles/63-templates-in-groovy-2.html

A ver si algo te sirve.

S!

Responder al hilo | Volver al foro "Groovy: primeros pasos" | Volver a los foros