Статьи

Модульность, Groovy и общие файловые системы

Давайте используем метод «ModuleInstall.restored», показанный в предыдущей части (где я представил модульный подход к разработке приложений на Groovy), чтобы создать наш Groovy UI:

@Override
public void restored() {
SwingBuilder builder = new SwingBuilder()
Frame gui = builder.frame(size: [290, 100],
title: 'Swinging with Groovy!') {
panel(layout: new FlowLayout()) {
button(text: 'Groovy Button', actionPerformed: {
builder.optionPane(message: 'Indubitably Groovy!').
createDialog(null, 'Zen Message').show()
})
button(text: 'Groovy Quit',
actionPerformed: {System.exit(0)})
}
}
gui.show()
}

Выше приведен небольшой фрагмент одного из примеров отличного Groovy Tutorial Пола Кинга (PDF) . ModuleInstall.restored вызывается, когда модуль загружается приложением, частью которого он является. На этом этапе Groovy UI создан. (Это совершенно нестандартный способ работы с платформой NetBeans, однако имеет смысл, если вы хотите придерживаться Groovy-подхода к разработке пользовательского интерфейса, а не использовать компоненты платформы NetBeans.)

Теперь вы можете запустить приложение и увидеть свой Groovy UI поверх контейнера среды выполнения NetBeans. Но какой в ​​этом смысл? Зачем вообще добавлять Runtime Container (5 модулей NetBeans, которые необходимы для запуска приложений на платформе NetBeans)?

Помните, что такой контейнер времени выполнения предназначен для решения общих инфраструктурных задач. ( Смотрите этот скринкаст для получения подробной информации. ) В этой статье мы в основном выигрываем от модульности контейнера среды выполнения NetBeans вместе с файловой системой, которую все модули в приложении могут совместно использовать друг с другом.

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

@Override
public void restored() {
SwingBuilder builder = new SwingBuilder()
Frame gui = builder.frame(size: [290, 100],
title: 'Swinging with Groovy!') {
panel(layout: new FlowLayout()) {
2.times {
button(text: 'Groovy Button', actionPerformed: {
builder.optionPane(message: 'Indubitably Groovy!').
createDialog(null, 'Zen Message').show()
})
}
// button(text: 'Groovy Quit',
// actionPerformed: {System.exit(0)})
}
}
gui.show()
}

Итак, обратите внимание на кнопки выше. Вместо жесткого кодирования два, мы дважды повторяем цикл, а затем заканчиваем нашими кнопками, которые для простоты будут выполнять то же действие. Теперь, в контексте модульного приложения, мы можем предложить разные дистрибутивы нашего приложения для разных пользователей. Одному набору пользователей могут понадобиться две кнопки, а другому набору пользователей (например, администраторам) могут потребоваться три кнопки.

Вот где общая файловая система вступает в игру. Каждый модуль в приложении может участвовать в общей файловой системе. Итак, допустим, мы создаем дистрибутив для наших администраторов. У нас будут те же модули, что и раньше, плюс дополнительный, который содержит только файл layer.xml, который является XML-файлом, зарегистрированным в манифесте для предоставления вкладов файловой системы модуля. В этом случае файл layer.xml содержит следующие записи:

<folder name="buttons"> 
<file name="One">
<attr name="position" intvalue="100"/>
</file>
<file name="Two">
<attr name="position" intvalue="200"/>
</file>
<file name="Three">
<attr name="position" intvalue="300"/>
</file>
</folder>

Для другого набора пользователей, то есть тех, кто не является администратором, мы не включили бы модуль, который предоставляет файл слоя с содержимым выше. Вместо этого специально для этих пользователей будет отдельный модуль с таким содержимым:

<folder name="buttons"> 
<file name="One">
<attr name="position" intvalue="100"/>
</file>
<file name="Two">
<attr name="position" intvalue="200"/>
</file>
</folder>

И затем, чтобы загрузить записи из файла слоя и установить значения в кнопках на основе этих записей, мы переписали бы метод «ModuleInstall.restored» следующим образом:

@Override
public void restored() {

FileObject buttons = Repository.getDefault().getDefaultFileSystem().findResource("buttons");

SwingBuilder builder = new SwingBuilder()
Frame gui = builder.frame(size: [290, 100],
title: 'Swinging with Groovy!') {
FileObject[] kids = buttons.getChildren();
panel(layout: new FlowLayout()) {
for (FileObject kid : FileUtil.getOrder(Arrays.asList(kids), true)) {
button(
text: kid.getName(), actionPerformed: {
builder.optionPane(message: 'Indubitably Groovy!').
createDialog(null, 'Zen Message').show() )
}
}
}
gui.show()

}

Здесь мы просто создаем столько кнопок, сколько их зарегистрировано в общей файловой системе, а затем присваиваем тексту этих кнопок имя виртуальных файлов, зарегистрированных в общей файловой системе. Запустите приложение и, в зависимости от того, какой из двух дополнительных модулей доступен, у вас будет две или три кнопки:

Порядок, в котором отображаются кнопки, задается в файле layer.xml в сочетании с вызовом «FileUtil.getOrder» в коде. Все это стало возможным благодаря API-интерфейсу файловой системы NetBeans , который представляет собой API-интерфейс Java для анализа общей файловой системы и обработки ее содержимого как объектов Java. Вышеприведенный пример довольно тривиален, но можно представить себе очень большое распределенное приложение с множеством настроек, предоставляемых в разных модулях, что позволяет собирать дистрибутивы для разных клиентов, в зависимости от их потребностей … без изменения одного строка Groovy кода. Ненужные накладные расходы для небольших приложений Groovy, но очень удобно для очень больших распределенных модульных приложений Groovy.