Содержание


Практически Groovy

Разметка с помощью Groovy Builders

Сконцентрируйтесь на приложении, а не на деталях языков разметки

Comments

Серия контента:

Этот контент является частью # из серии # статей: Практически Groovy

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Практически Groovy

Следите за выходом новых статей этой серии.

Несколько месяцев назад, когда я впервые написал про разработку сценариев Ant с помощью Groovy (En), я упомянул концепцию Builders в Groovy. В той статье я показал, как легко строить сложные build-файлы в Ant с помощью класса Groovy, который называется AntBuilder. В данной статье я углублюсь в мир Groovy Builders, чтобы продемонстрировать другие возможности этих мощных классов.

Использование Builders

Groovy Builders позволяют без особых усилий имитировать языки разметки, такие как XML, HTML, задачи Ant и даже графические оболочки на основе таких сред, как Swing. С помощью этого инструмента можно быстро создавать сложные типы разметок, такие как XML, при этом не имя дела с самим XML.

Принцип работы Builder довольно прост. Методы, прикрепленные к экземпляру Builder, соответствуют элементам некоторой разметки (как, например тег <body> в HTML). Объекты, созданные внутри замыканий, прикрепленных к методам, представляют собой узлы-потомки (например, тег <p> внутри оборачивающего его тега <body>).

Для наглядности я создам простой Builder, который программно представляет XML-документ, имеющий структуру, показанную в Листинге 1.

Листинг 1. Простая XML-структура
 <person>
   <name first="Megan" last="Smith">
     <age>32</age>
     <gender>female</gender>
   </name>
   <friends>
     <friend>Julie</friend>
     <friend>Joe</friend>
     <friend>Hannah</friend>
   </friends>
 </person>

Создать представление такой структуры довольно легко. Сначала я прикрепляю метод person к экземпляру Builder, после чего последний начинает играть роль корневого узла XML <person>. Для создания узлов-потомков я создаю замыкание и объявляю новый объект name, который принимает параметры в виде map. Эти параметры, кстати, образуют основу атрибутов, прикрепленных к элементу.

Затем внутри объекта name я помещаю замыкание с двумя дополнительными объектами, age и gender, соответствующими аналогичным элементам-потомкам <name>. Вы уже поняли, в чем дело? Все очень просто.

Элементы <friends> и <person> имеют общего родителя, так что я выхожу из замыкания, объявляю объект friends и, конечно, прикрепляю замыкание, содержащее набор элементов friend, как показано в Листинге 2.

Листинг 2. Легкость использования Builders
import groovy.xml.*
import java.io.*

class XMLBuilder{

  static void main(args) {

    writer = new StringWriter()	 	
    builder = new MarkupBuilder(writer)
    friendnames = [ "Julie", "Joey", "Hannah"]

	builder.person() {
       name(first:"Megan", last:"Smith") {
         age("33")
         gender("female")
       }
       friends() {
         for (e in friendnames) { friend(e) }
       }
    }
    println writer.toString()
  }
}

Как видно, представление Groovy достаточно изящно и с легкостью сопоставляется с представлением соответствующей разметки. Внутри этого представления, очевидно, Groovy самостоятельно обрабатывает громоздкие элементы разметки (такие как < и >), позволяя сконцентрироваться на содержании, а не на особенностях структуры.

Как это работает с HTML

Builders могут также облегчить создание HTML, что может пригодиться при разработке Groovlets. В качестве простейшего примера представим, что мне нужно создать простую HTML-страницу, как в Листинге 3.

Листинг 3. HTML 101
 <html>
  <head>
   <title>Groov'n with Builders</title>
  </head>
  <body>
   <p>Welcome to Builders 101. As you can see this Groovlet is fairly simple.</p>
  </body>
 </html>

Я могу легко создать ее с помощью Groovy, как показано в Листинге 4.

Листинг 4. HTML 101 на Groovy
import groovy.xml.*
import java.io.* 

class HTMLBuilderExample{

  static void main(args) {
   writer = new StringWriter()	 	
   builder = new MarkupBuilder(writer)

   builder.html(){
     head(){
       title("Groov'n with Builders"){}
     }
     body(){
       p("Welcome to Builders 101. As you can see " +
         "this Groovlet is fairly simple.") 
     }
   }
   println writer.toString()
}

Давайте позабавимся еще и посмотрим, как просто создать полноценный графический интерфейс с помощью Builders. Ранее я упоминал, что класс Groovy SwingBuilder позволяет с легкостью создать графический интерфейс. В Листинге 5 показано, как работает SwingBuilder.

Листинг 5. GUI Builders на Groovy
import java.awt.FlowLayout
import javax.swing.*
import groovy.swing.SwingBuilder

class SwingExample{

  static void main(args) {
    swinger = new SwingBuilder()
    langs = ["Groovy", "Ruby", "Python", "Pnuts"]

	gui = swinger.frame(title:'Swinging with Groovy!', size:[290,100]) {
      panel(layout:new FlowLayout()) {
        panel(layout:new FlowLayout()) {
          for (lang in langs) {
            checkBox(text:lang)
          }
        }
        button(text:'Groovy Button', actionPerformed:{ 
swinger.optionPane(message:'Indubitably Groovy!').createDialog(null, 'Zen Message').show()
        })
        button(text:'Groovy Quit', actionPerformed:{ System.exit(0)})
     }
   }
   gui.show()
   }
}

А результат приведен на рис. 1. Неплохо, правда?

Рис. 1. Простой пример графического интерфейса на Groovy
Простой пример графического интерфейса на Groovy
Простой пример графического интерфейса на Groovy

Легко представить, насколько такой мощный инструмент как SwingBuilder может быть полезен для разработки прототипов.

Теперь посложнее

Эти примеры были очень простыми, хотя и забавными. Надеюсь, что я показал возможности Groovy Builders, позволяющие избегать базовых элементов разметки определенных языков, таких, как XML. Очевидно, что иногда предпочтительнее избегать XML или HTML , а средства, облегающие создание разметки для платформы Java™ , уже существуют. Например, одна из моих любимых сред, помогающих создавать XML – это JiBX.

С помощью JiBX можно легко связать структуру XML с объектной моделью, и наоборот. Связывание – это мощная парадигма, для реализации которой существует множество инструментов, таких как JAXB, Castor и Zeus.

Единственный недостаток подобных сред для связывания – они могут быть весьма сложны в работе. К счастью, Groovy Builders предоставляет более простое и зачастую не менее эффективное решение.

Псевдосвязывание с помощью Builders

Представьте на мгновение, что имеется простая база данных, представляющая словарь английских слов. Существует таблица для слов (words), их определений (definitions) и, наконец, таблица для синонимов (synonyms). На рис. 2 показано простое представление этой базы данных.

Рис. 2. База данных словаря
База данных словаря
База данных словаря

Как видно, структура этой базы данных несложна: слова (words) связаны отношением типа один-ко-многим с определениями (definitions) и синонимами (synonyms).

В базе данных существует клиент, который потребляет структуру XML, отражающую основные принципы устройства содержимого этой базы данных. Искомая структура XML приведена в Листинге 6.

Листинг 6. XML, необходимый для словаря
<words>
  <word spelling="glib" partofspeech="adjective">
    <defintions>
      <defintion>Performed with a natural, offhand ease.</defintion>
      <defintion>Marked by ease and fluency of speech or writing that often suggests 
	  or stems from insincerity, superficiality, or deceitfulness</defintion>
    </defintions>
    <synonyms>
      <synonym spelling="artful"/> 
      <synonym spelling="urbane"/> 
    </synonyms>
  </word>	
</words>

Если вы решите реализовать это с помощью сред для связывания данных, таких как JiBX, то, вероятнее всего, придется создать некую промежуточную объектную модель, чтобы перейти от реляционной модели к необходимой модели XML. Затем придется переносить содержимое базы данных в эту промежуточную объектную модель, а потом использовать основную среду связывания данных для преобразования структуры промежуточной объектной модели в формат XML.

В этом процессе подразумевается также связывание среды с форматом XML (с помощью процедур выбранной среды). Некоторые среды, такие как JAXB,в действительности создают Java-объекты из XML и других сред, например JiBX, тем самым позволяя связать определенным образом ваши Java-объекты с форматом XML. В любом случае это может потребовать большого количества работы.

С другой стороны, труд – благородное дело. Я не выступаю против использования сред для связывания данных, а просто предупреждаю. А теперь я хочу показать более быстрый путь к созданию вышеупомянутого XML.

Быстрое создание XML, готовых к использованию

Используя Groovy MarkupBuilder вместе с новой уже знакомой вам инфраструктурой доступа к базам данных GroovySql, можно легко создавать готовые к использованию XML-файлы. Надо только понять, какие запросы вам потребуются, и связать результаты с экземпляром Builder. Вы сразу получите XML-документ, отражающий содержимое базы данных словаря.

Давайте шаг за шагом пройдем этот процесс. Сперва необходимо создать экземпляр Builder, в данном случае MarkupBuilder, потому что мы создаем XML. Самый наружным (корневым) элементом является words, поэтому нужно создать метод words. В замыкании сначала вызывается первый запрос, а его результаты связываются в итераторе с узлом-потомком word.

Затем необходимо создать два узла-потомка word с помощью двух новых запросов. Мы создаем объект definitions и связываем его в итераторе, а затем проделываем нечто подобное с synonyms.

Листинг 7. Собираем все вместе с помощью Builders
import groovy.sql.Sql
import groovy.xml.MarkupBuilder
import java.io.File
import java.io.StringWriter

class WordsDbReader{
  static void main(args) {
    sql = Sql.newInstance("jdbc:mysql://localhost/words", 
      "words", "words", "org.gjt.mm.mysql.Driver")
    writer = new StringWriter()	 	
    builder = new MarkupBuilder(writer)
    builder.words() {
      sql.eachRow("select word_id, spelling, part_of_speech from word"){ row |
        builder.word(spelling:row.spelling, partofspeech:row.part_of_speech){

		 builder.definitions(){
sql.eachRow("select definition from definition where word_id = ${row.word_id}"){ defrow |
              builder.definition(defrow.definition)
            }
         }

		 builder.synonyms(){  		       		
  sql.eachRow("select spelling from synonym where word_id = ${row.word_id}"){ synrow |
              builder.synonym(synrow.spelling)
            }		       					       		
         }
       }
      }
    }
   new File("dbouuput.xml").withPrintWriter{ pwriter |
      pwriter.println writer.toString()
   }
 }
}

Заключение

Приведенный пример связывания кажется предельно простым, особенно с точки зрения приверженцев «чистого» Java. Хотя это решение ничем не лучше того, которое можно было бы создать с помощью связывающей среды, такой как JABX или JiBX, оно безусловно быстрее, и я бы даже сказал, что легче. Мог бы я сделать что-нибудь подобное на обычном Java? Конечно, но при этом в какой-то момент мне бы пришлось иметь дело с XML.

Скорость и простота разработки с использованием Groovy Builders будут полезны в случаях, когда необходимо использовать разметку. Например, как было показано во втором примере, мне удалось очень быстро создать XML, представляющий базу данных. Builders также очень удобны, когда дело касается макетирования или когда необходимо разработать рабочее решение в сжатые сроки, используя при этом минимальное количество ресурсов.

О чем я расскажу в следующем месяце в Практически Groovy? Конечно же, об использовании Groovy в Java!


Ресурсы для скачивания


Похожие темы

  • Ознакомьтесь с полным набором статей Практически Groovy, каждая из которых развивает темы предыдущих. В частности, к этой статье имеют отношение:

  • Более подробно ознакомиться со связывающими инфраструктурами (включая JiBX) можно в серии статей Денниса Сосноски (Dennis Sosnoski), посвященных технологиям XML и Java (EN) (developerWorks, январь 2003 г.).
  • Статьи обо всех аспектах программирования на Java можно найти в разделе Java-технологий сайта developerWorks Россия.

Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java, XML
ArticleID=261486
ArticleTitle=Практически Groovy: Разметка с помощью Groovy Builders
publish-date=10122007