All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.basex.api.xmldb.BXXMLResource Maven / Gradle / Ivy

There is a newer version: 11.6
Show newest version
package org.basex.api.xmldb;

import static org.basex.api.xmldb.BXXMLDBText.*;
import static org.basex.util.Token.*;

import java.io.*;

import org.basex.api.dom.*;
import org.basex.build.*;
import org.basex.build.Parser;
import org.basex.build.xml.*;
import org.basex.core.*;
import org.basex.data.*;
import org.basex.io.*;
import org.basex.io.in.*;
import org.basex.io.out.*;
import org.basex.io.parse.xml.*;
import org.basex.io.serial.*;
import org.basex.query.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;

/**
 * Implementation of the XMLResource Interface for the XMLDB:API.
 *
 * @author BaseX Team, BSD License
 * @author Christian Gruen
 */
public final class BXXMLResource implements XMLResource {
  /** Collection reference. */
  private final BXCollection coll;
  /** String id. */
  private String id;
  /** Query result. */
  private Item item;
  /** Cached content. */
  Object content;
  /** Data reference. */
  Data data;
  /** Pre value or result position. */
  int pre;

  /**
   * Constructor for generated results.
   * @param content content data
   * @param coll Collection
   */
  BXXMLResource(final byte[] content, final BXCollection coll) {
    this.content = content;
    this.coll = coll;
  }

  /**
   * Constructor for query results.
   * @param item query result
   * @param coll Collection
   */
  BXXMLResource(final Item item, final BXCollection coll) {
    this.item = item;
    this.coll = coll;
  }

  /**
   * Standard constructor.
   * @param data data reference
   * @param pre pre value
   * @param id id
   * @param coll collection
   */
  BXXMLResource(final Data data, final int pre, final String id, final BXCollection coll) {
    this.id = id;
    this.coll = coll;
    this.data = data;
    this.pre = pre;
  }

  @Override
  public Collection getParentCollection() {
    return coll;
  }

  @Override
  public String getId() {
    return id;
  }

  @Override
  public String getResourceType() {
    return XMLResource.RESOURCE_TYPE;
  }

  @Override
  public Object getContent() throws XMLDBException {
    if(content == null) {
      try {
        // serialize and cache content
        final ArrayOutput ao = new ArrayOutput();
        try(Serializer ser = Serializer.get(ao)) {
          if(data != null) {
            ser.serialize(new DBNode(data, pre));
          } else if(item != null) {
            ser.serialize(item);
          } else {
            return null;
          }
        }
        content = ao.finish();
      } catch(final IOException ex) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ex.getMessage());
      }
    }
    return content instanceof byte[] ? string((byte[]) content) : content;
  }

  @Override
  public void setContent(final Object value) throws XMLDBException {
    // allow only strings, byte arrays and {@link File} instances
    if(value instanceof byte[]) {
      content = value;
    } else if(value instanceof String) {
      content = token(value.toString());
    } else if(value instanceof File) {
      try {
        content = new IOFile((File) value).read();
      } catch(final IOException ex) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_CONT +
                '\n' + ex.getMessage());
      }
    } else {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_CONT);
    }
  }

  @Override
  public String getDocumentId() throws XMLDBException {
    // throw exception if resource results from query; does not conform to the
    // specs, but many query results are not related to a document anymore
    if(item != null) throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_DOC);

    // resource does not result from a query - return normal id
    if(id != null) return id;
    // get document root id
    int p = pre;
    while(p >= 0) {
      final int k = data.kind(p);
      if(k == Data.DOC) return string(data.text(p, true));
      p = data.parent(p, k);
    }
    return null;
  }

  @Override
  public Node getContentAsDOM() {
    if(!(content instanceof Node)) content = new BXDoc(new DBNode(data, pre));
    return (Node) content;
  }

  @Override
  public void setContentAsDOM(final Node cont) throws XMLDBException {
    // allow only document instances...
    if(cont == null) throw new XMLDBException(ErrorCodes.INVALID_RESOURCE);
    if(cont instanceof Document) content = cont;
    else throw new XMLDBException(ErrorCodes.WRONG_CONTENT_TYPE);
  }

  @Override
  public void getContentAsSAX(final ContentHandler handler) throws XMLDBException {
    if(handler == null) throw new XMLDBException(ErrorCodes.INVALID_RESOURCE);
    try {
      new XmlParser().contentHandler(handler).parse(new ArrayInput(getContent().toString()));
    } catch(final Exception pce) {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR, pce.getMessage());
    }
  }

  @Override
  public ContentHandler setContentAsSAX() {
    // might be replaced by a custom SAX content handler in future
    final MemBuilder builder = new MemBuilder(Parser.emptyParser(coll.ctx.options)).init();
    return new BXSAXContentHandler(this, builder);
  }

  /** SAX parser. */
  private static final class BXSAXContentHandler extends SAXHandler {
    /** XMLResource. */
    private final BXXMLResource resource;

    /**
     * Default constructor.
     * @param builder memory builder
     * @param resource resource
     */
    BXSAXContentHandler(final BXXMLResource resource, final MemBuilder builder) {
      super(builder);
      this.resource = resource;
    }

    @Override
    public void endDocument() throws SAXException {
      try {
        resource.content = new DBNode(((MemBuilder) builder).data()).serialize().finish();
      } catch(final QueryIOException ex) {
        throw error(new BaseXException(ex));
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy