/**
   * INTERNAL: Saves the DataObject as an XML document with the specified root element. Same as
   * save(createDocument(dataObject, rootElementURI, rootElementName), writer, null);
   *
   * @param dataObject specifies DataObject to be saved
   * @param rootElementURI the Target Namespace URI of the root XML element
   * @param rootElementName the Name of the root XML element
   * @param writer specifies the Writer to write to.
   * @throws IOException for stream exceptions.
   * @throws IllegalArgumentException if the dataObject tree is not closed or has no container.
   */
  private void save(
      DataObject rootObject,
      String rootElementURI,
      String rootElementName,
      Writer writer,
      XMLMarshaller anXMLMarshaller)
      throws XMLMarshalException {
    SDOXMLDocument xmlDocument =
        (SDOXMLDocument) createDocument(rootObject, rootElementURI, rootElementName);

    // Ask the SDOXMLDocument if we should include the XML declaration in the resulting XML
    anXMLMarshaller.setFragment(!xmlDocument.isXMLDeclaration());
    WriterRecord writerRecord;
    if (anXMLMarshaller.isFormattedOutput()) {
      writerRecord = new FormattedWriterRecord();
    } else {
      writerRecord = new WriterRecord();
    }
    writerRecord.setWriter(writer);
    writerRecord.setMarshaller(anXMLMarshaller);

    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener()).setMarshalledObject(rootObject);
    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener())
        .setMarshalledObjectRootQName(new QName(rootElementURI, rootElementName));
    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener()).setRootMarshalRecord(writerRecord);
    anXMLMarshaller.marshal(xmlDocument, writerRecord);
    try {
      writer.flush();
    } catch (IOException ex) {
      throw XMLMarshalException.marshalException(ex);
    }
  }
  private void save(XMLDocument xmlDocument, Writer outputWriter, XMLMarshaller anXMLMarshaller)
      throws IOException {
    if (xmlDocument == null) {
      throw new IllegalArgumentException(
          SDOException.cannotPerformOperationWithNullInputParameter("save", "xmlDocument"));
    }

    // Ask the SDOXMLDocument if we should include the XML declaration in the resulting XML
    anXMLMarshaller.setFragment(!xmlDocument.isXMLDeclaration());

    anXMLMarshaller.setEncoding(xmlDocument.getEncoding());
    anXMLMarshaller.setSchemaLocation(xmlDocument.getSchemaLocation());
    anXMLMarshaller.setNoNamespaceSchemaLocation(xmlDocument.getNoNamespaceSchemaLocation());

    WriterRecord writerRecord;
    if (anXMLMarshaller.isFormattedOutput()) {
      writerRecord = new FormattedWriterRecord();
    } else {
      writerRecord = new WriterRecord();
    }
    writerRecord.setWriter(outputWriter);
    writerRecord.setMarshaller(anXMLMarshaller);

    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener())
        .setMarshalledObject(xmlDocument.getRootObject());
    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener())
        .setMarshalledObjectRootQName(
            new QName(xmlDocument.getRootElementURI(), xmlDocument.getRootElementName()));
    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener()).setRootMarshalRecord(writerRecord);

    anXMLMarshaller.marshal(xmlDocument, writerRecord);
    outputWriter.flush();
  }
  /**
   * INTERNAL: Saves the DataObject as an XML document with the specified root element. Same as
   * save(createDocument(dataObject, rootElementURI, rootElementName), writer, null);
   *
   * @param dataObject specifies DataObject to be saved
   * @param rootElementURI the Target Namespace URI of the root XML element
   * @param rootElementName the Name of the root XML element
   * @param writer specifies the Writer to write to.
   * @throws IOException for stream exceptions.
   * @throws IllegalArgumentException if the dataObject tree is not closed or has no container.
   */
  private void save(
      DataObject rootObject,
      String rootElementURI,
      String rootElementName,
      Writer writer,
      XMLMarshaller anXMLMarshaller)
      throws XMLMarshalException {
    SDOXMLDocument xmlDocument =
        (SDOXMLDocument) createDocument(rootObject, rootElementURI, rootElementName);

    // Ask the SDOXMLDocument if we should include the XML declaration in the resulting XML
    anXMLMarshaller.setFragment(!xmlDocument.isXMLDeclaration());
    WriterRecord writerRecord;
    if (anXMLMarshaller.isFormattedOutput()) {
      writerRecord = new FormattedWriterRecord();
    } else {
      writerRecord = new WriterRecord();
    }
    writerRecord.setWriter(writer);
    writerRecord.setMarshaller(anXMLMarshaller);

    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener()).setMarshalledObject(rootObject);
    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener())
        .setMarshalledObjectRootQName(new QName(rootElementURI, rootElementName));
    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener()).setRootMarshalRecord(writerRecord);

    try {
      anXMLMarshaller.marshal(xmlDocument, writerRecord);
    } catch (XMLMarshalException xme) {
      if (xme.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT) {
        if (aHelperContext != ((SDOType) rootObject.getType()).getHelperContext()) {
          throw SDOException.dataObjectNotFromHelperContext();
        }
      }
    }

    try {
      writer.flush();
    } catch (IOException ex) {
      throw XMLMarshalException.marshalException(ex);
    }
  }
  private void save(XMLDocument xmlDocument, Writer outputWriter, XMLMarshaller anXMLMarshaller)
      throws IOException {
    if (xmlDocument == null) {
      throw new IllegalArgumentException(
          SDOException.cannotPerformOperationWithNullInputParameter("save", "xmlDocument"));
    }

    // Ask the SDOXMLDocument if we should include the XML declaration in the resulting XML
    anXMLMarshaller.setFragment(!xmlDocument.isXMLDeclaration());

    anXMLMarshaller.setEncoding(xmlDocument.getEncoding());
    anXMLMarshaller.setSchemaLocation(xmlDocument.getSchemaLocation());
    anXMLMarshaller.setNoNamespaceSchemaLocation(xmlDocument.getNoNamespaceSchemaLocation());

    WriterRecord writerRecord;
    if (anXMLMarshaller.isFormattedOutput()) {
      writerRecord = new FormattedWriterRecord();
    } else {
      writerRecord = new WriterRecord();
    }
    writerRecord.setWriter(outputWriter);
    writerRecord.setMarshaller(anXMLMarshaller);

    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener())
        .setMarshalledObject(xmlDocument.getRootObject());
    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener())
        .setMarshalledObjectRootQName(
            new QName(xmlDocument.getRootElementURI(), xmlDocument.getRootElementName()));
    ((SDOMarshalListener) anXMLMarshaller.getMarshalListener()).setRootMarshalRecord(writerRecord);

    try {
      anXMLMarshaller.marshal(xmlDocument, writerRecord);
    } catch (XMLMarshalException xme) {
      if (xme.getErrorCode() == XMLMarshalException.DESCRIPTOR_NOT_FOUND_IN_PROJECT) {
        if (aHelperContext
            != ((SDOType) xmlDocument.getRootObject().getType()).getHelperContext()) {
          throw SDOException.dataObjectNotFromHelperContext();
        }
      }
    }
    outputWriter.flush();
  }
  /** INTERNAL: */
  public Map buildAppInfoMap(List appInfoElements) {
    HashMap appInfoMap = new HashMap();

    // Build AppInfo map
    if (appInfoElements != null) {
      for (int i = 0; i < appInfoElements.size(); i++) {
        Element nextElement = (Element) appInfoElements.get(i);

        if (nextElement.getNamespaceURI().equals(XMLConstants.SCHEMA_URL)
            && nextElement.getLocalName().equals("appinfo")) {
          String key = nextElement.getAttribute(SDOConstants.APPINFO_SOURCE_ATTRIBUTE);
          String value = (String) appInfoMap.get(key);
          StringWriter sw = new StringWriter();
          WriterRecord wrec = new WriterRecord();
          wrec.setWriter(sw);
          wrec.node(nextElement, new NamespaceResolver());
          appInfoMap.put(key, value == null ? sw.toString() : value + sw.toString());
        }
      }
    }
    return appInfoMap;
  }