Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Фреймворк Violet

Глава 22 из книги "Архитектура приложений с открытым исходным кодом", том 1.

Оригинал: "Violet", глава из книги "The Architecture of Open Source Applications"
Автор: Cay Horstmann
Перевод: Н.Ромоданов

22.3. Использование свойств JavaBeans

В золотые деньки использования языка Java на клиентской стороне были разработаны спецификации JavaBeans с целью обеспечить портируемые механизмы для редактирования компонент графического интерфейса GUI в визуальной среде сборки приложений. Предполагалось, что сторонний компонент GUI может быть помещен в любую среду сборки GUI, где его свойства могут быть настроены таким же самым образом, как и стандартные кнопки, текстовые компоненты, и так далее.

В языке Java нет нативных свойств. Вместо этого, могут использоваться свойства JavaBeans, доступ к которым осуществляется при помощи пар методов get и set или указываемых в сопутствующих классах BeanInfo. Кроме того, для визуального редактирования значения свойства могут быть определены редакторы свойств. В JDK даже есть несколько базовых редакторов свойств, например, для типа java.awt.Color.

Фреймворк Violet в полной мере использует спецификации JavaBeans. Например, в классе CircleNode можно пользоваться свойством «цвет» с помощью следующих двух методов:

public void setColor(Color newValue)
public Color getColor()

Ничего большего не требуется. Редактор графов теперь может редактировать цвет узла круглых узлов (рис.22.5).

Рис.22.5: Редактирование цвета кружков с помощью редактора цвета, предлагаемого в JavaBeans по умолчанию

22.4. Хранение полученных результатов

Как и любая программа-редактор, Violet должен сохранять в файле творения пользователя и загружать их позже. Я должен был обратиться к спецификации XMI [3], которая была разработана как общий формат обмена для моделей UML. Я посчитал его громоздким, запутанным, и трудным в использовании. Не думаю, что я был одинок - XMI имел репутацию плохо совместимого языка даже для самых простых моделей [PGL+05].

Я решил просто использовать сериализацию языка Java, однако из-за этого было трудно читать старые версии сериализованного объекта, реализация которого с течением времени изменялась. Эту проблему также предвидели архитекторы JavaBeans, которые разработали формат стандарта XML для долгосрочного хранения данных [4]. Объект языка Java, в случае использования Violet, - диаграмма UML, которая сериализуется как последовательность операторов для построения и модификации объекта. Например:

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.0" class="java.beans.XMLDecoder">
 <object class="com.horstmann.violet.ClassDiagramGraph">
  <void method="addNode">
   <object id="ClassNode0" class="com.horstmann.violet.ClassNode">
    <void property="name">…</void>
   </object>
   <object class="java.awt.geom.Point2D$Double">
    <double>200.0</double>
    <double>60.0</double>
   </object>
  </void>
  <void method="addNode">
   <object id="ClassNode1" class="com.horstmann.violet.ClassNode">
    <void property="name">…</void>
   </object>
   <object class="java.awt.geom.Point2D$Double">
    <double>200.0</double>
    <double>210.0</double>
   </object>
  </void>
  <void method="connect">
   <object class="com.horstmann.violet.ClassRelationshipEdge">
    <void property="endArrowHead">
     <object class="com.horstmann.violet.ArrowHead" field="TRIANGLE"/>
    </void>
   </object>
   <object idref="ClassNode0"/>
   <object idref="ClassNode1"/>
  </void>
 </object>
</java>

Когда класс XMLDecoder читает этот файл, он выполняет эти инструкции (для простоты имена пакетов опущены).

ClassDiagramGraph obj1 = new ClassDiagramGraph();
ClassNode ClassNode0 = new ClassNode();
ClassNode0.setName(…);
obj1.addNode(ClassNode0, new Point2D.Double(200, 60));
ClassNode ClassNode1 = new ClassNode();
ClassNode1.setName(…);
obj1.addNode(ClassNode1, new Point2D.Double(200, 60));
ClassRelationShipEdge obj2 = new ClassRelationShipEdge();
obj2.setEndArrowHead(ArrowHead.TRIANGLE);
obj1.connect(obj2, ClassNode0, ClassNode1);

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

Создание таких файлов осуществляется сравнительно просто. Кодировщик автоматически перечисляет свойства каждого объекта и записывает инструкции set для тех значений свойств, которые отличаются от используемых по умолчанию. Большинство базовых типов данных обрабатываются платформой Java; но я должен был предоставить специальные обработчики для Point2D, Line2D и Rectangle2D. Самое главное, что кодировщик должен знать, что граф может быть сериализован как последовательность вызовов методов addNode и connect:

encoder.setPersistenceDelegate(Graph.class, new DefaultPersistenceDelegate()
{
  protected void initialize(Class type, Object oldInstance,
    Object newInstance, Encoder out)
  {
    super.initialize(type, oldInstance, newInstance, out);
    AbstractGraph g = (AbstractGraph) oldInstance;
    for (Node n : g.getNodes())
      out.writeStatement(new Statement(oldInstance, "addNode", new Object[]
      {
        n,
        n.getLocation()
      }));
    for (Edge e : g.getEdges())
      out.writeStatement(new Statement(oldInstance, "connect", new Object[]
      {
        e, e.getStart(), e.getEnd()
      }));
   }
 });

Как только кодировщик был сконфигурирован, сохранение графа стало выглядеть максимально просто:

encoder.writeObject(graph);

Поскольку декодировщик просто выполняет инструкции, для него настройка не требуется. Графы читаются просто с помощью:

Graph graph = (Graph) decoder.readObject();

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


Продолжение статьи: 22.5. Java WebStart.