public void write(final OutputRepository outputRepository) throws IOException {
    if (isEmpty()) {
      return;
    }

    final DefaultTagDescription tagDescription = new DefaultTagDescription();
    tagDescription.configure(JFreeReportBoot.getInstance().getGlobalConfig(), TAG_DEF_PREFIX);

    final OutputStream manifestOutputStream =
        outputRepository.createOutputStream("META-INF/manifest.xml", "text/xml");

    final OutputStreamWriter writer = new OutputStreamWriter(manifestOutputStream, "UTF-8");
    final XmlWriter xmlWriter = new XmlWriter(writer, tagDescription);
    xmlWriter.setAlwaysAddNamespace(true);
    xmlWriter.writeXmlDeclaration("UTF-8");

    final AttributeList rootAttributes = new AttributeList();
    rootAttributes.addNamespaceDeclaration("manifest", MANIFEST_NS);
    xmlWriter.writeTag(MANIFEST_NS, "manifest", rootAttributes, XmlWriterSupport.OPEN);

    final Iterator<Map.Entry<String, String>> iterator = entries.entrySet().iterator();
    while (iterator.hasNext()) {
      final Map.Entry<String, String> entry = iterator.next();
      final AttributeList entryAttrs = new AttributeList();
      entryAttrs.setAttribute(MANIFEST_NS, "media-type", entry.getValue());
      entryAttrs.setAttribute(MANIFEST_NS, "full-path", entry.getKey());
      xmlWriter.writeTag(MANIFEST_NS, "file-entry", entryAttrs, XmlWriterSupport.CLOSE);
    }

    xmlWriter.writeCloseTag();
    xmlWriter.close();
  }
  public static void writeExpression(
      final WriteableDocumentBundle bundle,
      final BundleWriterState state,
      final Expression expression,
      final XmlWriter writer,
      final String namespaceUri,
      final String expressionTag)
      throws IOException, BundleWriterException {
    if (state == null) {
      throw new NullPointerException();
    }
    if (bundle == null) {
      throw new NullPointerException();
    }
    if (expression == null) {
      throw new NullPointerException();
    }
    if (writer == null) {
      throw new NullPointerException();
    }
    if (namespaceUri == null) {
      throw new NullPointerException();
    }
    if (expressionTag == null) {
      throw new NullPointerException();
    }

    final AttributeList expressionAttrList = new AttributeList();
    if (expression.getName() != null) {
      expressionAttrList.setAttribute(namespaceUri, "name", expression.getName());
    }

    if (expression.getDependencyLevel() > 0) {
      expressionAttrList.setAttribute(
          namespaceUri,
          "deplevel", // NON-NLS
          String.valueOf(expression.getDependencyLevel()));
    }

    writeExpressionCore(
        bundle, state, expression, writer, namespaceUri, expressionTag, expressionAttrList);
  }
  /**
   * Writes the report definition portion. Every DefinitionWriter handles one or more elements of
   * the JFreeReport object tree, DefinitionWriter traverse the object tree and write the known
   * objects or forward objects to other definition writers.
   *
   * @throws java.io.IOException if there is an I/O problem.
   * @throws ReportWriterException if the report serialisation failed.
   */
  public void write() throws IOException, ReportWriterException {
    final AttributeList attList = new AttributeList();
    if (template.getName() != null) {
      // dont copy the parent name for anonymous templates ...
      if (template.getName().equals(parent.getName()) == false) {
        attList.setAttribute(ExtParserModule.NAMESPACE, "name", template.getName());
      }
    }
    attList.setAttribute(ExtParserModule.NAMESPACE, "references", parent.getName());

    boolean tagWritten = false;
    final XmlWriter writer = getXmlWriter();
    final Iterator it = template.getParameterNames();
    while (it.hasNext()) {
      final String name = (String) it.next();
      if (shouldWriteParameter(name)) {
        if (tagWritten == false) {
          writer.writeTag(
              ExtParserModule.NAMESPACE,
              AbstractXMLDefinitionWriter.TEMPLATE_TAG,
              attList,
              XmlWriterSupport.OPEN);
          tagWritten = true;
        }
        writeParameter(name);
      }
    }
    if (tagWritten) {
      writer.writeCloseTag();
    } else {
      writer.writeTag(
          ExtParserModule.NAMESPACE,
          AbstractXMLDefinitionWriter.TEMPLATE_TAG,
          attList,
          XmlWriterSupport.CLOSE);
    }
  }
  public static void writeStyleExpression(
      final WriteableDocumentBundle bundle,
      final BundleWriterState state,
      final Expression expression,
      final XmlWriter writer,
      final StyleKey styleKey,
      final String namespaceUri,
      final String expressionTag)
      throws IOException, BundleWriterException {
    if (bundle == null) {
      throw new NullPointerException();
    }
    if (state == null) {
      throw new NullPointerException();
    }
    if (expression == null) {
      throw new NullPointerException();
    }
    if (writer == null) {
      throw new NullPointerException();
    }
    if (styleKey == null) {
      throw new NullPointerException();
    }
    if (namespaceUri == null) {
      throw new NullPointerException();
    }
    if (expressionTag == null) {
      throw new NullPointerException();
    }

    final AttributeList expressionAttrList = new AttributeList();
    expressionAttrList.setAttribute(namespaceUri, "style-key", styleKey.getName()); // NON-NLS

    writeExpressionCore(
        bundle, state, expression, writer, namespaceUri, expressionTag, expressionAttrList);
  }
  public void writeReport(
      final WriteableDocumentBundle bundle,
      final BundleWriterState wizardFileState,
      final XmlWriter xmlWriter,
      final DetailFieldDefinition definition)
      throws BundleWriterException, IOException {
    try {
      final AttributeList attList = new AttributeList();

      final ColorValueConverter colorValueConverter = new ColorValueConverter();
      final Color backgroundColor = definition.getBackgroundColor();
      if (backgroundColor != null) {
        attList.setAttribute(
            WizardCoreModule.NAMESPACE,
            "background-color",
            ColorValueConverter.colorToString(backgroundColor));
      }
      final Boolean bold = definition.getFontBold();
      if (bold != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "bold", String.valueOf(bold));
      }
      final Color color = definition.getFontColor();
      if (color != null) {
        attList.setAttribute(
            WizardCoreModule.NAMESPACE, "font-color", ColorValueConverter.colorToString(color));
      }
      final Boolean italic = definition.getFontItalic();
      if (italic != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "italic", String.valueOf(italic));
      }
      final Boolean underline = definition.getFontUnderline();
      if (underline != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "underline", String.valueOf(underline));
      }
      final Boolean strikethrough = definition.getFontStrikethrough();
      if (strikethrough != null) {
        attList.setAttribute(
            WizardCoreModule.NAMESPACE, "strikethrough", String.valueOf(strikethrough));
      }
      final String fontName = definition.getFontName();
      if (fontName != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "font-name", String.valueOf(fontName));
      }
      final Integer fontSize = definition.getFontSize();
      if (fontSize != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "font-size", String.valueOf(fontSize));
      }
      final ElementAlignmentValueConverter elementAlignmentValueConverter =
          new ElementAlignmentValueConverter();
      final ElementAlignment horizontalAlignment = definition.getHorizontalAlignment();
      if (horizontalAlignment != null) {
        attList.setAttribute(
            WizardCoreModule.NAMESPACE,
            "horizontal-align",
            elementAlignmentValueConverter.toAttributeValue(horizontalAlignment));
      }
      final ElementAlignment verticalAlignment = definition.getVerticalAlignment();
      if (verticalAlignment != null) {
        attList.setAttribute(
            WizardCoreModule.NAMESPACE,
            "vertical-align",
            elementAlignmentValueConverter.toAttributeValue(verticalAlignment));
      }

      final Boolean distinctValues = definition.getOnlyShowChangingValues();
      if (distinctValues != null) {
        attList.setAttribute(
            WizardCoreModule.NAMESPACE, "only-show-distinct", String.valueOf(distinctValues));
      }
      final Length width = definition.getWidth();
      if (width != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "width", String.valueOf(width));
      }

      final String nullString = definition.getNullString();
      if (nullString != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "null-string", String.valueOf(nullString));
      }
      final String field = definition.getField();
      if (field != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "field", String.valueOf(field));
      }
      final String displayName = definition.getDisplayName();
      if (displayName != null) {
        attList.setAttribute(
            WizardCoreModule.NAMESPACE, "display-name", String.valueOf(displayName));
      }
      final Class aggreationFunction = definition.getAggregationFunction();
      if (aggreationFunction != null) {
        attList.setAttribute(
            WizardCoreModule.NAMESPACE,
            "aggregation-function",
            String.valueOf(aggreationFunction.getName()));
      }
      final String dataFormat = definition.getDataFormat();
      if (dataFormat != null) {
        attList.setAttribute(WizardCoreModule.NAMESPACE, "data-format", String.valueOf(dataFormat));
      }
      xmlWriter.writeTag(WizardCoreModule.NAMESPACE, "detail-field", attList, XmlWriter.CLOSE);

    } catch (BeanException e) {
      throw new BundleWriterException("Failed to write bundle", e);
    }
  }
  public static void writeExpressionCore(
      final WriteableDocumentBundle bundle,
      final BundleWriterState state,
      final Expression expression,
      final XmlWriter writer,
      final String namespaceUri,
      final String expressionTag,
      final AttributeList expressionAttrList)
      throws IOException, BundleWriterException {
    if (bundle == null) {
      throw new NullPointerException();
    }
    if (state == null) {
      throw new NullPointerException();
    }
    if (expression == null) {
      throw new NullPointerException();
    }
    if (writer == null) {
      throw new NullPointerException();
    }
    if (namespaceUri == null) {
      throw new NullPointerException();
    }
    if (expressionTag == null) {
      throw new NullPointerException();
    }
    if (expressionAttrList == null) {
      throw new NullPointerException();
    }

    if (expression instanceof FormulaExpression) {
      final FormulaExpression fe = (FormulaExpression) expression;
      if (StringUtils.isEmpty(fe.getFormula())) {
        return;
      }
      expressionAttrList.setAttribute(namespaceUri, "formula", fe.getFormula()); // NON-NLS
      writer.writeTag(namespaceUri, expressionTag, expressionAttrList, XmlWriterSupport.CLOSE);
      return;
    }

    if (expression instanceof FormulaFunction) {
      final FormulaFunction fe = (FormulaFunction) expression;
      if (StringUtils.isEmpty(fe.getFormula())) {
        return;
      }
      expressionAttrList.setAttribute(namespaceUri, "formula", fe.getFormula()); // NON-NLS
      expressionAttrList.setAttribute(namespaceUri, "initial", fe.getInitial()); // NON-NLS
      writer.writeTag(namespaceUri, expressionTag, expressionAttrList, XmlWriterSupport.CLOSE);
      return;
    }

    try {

      final String expressionId = expression.getClass().getName();
      expressionAttrList.setAttribute(namespaceUri, "class", expressionId);

      final ExpressionMetaData emd;
      if (ExpressionRegistry.getInstance().isExpressionRegistered(expressionId)) {
        emd = ExpressionRegistry.getInstance().getExpressionMetaData(expressionId);
      } else {
        emd = null;
      }

      if (emd != null) {
        final BeanUtility bu = new BeanUtility(expression);
        final ExpressionPropertyMetaData[] expressionProperties = emd.getPropertyDescriptions();
        boolean propertiesOpen = false;
        for (int i = 0; i < expressionProperties.length; i++) {
          final ExpressionPropertyMetaData metaData = expressionProperties[i];
          final String propertyName = metaData.getName();
          if (isFilteredProperty(propertyName)) {
            continue;
          }
          if (metaData.isComputed()) {
            continue;
          }
          if (propertiesOpen == false) {
            writer.writeTag(namespaceUri, expressionTag, expressionAttrList, XmlWriterSupport.OPEN);
            writer.writeTag(namespaceUri, "properties", XmlWriterSupport.OPEN); // NON-NLS
            propertiesOpen = true;
          }

          copyStaticResources(bundle, state, expression, bu, expressionProperties);
          writeExpressionParameter(
              bundle, state, writer, expression, bu, propertyName, namespaceUri);
        }

        if (propertiesOpen) {
          writer.writeCloseTag();
          writer.writeCloseTag();
        } else {
          writer.writeTag(namespaceUri, expressionTag, expressionAttrList, XmlWriterSupport.CLOSE);
        }
      } else {
        // the classic way, in case the expression does not provide any meta-data. This is
        // in the code for legacy reasons, as there are many expression implementations out there
        // that do not yet provide meta-data descriptions ..

        final BeanUtility beanUtility = new BeanUtility(expression);
        final String[] propertyNames = beanUtility.getProperties();

        for (int i = 0; i < propertyNames.length; i++) {
          final String key = propertyNames[i];
          // filter some of the standard properties. These are system-properties
          // and are set elsewhere
          if (isFilteredProperty(key)) {
            continue;
          }

          writeExpressionParameter(
              bundle, state, writer, expression, beanUtility, key, namespaceUri);
        }
      }
    } catch (IOException ioe) {
      throw ioe;
    } catch (Exception e) {
      throw new BundleWriterException("Unable to extract or write properties.", e);
    }
  }
  public void save(final File file) {
    try {
      final DefaultTagDescription tags = new DefaultTagDescription();
      tags.setDefaultNamespace(DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE);
      tags.setNamespaceHasCData(DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE, false);
      tags.setElementHasCData(DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE, "attribute", true);

      final XmlWriter w =
          new XmlWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"), tags);
      w.writeXmlDeclaration("UTF-8");

      final AttributeList rootList = new AttributeList();
      rootList.addNamespaceDeclaration("", DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE);
      w.writeTag(
          DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE,
          "drilldown-profiles",
          rootList,
          XmlWriter.OPEN);

      final Object[] objects = drillDownProfiles.toArray();
      for (int i = 0; i < objects.length; i++) {
        final DrillDownProfile object = (DrillDownProfile) objects[i];

        final AttributeList profileAttrs = new AttributeList();
        profileAttrs.setAttribute(
            DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE, "name", object.getName());
        profileAttrs.setAttribute(
            DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE,
            "class",
            object.getLinkCustomizerType().getName());
        profileAttrs.setAttribute(
            DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE, "bundle-name", object.getBundleLocation());
        profileAttrs.setAttribute(
            DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE,
            "expert",
            String.valueOf(object.isExpert()));
        profileAttrs.setAttribute(
            DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE,
            "hidden",
            String.valueOf(object.isHidden()));
        profileAttrs.setAttribute(
            DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE,
            "deprecated",
            String.valueOf(object.isDeprecated()));
        profileAttrs.setAttribute(
            DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE,
            "preferred",
            String.valueOf(object.isPreferred()));

        w.writeTag(
            DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE,
            "drilldown-profile",
            profileAttrs,
            XmlWriter.OPEN);

        final String[] attrNames = object.getAttributes();
        for (int j = 0; j < attrNames.length; j++) {
          final String attrName = attrNames[j];
          final String attrValue = object.getAttribute(attrName);

          w.writeTag(
              DrillDownModule.DRILLDOWN_PROFILE_NAMESPACE,
              "attribute",
              "name",
              attrName,
              XmlWriter.OPEN);
          w.writeTextNormalized(attrValue, false);
          w.writeCloseTag();
        }

        w.writeCloseTag();
      }

      w.writeCloseTag();
      w.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }