2.3. Связь с данными

Реализовано два варианта передачи данных в диаграмму: через интерфейс DataProvider и с использованием упрощённого API, позволяющего привязывать данные напрямую при помощи метода addData() и удобных конструкторов класса MapDataItem. Последний способ подходит для диаграмм, для которых не определен контейнер данных. В главе Пример работы с диаграммами проиллюстрированы все способы получения данных.

DataProvider:

Интерфейс DataProvider имеет две стандартные реализации: класс ListDataProvider и класс ContainerDataProvider.

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

    • EntityDataItem принимает экземпляр сущности, из которой будут браться данные для диаграммы:

      @Inject
      private PieChart chart;
      
      @Inject
      private Metadata metadata;
      
      @Subscribe
      protected void onInit(InitEvent event) {
          ListDataProvider dataProvider = new ListDataProvider();
          dataProvider.addItem(new EntityDataItem(valueDescription(75, "Sky")));
          dataProvider.addItem(new EntityDataItem(valueDescription(7, "Shady side of pyramid")));
          dataProvider.addItem(new EntityDataItem(valueDescription(18, "Sunny side of pyramid")));
      
          chart.setDataProvider(dataProvider);
      }
      
      private ValueDescription valueDescription(Integer value, String description) {
          ValueDescription entity = metadata.create(ValueDescription.class);
          entity.setValue(value);
          entity.setDescription(description);
          return entity;
      }
    • MapDataItem содержит набор пар ключ-значение, из которого будут браться данные для диаграммы:

      @Inject
      private PieChart chart;
      
      @Subscribe
      protected void onInit(InitEvent event) {
          ListDataProvider dataProvider = new ListDataProvider();
          dataProvider.addItem(new MapDataItem(
                  ImmutableMap.of("value", 75, "description", "Sky")));
          dataProvider.addItem(new MapDataItem(
                  ImmutableMap.of("value", 7, "description", "Shady side of pyramid")));
          dataProvider.addItem(new MapDataItem(
                  ImmutableMap.of("value", 18, "description", "Sunny side of pyramid")));
      
          chart.setDataProvider(dataProvider);
      }
    • SimpleDataItem принимает экземпляр любого public класса, из которого будут браться данные для диаграммы:

    @Inject
    private PieChart chart;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        ListDataProvider dataProvider = new ListDataProvider();
        dataProvider.addItem(new SimpleDataItem(new ValueDescription(75, "Sky")));
        dataProvider.addItem(new SimpleDataItem(new ValueDescription(7, "Shady side of pyramid")));
        dataProvider.addItem(new SimpleDataItem(new ValueDescription(18, "Sunny side of pyramid")));
    
        chart.setDataProvider(dataProvider);
    }
    
    public class ValueDescription {
        private Integer value;
        private String description;
    
        public ValueDescription(Integer value, String description) {
            this.value = value;
            this.description = description;
        }
    
        public Integer getValue() {
            return value;
        }
    
        public String getDescription() {
            return description;
        }
    }
  • ContainerDataProvider используется для связи CollectionContainer с компонентом диаграммы.

    Предположим, имеется контейнер данных с загрузчиком, который получает список экземпляров сущности TransportCount. Ниже приведен фрагмент XML-дескриптора экрана:

    <data>
        <collection id="transportCountsDc"
                    class="com.company.sampler.entity.TransportCount"
                    view="_local">
            <loader id="transportCountsDl">
                    <query><![CDATA[select e from sampler_TransportCount e order by e.year]]></query>
            </loader>
        </collection>
    </data>
    <layout>
        <chart:serialChart id="stackedArea"
                           marginLeft="0"
                           marginTop="10"
                           plotAreaBorderAlpha="0"
                           height="100%"
                           width="100%">
            <!--...-->
        </chart:serialChart>
    </layout>

    В контроллере экрана определяется метод onInit(), который задает провайдер данных для диаграммы stackedArea. Провайдер данных создан на основе контейнера данных transportCountsDc.

    @UiController("sampler_StackedareaChartSample")
    @UiDescriptor("stackedarea-chart-sample.xml")
    @LoadDataBeforeShow
    public class StackedareaChartSample extends Screen {
    
        @Inject
        private CollectionContainer<TransportCount> transportCountsDc;
    
        @Inject
        private SerialChart stackedArea;
    
        @Subscribe
        private void onInit(InitEvent event) {
            stackedArea.setDataProvider(new ContainerDataProvider(transportCountsDc));
            stackedArea.setCategoryField("year");
        }
    }

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

Экземпляр DataProvider передается методу setDataProvider() конфигурации диаграммы. Данный способ предоставления данных для диаграммы наиболее универсален, однако требует создания экземпляров DataProvider или DataItem в коде контроллера экрана.

Используемые для отображения свойства сущности или значения, содержащиеся в экземпляре DataProvider, задаются в атрибутах диаграммы, причем атрибуты различаются для разных типов диаграмм. Например для компонента chart:pieChart необходимо задать атрибуты valueField и titleField.В качестве значений могут выступать типы Integer, Long, Double, String, Boolean, Date.

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

Элемент chart:data:

Этот способ удобен для быстрого прототипирования диаграмм. Элемент chart:data и вложенные в него элементы item позволяют вручную указать фиксированные значения прямо в XML-дескрипторе диаграммы, например:

<chart:pieChart id="pieChart"
                titleField="key"
                valueField="value">
    <chart:data>
        <chart:item>
            <chart:property name="key" value="piece of apple pie"/>
            <chart:property name="value" value="70" type="int"/>
        </chart:item>
        <chart:item>
            <chart:property name="key" value="piece of blueberry pie"/>
            <chart:property name="value" value="20" type="int"/>
        </chart:item>
        <chart:item>
            <chart:property name="key" value="piece of cherry pie"/>
            <chart:property name="value" value="10" type="int"/>
        </chart:item>
    </chart:data>
</chart:pieChart>