public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
    ChartModel chartModel = (ChartModel) value;
    if (chartModel.getChartEngineId() != null) {
      writer.addAttribute("chartEngine", chartModel.getChartEngineId());
    }

    if (chartModel.getTheme() != null) {
      writer.addAttribute("theme", chartModel.getTheme().toString());
    }

    if (chartModel.getStyle().size() > 0) {
      writer.addAttribute("style", chartModel.getStyle().getStyleString());
    }

    if ((chartModel.getTitle() != null)
        && (chartModel.getTitle().getText() != null)
        && (chartModel.getTitle().getText().length() > 0)) {
      ExtendedHierarchicalStreamWriterHelper.startNode(
          writer, "title", chartModel.getTitle().getClass());
      context.convertAnother(chartModel.getTitle());
      writer.endNode();
    }

    for (StyledText subtitle : chartModel.getSubtitles()) {
      if ((subtitle.getText() != null) && (subtitle.getText().trim().length() > 0)) {
        ExtendedHierarchicalStreamWriterHelper.startNode(writer, "subtitle", subtitle.getClass());
        context.convertAnother(subtitle);
        writer.endNode();
      }
    }

    if ((chartModel.getLegend() != null) && chartModel.getLegend().getVisible()) {
      ExtendedHierarchicalStreamWriterHelper.startNode(
          writer, "legend", chartModel.getLegend().getClass());
      context.convertAnother(chartModel.getLegend());
      writer.endNode();
    }

    if (chartModel.getPlot() != null) {
      String plotType = chartModel.getPlot().getClass().getSimpleName();
      plotType = plotType.substring(0, 1).toLowerCase() + plotType.substring(1);
      ExtendedHierarchicalStreamWriterHelper.startNode(
          writer, plotType, chartModel.getPlot().getClass());
      context.convertAnother(chartModel.getPlot());
      if (chartModel.getPlot() instanceof PiePlot) {
        PiePlot piePlot = (PiePlot) chartModel.getPlot();
        if (piePlot.getLabels().getVisible()) {
          ExtendedHierarchicalStreamWriterHelper.startNode(
              writer, "labels", piePlot.getLabels().getClass());
          context.convertAnother(piePlot.getLabels());
          writer.endNode();
        }
      }
      if (chartModel.getPlot() instanceof TwoAxisPlot) {
        TwoAxisPlot twoAxisPlot = (TwoAxisPlot) chartModel.getPlot();

        Axis xAxis = twoAxisPlot.getHorizontalAxis();
        ExtendedHierarchicalStreamWriterHelper.startNode(
            writer, "horizontalAxis", xAxis.getClass());
        context.convertAnother(xAxis);
        writer.endNode();

        Axis yAxis = twoAxisPlot.getVerticalAxis();
        ExtendedHierarchicalStreamWriterHelper.startNode(writer, "verticalAxis", yAxis.getClass());
        context.convertAnother(yAxis);
        writer.endNode();

        Grid grid = twoAxisPlot.getGrid();
        if (grid.getVisible()) {
          ExtendedHierarchicalStreamWriterHelper.startNode(writer, "grid", grid.getClass());
          context.convertAnother(grid);
          writer.endNode();
        }
      }
      writer.endNode();
    }
  }
  public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {

    ChartModel chartModel = new ChartModel();
    chartModel.setChartEngineId(reader.getAttribute("chartEngine"));

    String attribute = reader.getAttribute("theme");
    if (attribute != null) {
      try {
        chartModel.setTheme(Enum.valueOf(ChartTheme.class, attribute.toUpperCase()));
      } catch (Exception e) {
        // Do nothing
      }
    }

    String cssStyle = reader.getAttribute("style");
    if (cssStyle != null) {
      chartModel.getStyle().setStyleString(cssStyle);
    }

    while (reader.hasMoreChildren()) {
      reader.moveDown();
      if (reader.getNodeName().equals("title")) {
        String title = reader.getValue();
        if (title != null) {
          chartModel.getTitle().setText(title);
        }
        cssStyle = reader.getAttribute("style");
        if (cssStyle != null) {
          chartModel.getTitle().getStyle().setStyleString(cssStyle);
        }
        attribute = reader.getAttribute("location");
        if (attribute != null) {
          try {
            chartModel
                .getTitle()
                .setLocation(Enum.valueOf(TitleLocation.class, attribute.toUpperCase()));
          } catch (Exception e) {
            // Do nothing
          }
        }
      } else if (reader.getNodeName().equals("subtitle")) {
        String subtitle = reader.getValue();
        if ((subtitle != null) && (subtitle.trim().length() > 0)) {
          StyledText styledText = new StyledText(subtitle);
          cssStyle = reader.getAttribute("style");
          if (cssStyle != null) {
            styledText.getStyle().setStyleString(cssStyle);
          }
          chartModel.getSubtitles().add(styledText);
        }
      } else if (reader.getNodeName().equals("legend")) {
        chartModel.getLegend().setVisible(true);
        cssStyle = reader.getAttribute("style");
        if (cssStyle != null) {
          chartModel.getLegend().getStyle().setStyleString(cssStyle);
        }
      } else if (reader.getNodeName().equals("barPlot")
          || reader.getNodeName().equals("linePlot")
          || reader.getNodeName().equals("areaPlot")
          || reader.getNodeName().equals("piePlot")
          || reader.getNodeName().equals("dialPlot")
          || reader.getNodeName().equals("scatterPlot")) {
        chartModel.setPlot(createPlot(reader));
      }
      reader.moveUp();
    }

    return chartModel;
  }