Package org.structr.web.entity.dom

Source Code of org.structr.web.entity.dom.Page

/**
* Copyright (C) 2010-2014 Morgner UG (haftungsbeschränkt)
*
* This file is part of Structr <http://structr.org>.
*
* Structr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Structr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Structr.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.web.entity.dom;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.ftpserver.ftplet.FtpFile;
import org.structr.common.PropertyView;
import org.structr.common.SecurityContext;
import org.structr.common.Syncable;
import org.structr.common.ValidationHelper;
import org.structr.common.error.ErrorBuffer;
import org.structr.common.error.FrameworkException;
import org.structr.core.Export;
import org.structr.core.Predicate;
import org.structr.core.app.App;
import org.structr.core.app.StructrApp;
import org.structr.core.entity.AbstractNode;
import org.structr.core.entity.AbstractUser;
import org.structr.core.entity.Principal;
import org.structr.core.graph.CreateNodeCommand;
import org.structr.core.graph.NodeAttribute;
import org.structr.core.graph.NodeInterface;
import static org.structr.core.graph.NodeInterface.owner;
import org.structr.core.graph.Tx;
import org.structr.core.property.BooleanProperty;
import org.structr.core.property.IntProperty;
import org.structr.core.property.Property;
import org.structr.core.property.PropertyMap;
import org.structr.core.property.RelationProperty;
import org.structr.core.property.StartNode;
import org.structr.core.property.StartNodes;
import org.structr.core.property.StringProperty;
import org.structr.dynamic.File;
import org.structr.files.ftp.AbstractStructrFtpFile;
import org.structr.files.ftp.StructrFtpFile;
import org.structr.schema.SchemaHelper;
import org.structr.schema.SchemaService;
import org.structr.web.Importer;
import org.structr.web.common.RenderContext;
import org.structr.web.common.StringRenderBuffer;
import org.structr.web.diff.InvertibleModificationOperation;
import org.structr.web.entity.Linkable;
import static org.structr.web.entity.Linkable.linkingElements;
import org.structr.web.entity.Site;
import static org.structr.web.entity.dom.DOMNode.children;
import org.structr.web.entity.html.Html;
import org.structr.web.entity.html.relation.ResourceLink;
import org.structr.web.entity.relation.PageLink;
import org.structr.web.entity.relation.Pages;
import org.structr.web.property.UiNotion;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;

//~--- classes ----------------------------------------------------------------
/**
* Represents a ownerDocument resource
*
* @author Axel Morgner
* @author Christian Morgner
*/
public class Page extends DOMNode implements Linkable, Document, DOMImplementation, FtpFile {

  private static final Logger logger = Logger.getLogger(Page.class.getName());

  public static final Property<Integer> version = new IntProperty("version").indexed().readOnly();
  public static final Property<Integer> position = new IntProperty("position").indexed();
  public static final Property<String> contentType = new StringProperty("contentType").indexed();
  public static final Property<Integer> cacheForSeconds = new IntProperty("cacheForSeconds");
  public static final Property<String> showOnErrorCodes = new StringProperty("showOnErrorCodes").indexed();
  public static final Property<List<DOMNode>> elements = new StartNodes<>("elements", PageLink.class);
  public static final Property<Boolean> isPage = new BooleanProperty("isPage", true).readOnly();
        public static final Property<String> path = new StringProperty("path").indexed();
  public static final Property<Site> site = new StartNode<>("Site", Pages.class, new UiNotion()).indexedWhenEmpty();

  public static final org.structr.common.View publicView = new org.structr.common.View(Page.class, PropertyView.Public,
    path, children, linkingElements, contentType, owner, cacheForSeconds, version, showOnErrorCodes, isPage, site
  );

  public static final org.structr.common.View uiView = new org.structr.common.View(Page.class, PropertyView.Ui,
    path, children, linkingElements, contentType, owner, cacheForSeconds, version, position, showOnErrorCodes, isPage, site
  );

  private Html5DocumentType docTypeNode = null;

  // register this type as an overridden builtin type
  static {
    SchemaService.registerBuiltinTypeOverride("Page", Page.class.getName());
  }

  public Page() {

    docTypeNode = new Html5DocumentType(this);
  }

  //~--- methods --------------------------------------------------------
  @Override
  public boolean contentEquals(DOMNode otherNode) {
    return false;
  }

  @Override
  public void updateFromNode(final DOMNode newNode) throws FrameworkException {
    // do nothing
  }

  @Override
  public void updateFromPropertyMap(final PropertyMap properties) throws FrameworkException {

    if (properties.containsKey(NodeInterface.name)) {

      final String newName = properties.get(NodeInterface.name);
      if (newName != null) {

        setProperty(NodeInterface.name, newName);
      }
    }
  }

  @Override
  public boolean isValid(ErrorBuffer errorBuffer) {

    boolean valid = true;

    valid &= nonEmpty(AbstractNode.name, errorBuffer);
                valid &= ValidationHelper.checkStringMatchesRegex(this, name, "[_a-zA-Z0-9\\s\\-\\.]+", errorBuffer);
    valid &= super.isValid(errorBuffer);

    return valid;
  }

  /**
   * Creates a new Page entity with the given name in the database.
   *
   * @param securityContext the security context to use
   * @param name the name of the new ownerDocument, defaults to
   * "ownerDocument" if not set
   *
   * @return the new ownerDocument
   * @throws FrameworkException
   */
  public static Page createNewPage(SecurityContext securityContext, String name) throws FrameworkException {

    final App app = StructrApp.getInstance(securityContext);
    final PropertyMap properties = new PropertyMap();

    properties.put(AbstractNode.name, name != null ? name : "page");
    properties.put(AbstractNode.type, Page.class.getSimpleName());
    properties.put(Page.contentType, "text/html");

    return app.create(Page.class, properties);
  }

  @Override
  protected void checkHierarchy(Node otherNode) throws DOMException {

    // verify that this document has only one document element
    if (getDocumentElement() != null) {
      throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, HIERARCHY_REQUEST_ERR_MESSAGE_DOCUMENT);
    }

    if (!(otherNode instanceof Html || otherNode instanceof Comment || otherNode instanceof Template)) {

      throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, HIERARCHY_REQUEST_ERR_MESSAGE_ELEMENT);
    }

    super.checkHierarchy(otherNode);
  }

  @Override
  public boolean hasChildNodes() {
    return true;
  }

  @Override
  public NodeList getChildNodes() {

    DOMNodeList _children = new DOMNodeList();

    _children.add(docTypeNode);
    _children.addAll(super.getChildNodes());

    return _children;
  }

  @Override
  public Node getFirstChild() {
    return docTypeNode;
  }

  public void increaseVersion() throws FrameworkException {

    final Integer _version = getProperty(Page.version);
    if (_version == null) {

      setProperty(Page.version, 1);

    } else {

      setProperty(Page.version, _version + 1);
    }
  }

  @Override
  public Element createElement(final String tag) throws DOMException {

    final String elementType = StringUtils.capitalize(tag);
    final App app = StructrApp.getInstance(securityContext);

    String c = Content.class.getSimpleName();

    // Avoid creating an (invalid) 'Content' DOMElement
    if (elementType == null || c.equals(elementType)) {

      logger.log(Level.WARNING, "Blocked attempt to create a DOMElement of type {0}", c);

      return null;

    }

    final Page _page = this;

    // create new content element
    DOMElement element;
    try {
      final Class entityClass = SchemaHelper.getEntityClassForRawType(elementType);
      if (entityClass != null) {

        element = (DOMElement) app.create(entityClass, new NodeAttribute(DOMElement.tag, tag));
        element.doAdopt(_page);

        return element;
      }

    } catch (FrameworkException ex) {
      logger.log(Level.SEVERE, null, ex);
    }

    return null;

  }
  @Override
  protected void handleNewChild(Node newChild) {
   
    for (final DOMNode child : getAllChildNodes()) {
     
      try {
       
        child.setProperty(ownerDocument, this);
       
      } catch (FrameworkException ex) {
        ex.printStackTrace();
      }
     
    }
   
  }

  @Override
  public DocumentFragment createDocumentFragment() {

    final App app = StructrApp.getInstance(securityContext);

    try {

      // create new content element
      org.structr.web.entity.dom.DocumentFragment fragment = app.create(org.structr.web.entity.dom.DocumentFragment.class);

      // create relationship from ownerDocument to new text element
      ((RelationProperty<DOMNode>) Page.elements).addSingleElement(securityContext, Page.this, fragment);
      // Page.elements.createRelationship(securityContext, Page.this, fragment);

      return fragment;

    } catch (FrameworkException fex) {

      // FIXME: what to do with the exception here?
      fex.printStackTrace();
    }

    return null;

  }

  @Override
  public Text createTextNode(final String text) {

    try {

      // create new content element
      Content content = (Content) StructrApp.getInstance(securityContext).command(CreateNodeCommand.class).execute(
        new NodeAttribute(AbstractNode.type, Content.class.getSimpleName()),
        new NodeAttribute(Content.content, text)
      );

      // create relationship from ownerDocument to new text element
      ((RelationProperty<DOMNode>) Page.elements).addSingleElement(securityContext, Page.this, content);
      //Page.elements.createRelationship(securityContext, Page.this, content);

      return content;

    } catch (FrameworkException fex) {

      // FIXME: what to do with the exception here?
      fex.printStackTrace();
    }

    return null;
  }

  @Override
  public Comment createComment(String comment) {

    try {

      // create new content element
      org.structr.web.entity.dom.Comment commentNode = (org.structr.web.entity.dom.Comment) StructrApp.getInstance(securityContext).command(CreateNodeCommand.class).execute(
        new NodeAttribute(AbstractNode.type, org.structr.web.entity.dom.Comment.class.getSimpleName()),
        new NodeAttribute(Content.content, comment)
      );

      // create relationship from ownerDocument to new text element
      ((RelationProperty<DOMNode>) Page.elements).addSingleElement(securityContext, Page.this, commentNode);
      //Page.elements.createRelationship(securityContext, Page.this, content);

      return commentNode;

    } catch (FrameworkException fex) {

      // FIXME: what to do with the exception here?
      fex.printStackTrace();
    }

    return null;
  }

  @Override
  public CDATASection createCDATASection(String string) throws DOMException {

    try {

      // create new content element
      Cdata content = (Cdata) StructrApp.getInstance(securityContext).command(CreateNodeCommand.class).execute(
        new NodeAttribute(AbstractNode.type, Cdata.class.getSimpleName())
      );

      // create relationship from ownerDocument to new text element
      ((RelationProperty<DOMNode>) Page.elements).addSingleElement(securityContext, Page.this, content);
      //Page.elements.createRelationship(securityContext, Page.this, content);

      return content;

    } catch (FrameworkException fex) {

      // FIXME: what to do with the exception here?
      fex.printStackTrace();
    }

    return null;
  }

  @Override
  public ProcessingInstruction createProcessingInstruction(String string, String string1) throws DOMException {

    throw new UnsupportedOperationException("Not supported yet.");

  }

  @Override
  public Attr createAttribute(String name) throws DOMException {
    return new DOMAttribute(this, null, name, null);
  }

  @Override
  public EntityReference createEntityReference(String string) throws DOMException {

    throw new UnsupportedOperationException("Not supported yet.");

  }

  @Override
  public Element createElementNS(String string, String string1) throws DOMException {
    throw new UnsupportedOperationException("Namespaces not supported");
  }

  @Override
  public Attr createAttributeNS(String string, String string1) throws DOMException {
    throw new UnsupportedOperationException("Namespaces not supported");
  }

  @Override
  public Node importNode(final Node node, final boolean deep) throws DOMException {
    return importNode(node, deep, true);
  }

  private Node importNode(final Node node, final boolean deep, final boolean removeParentFromSourceNode) throws DOMException {

    if (node instanceof DOMNode) {

      final DOMNode domNode = (DOMNode) node;

      // step 1: use type-specific import impl.
      Node importedNode = domNode.doImport(Page.this);

      // step 2: do recursive import?
      if (deep && domNode.hasChildNodes()) {

        // FIXME: is it really a good idea to do the
        // recursion inside of a transaction?
        Node child = domNode.getFirstChild();

        while (child != null) {

          // do not remove parent for child nodes
          importNode(child, deep, false);
          child = child.getNextSibling();

          logger.log(Level.INFO, "sibling is {0}", child);
        }

      }

      // step 3: remove node from its current parent
      // (Note that this step needs to be done last in
      // (order for the child to be able to find its
      // siblings.)
      if (removeParentFromSourceNode) {

        // only do this for the actual source node, do not remove
        // child nodes from its parents
        Node _parent = domNode.getParentNode();
        if (_parent != null) {
          _parent.removeChild(domNode);
        }
      }

      return importedNode;

    }

    return null;
  }

  @Override
  public Node adoptNode(Node node) throws DOMException {
    return adoptNode(node, true);
  }

  private Node adoptNode(final Node node, final boolean removeParentFromSourceNode) throws DOMException {

    if (node instanceof DOMNode) {

      final DOMNode domNode = (DOMNode) node;

      // step 2: do recursive import?
      if (domNode.hasChildNodes()) {

        Node child = domNode.getFirstChild();
        while (child != null) {

          // do not remove parent for child nodes
          adoptNode(child, false);
          child = child.getNextSibling();
        }

      }

      // step 3: remove node from its current parent
      // (Note that this step needs to be done last in
      // (order for the child to be able to find its
      // siblings.)
      if (removeParentFromSourceNode) {

        // only do this for the actual source node, do not remove
        // child nodes from its parents
        Node _parent = domNode.getParentNode();
        if (_parent != null) {
          _parent.removeChild(domNode);
        }
      }

      // step 1: use type-specific adopt impl.
      Node adoptedNode = domNode.doAdopt(Page.this);

      return adoptedNode;

    }

    return null;
  }

  @Override
  public void normalizeDocument() {
    normalize();
  }

  @Override
  public Node renameNode(Node node, String string, String string1) throws DOMException {
    throw new DOMException(DOMException.NOT_SUPPORTED_ERR, NOT_SUPPORTED_ERR_MESSAGE_RENAME);
  }

  @Override
  public DocumentType createDocumentType(String string, String string1, String string2) throws DOMException {

    throw new UnsupportedOperationException("Not supported yet.");

  }

  @Override
  public Document createDocument(String string, String string1, DocumentType dt) throws DOMException {

    throw new UnsupportedOperationException("Not supported yet.");

  }

  @Override
  public String toString() {

    return getClass().getSimpleName() + " " + getName() + " [" + getUuid() + "] (" + getTextContent() + ")";
  }

  /**
   * Return the content of this page depending on edit mode
   *
   * @param editMode
   * @return content
   * @throws FrameworkException
   */
  public String getContent(final RenderContext.EditMode editMode) throws FrameworkException {

    final RenderContext ctx = new RenderContext(null, null, editMode, Locale.GERMAN);
    final StringRenderBuffer buffer = new StringRenderBuffer();
    ctx.setBuffer(buffer);
    render(securityContext, ctx, 0);

    // extract source
    return buffer.getBuffer().toString();

  }

  //~--- get methods ----------------------------------------------------
  @Override
  public short getNodeType() {

    return Element.DOCUMENT_NODE;
  }

  @Override
  public DOMImplementation getImplementation() {

    return this;
  }

  @Override
  public Element getDocumentElement() {
   
    Node node = super.getFirstChild();
   
    if (node instanceof Element) {
     
      return (Element) node;
     
    } else {
     
      return null;
    }
  }

  @Override
  public Element getElementById(final String id) {

    DOMNodeList results = new DOMNodeList();

    collectNodesByPredicate(this, results, new Predicate<Node>() {

      @Override
      public boolean evaluate(SecurityContext securityContext, Node... obj) {

        if (obj[0] instanceof DOMElement) {

          DOMElement elem = (DOMElement) obj[0];

          if (id.equals(elem.getProperty(DOMElement._id))) {
            return true;
          }
        }

        return false;
      }

    }, 0, true);

    // return first result
    if (results.getLength() == 1) {
      return (DOMElement) results.item(0);
    }

    return null;
  }

  @Override
  public String getInputEncoding() {
    return null;
  }

  @Override
  public String getXmlEncoding() {
    return "UTF-8";
  }

  @Override
  public boolean getXmlStandalone() {
    return true;
  }

  @Override
  public String getXmlVersion() {
    return "1.0";
  }

  @Override
  public boolean getStrictErrorChecking() {
    return true;
  }

  @Override
  public String getDocumentURI() {
    return null;
  }

  @Override
  public DOMConfiguration getDomConfig() {
    return null;
  }

  @Override
  public DocumentType getDoctype() {
    return new Html5DocumentType(this);
  }

  @Override
  public void render(SecurityContext securityContext, RenderContext renderContext, int depth) throws FrameworkException {

    renderContext.setPage(this);

    // Skip DOCTYPE node
    DOMNode subNode = (DOMNode) this.getFirstChild().getNextSibling();

    if (subNode == null) {
     
      subNode = (DOMNode) super.getFirstChild();
     
     
    } else {

      renderContext.getBuffer().append("<!DOCTYPE html>\n");

    }

    while (subNode != null) {

      if (subNode.isNotDeleted() && securityContext.isVisible(subNode)) {

        subNode.render(securityContext, renderContext, depth);
      }

      subNode = (DOMNode) subNode.getNextSibling();

    }
     
  }

  @Override
  public void renderContent(final SecurityContext securityContext, final RenderContext renderContext, final int depth) throws FrameworkException {
  } 

  @Override
  public boolean hasFeature(String string, String string1) {
    return false;
  }

  @Override
  public boolean isSynced() {
    return false;
  }

  //~--- set methods ----------------------------------------------------
  @Override
  public void setXmlStandalone(boolean bln) throws DOMException {
  }

  @Override
  public void setXmlVersion(String string) throws DOMException {
  }

  @Override
  public void setStrictErrorChecking(boolean bln) {
  }

  @Override
  public void setDocumentURI(String string) {
  }

  // ----- interface org.w3c.dom.Node -----
  @Override
  public String getLocalName() {
    return null;
  }

  @Override
  public String getNodeName() {
    return "#document";
  }

  @Override
  public String getNodeValue() throws DOMException {
    return null;
  }

  @Override
  public void setNodeValue(String string) throws DOMException {
  }

  @Override
  public NamedNodeMap getAttributes() {
    return null;
  }

  @Override
  public boolean hasAttributes() {
    return false;
  }

  @Override
  public NodeList getElementsByTagName(final String tagName) {

    DOMNodeList results = new DOMNodeList();

    collectNodesByPredicate(this, results, new Predicate<Node>() {

      @Override
      public boolean evaluate(SecurityContext securityContext, Node... obj) {

        if (obj[0] instanceof DOMElement) {

          DOMElement elem = (DOMElement) obj[0];

          if (tagName.equals(elem.getProperty(DOMElement.tag))) {
            return true;
          }
        }

        return false;
      }

    }, 0, false);

    return results;
  }

  @Override
  public NodeList getElementsByTagNameNS(String string, String tagName) {
    throw new UnsupportedOperationException("Namespaces not supported.");
  }

  // ----- interface DOMAdoptable -----
  @Override
  public Node doAdopt(Page page) throws DOMException {
    throw new DOMException(DOMException.NOT_SUPPORTED_ERR, NOT_SUPPORTED_ERR_MESSAGE_ADOPT_DOC);
  }

  // ----- interface DOMImportable -----
  @Override
  public Node doImport(Page newPage) throws DOMException {
    throw new DOMException(DOMException.NOT_SUPPORTED_ERR, NOT_SUPPORTED_ERR_MESSAGE_IMPORT_DOC);
  }

  @Override
  public String getPath() {
    return getProperty(path);
  }

  // ----- diff methods -----
  @Export
  public void diff(final String file) throws FrameworkException {

    final App app = StructrApp.getInstance(securityContext);

    try (final Tx tx = app.tx()) {

      final String source = IOUtils.toString(new FileInputStream(file));
      final List<InvertibleModificationOperation> changeSet = new LinkedList<>();
      final Page diffPage = Importer.parsePageFromSource(securityContext, source, this.getProperty(Page.name) + "diff");

      // build change set
      changeSet.addAll(Importer.diffPages(this, diffPage));

      for (final InvertibleModificationOperation op : changeSet) {

        System.out.println(op);

        op.apply(app, this, diffPage);
      }

      // delete remaining children
      for (final DOMNode child : diffPage.getProperty(Page.elements)) {
        app.delete(child);
      }

      // delete imported page
      app.delete(diffPage);

      tx.success();

    } catch (Throwable t) {
      t.printStackTrace();
    }
  }

  // ----- interface FtpFile -----
  @Override
  public String getAbsolutePath() {
    try (Tx tx = StructrApp.getInstance().tx()) {
      return getPath();
    } catch (FrameworkException fex) {
      logger.log(Level.SEVERE, "Error in getPath() of abstract ftp file", fex);
    }
    return null;
  }

  @Override
  public boolean isDirectory() {
    return false;
  }

  @Override
  public boolean isFile() {
    return true;
  }

  @Override
  public boolean doesExist() {
    return true;
  }

  @Override
  public boolean isReadable() {
    return true;
  }

  @Override
  public boolean isWritable() {
    return true;
  }

  @Override
  public boolean isRemovable() {
    return true;
  }

  private Principal getOwner() {
    try (Tx tx = StructrApp.getInstance().tx()) {
      Principal owner = getProperty(File.owner);
      tx.success();
      return owner;
    } catch (FrameworkException fex) {
      logger.log(Level.SEVERE, "Error while getting owner of " + this, fex);
    }
    return null;
  }

  @Override
  public String getOwnerName() {

    String name = "";

    try (Tx tx = StructrApp.getInstance().tx()) {

      Principal owner = getOwner();
      if (owner != null) {

        name = owner.getProperty(AbstractUser.name);
      }
      tx.success();

    } catch (FrameworkException fex) {
      logger.log(Level.SEVERE, "Error while getting owner name of " + this, fex);
    }

    return name;
  }

  @Override
  public String getGroupName() {

    String name = "";

    try (Tx tx = StructrApp.getInstance().tx()) {

      Principal owner = getOwner();

      if (owner != null) {
        List<Principal> parents = owner.getParents();
        if (!parents.isEmpty()) {

          name = parents.get(0).getProperty(AbstractNode.name);
        }
      }

      tx.success();

    } catch (FrameworkException fex) {
      logger.log(Level.SEVERE, "Error while getting group name of " + this, fex);
    }

    return name;
  }

  @Override
  public int getLinkCount() {
    return 1;
  }

  @Override
  public long getLastModified() {

    long lastModified = 0L;

    try (Tx tx = StructrApp.getInstance().tx()) {

      lastModified = getProperty(lastModifiedDate).getTime();
      tx.success();

    } catch (FrameworkException fex) {
      logger.log(Level.SEVERE, "Error while last modified date of " + this, fex);
    }

    return lastModified;
  }

  @Override
  public boolean setLastModified(long time) {

    try (Tx tx = StructrApp.getInstance().tx()) {
      setProperty(lastModifiedDate, new Date(time));
      tx.success();
    } catch (FrameworkException ex) {
      logger.log(Level.SEVERE, null, ex);
    }

    return true;
  }

  @Override
  public long getSize() {

    long size = 0L;

    try (Tx tx = StructrApp.getInstance().tx()) {

      size = getContent(RenderContext.EditMode.RAW).length();
      tx.success();

    } catch (FrameworkException fex) {
      logger.log(Level.SEVERE, "Error while last modified date of " + this, fex);
    }

    return size;
  }

  @Override
  public String getName() {

    String name = null;

    try (Tx tx = StructrApp.getInstance().tx()) {

      name = getProperty(AbstractNode.name);
      tx.success();

    } catch (FrameworkException fex) {
      logger.log(Level.SEVERE, "Error in getName() of page", fex);
    }

    return name;
  }

  @Override
  public boolean isHidden() {

    boolean hidden = true;

    try (Tx tx = StructrApp.getInstance().tx()) {

      hidden = getProperty(Page.hidden);
      tx.success();

    } catch (FrameworkException fex) {
      logger.log(Level.SEVERE, "Error in isHidden() of page", fex);
    }

    return hidden;
  }

  @Override
  public boolean mkdir() {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  }

  @Override
  public boolean delete() {
    final App app = StructrApp.getInstance();

    try (Tx tx = StructrApp.getInstance().tx()) {
      app.delete(this);
      tx.success();
    } catch (FrameworkException ex) {
      logger.log(Level.SEVERE, null, ex);
    }

    return true;
  }

  @Override
  public boolean move(FtpFile target) {
    try (Tx tx = StructrApp.getInstance().tx()) {

      logger.log(Level.INFO, "move()");

      final AbstractStructrFtpFile targetFile = (AbstractStructrFtpFile) target;
      final String path = targetFile instanceof StructrFtpFile ? "/" : targetFile.getAbsolutePath();

      try {

        if (!("/".equals(path))) {
          final String newName = path.contains("/") ? StringUtils.substringAfterLast(path, "/") : path;
          setProperty(AbstractNode.name, newName);
        }

      } catch (FrameworkException ex) {
        logger.log(Level.SEVERE, "Could not move ftp file", ex);
        return false;
      }

      tx.success();

      return true;
    } catch (FrameworkException ex) {
      logger.log(Level.SEVERE, null, ex);
    }

    return false;
  }

  @Override
  public List<FtpFile> listFiles() {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  }

  @Override
  public OutputStream createOutputStream(long offset) throws IOException {

    final Page origPage = this;

    OutputStream out = new ByteArrayOutputStream() {

      @Override
      public void flush() throws IOException {

        final String source = toString();

        final App app = StructrApp.getInstance();
        try (Tx tx = app.tx()) {

          // parse page from modified source
          Page modifiedPage = Importer.parsePageFromSource(securityContext, source, "__FTP_Temporary_Page__");

          final List<InvertibleModificationOperation> changeSet = Importer.diffPages(origPage, modifiedPage);

          for (final InvertibleModificationOperation op : changeSet) {

            // execute operation
            op.apply(app, origPage, modifiedPage);

          }

          app.delete(modifiedPage);

          tx.success();

        } catch (FrameworkException fex) {
          fex.printStackTrace();
        }

        super.flush();

      }

    };

    return out;
  }

  @Override
  public InputStream createInputStream(long offset) throws IOException {

    ByteArrayInputStream bis = null;
    try (Tx tx = StructrApp.getInstance().tx()) {

      bis = new ByteArrayInputStream(getContent(RenderContext.EditMode.RAW).getBytes("UTF-8"));
      tx.success();

    } catch (FrameworkException fex) {
      fex.printStackTrace();
    }

    return bis;
  }

  // ----- interface Syncable -----
  @Override
  public List<Syncable> getSyncData() {

    final List<Syncable> data = super.getSyncData();

    data.addAll(getProperty(Linkable.linkingElements));

    for (final ResourceLink link : getRelationships(ResourceLink.class)) {
      data.add(link);
    }

    return data;
  }
}
TOP

Related Classes of org.structr.web.entity.dom.Page

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.