Package org.structr.web.common

Source Code of org.structr.web.common.RenderContext

/**
* 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.common;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.structr.common.SecurityContext;
import org.structr.common.error.FrameworkException;
import org.structr.core.GraphObject;
import org.structr.core.Ownership;
import org.structr.core.Result;
import org.structr.core.app.StructrApp;
import org.structr.core.converter.PropertyConverter;
import org.structr.core.entity.AbstractNode;
import org.structr.core.entity.Principal;
import org.structr.core.entity.relationship.PrincipalOwnsNode;
import org.structr.core.graph.NodeInterface;
import org.structr.core.property.PropertyKey;
import org.structr.core.property.RelationProperty;
import org.structr.rest.ResourceProvider;
import org.structr.schema.action.ActionContext;
import org.structr.web.entity.dom.DOMNode;
import org.structr.web.entity.dom.Page;
import org.structr.web.entity.dom.Template;
import org.structr.web.entity.html.relation.ResourceLink;

/**
* Holds information about the context in which a resource is rendered, like
* f.e. edit mode, language
*
* @author Axel Morgner
*/
public class RenderContext extends ActionContext {

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

  private final Map<String, GraphObject> dataObjects = new LinkedHashMap<>();
  private final long renderStartTime = System.currentTimeMillis();
  private Locale locale = Locale.getDefault();
  private EditMode editMode = EditMode.NONE;
  private AsyncBuffer buffer = new AsyncBuffer();
  private int depth = 0;
  private boolean inBody = false;
  private boolean appLibRendered = false;
  private GraphObject detailsDataObject = null;
  private GraphObject currentDataObject = null;
  private GraphObject sourceDataObject = null;
  private Iterable<GraphObject> listSource = null;
  private PropertyKey relatedProperty = null;
  private Page page = null;
  private HttpServletRequest request = null;
  private HttpServletResponse response = null;
  private ResourceProvider resourceProvider = null;
  private Result result = null;
  private boolean anyChildNodeCreatesNewLine = false;

  public enum EditMode {

    NONE, WIDGET, CONTENT, RAW;

  }

  public RenderContext() {
  }

  /**
   * Create a copy of this render context with a clean buffer.
   *
   * @param other The render context to copy from
   */
  public RenderContext(final RenderContext other) {

    super(other);
   
    this.dataObjects.putAll(other.dataObjects);
    this.editMode = other.editMode;
    this.inBody = other.inBody;
    this.appLibRendered = other.appLibRendered;
    this.detailsDataObject = other.detailsDataObject;
    this.currentDataObject = other.currentDataObject;
    this.sourceDataObject = other.sourceDataObject;
    this.listSource = other.listSource;
    this.relatedProperty = other.relatedProperty;
    this.page = other.page;
    this.request = other.request;
    this.response = other.response;
    this.resourceProvider = other.resourceProvider;
    this.result = other.result;
    this.anyChildNodeCreatesNewLine = other.anyChildNodeCreatesNewLine;

  }

  public RenderContext(final HttpServletRequest request, HttpServletResponse response, final EditMode editMode, final Locale locale) {

    this.request = request;
    this.response = response;

    this.editMode = editMode;
    this.locale = locale;

  }

  public static RenderContext getInstance(final HttpServletRequest request, HttpServletResponse response, final Locale locale) {

    String editString = StringUtils.defaultString(request.getParameter("edit"));

    return new RenderContext(request, response, editMode(editString), locale);

  }

  public void setDetailsDataObject(GraphObject detailsDataObject) {
    this.detailsDataObject = detailsDataObject;
  }

  public GraphObject getDetailsDataObject() {
    return detailsDataObject;
  }

  public void setDataObject(GraphObject currentDataObject) {
    this.currentDataObject = currentDataObject;
  }

  public GraphObject getDataObject() {
    return currentDataObject;
  }

  public void setSourceDataObject(GraphObject sourceDataObject) {
    this.sourceDataObject = sourceDataObject;
  }

  public GraphObject getSourceDataObject() {
    return sourceDataObject;
  }

  public void setListSource(Iterable<GraphObject> listSource) {
    this.listSource = listSource;
  }

  public void setResult(Result result) {
    this.result = result;
  }

  public Iterable<GraphObject> getListSource() {
    return listSource;
  }

  public PropertyKey getRelatedProperty() {
    return relatedProperty;
  }

  public void setRelatedProperty(final PropertyKey relatedProperty) {
    this.relatedProperty = relatedProperty;
  }

  /**
   * Return edit mode.
   *
   * If no user is logged in, the edit mode is always NONE to disable
   * editing for public sessions.
   *
   * @param user
   * @return edit mode
   */
  public EditMode getEditMode(final Principal user) {
    return user == null ? EditMode.NONE : editMode;
  }

  public void setEditMode(final EditMode edit) {
    this.editMode = edit;
  }

  public static EditMode editMode(final String editString) {

    EditMode edit;

    switch (editString) {

      case "1":

        edit = EditMode.WIDGET;
        break;

      case "2":

        edit = EditMode.CONTENT;
        break;

      case "3":

        edit = EditMode.RAW;
        break;

      default:

        edit = EditMode.NONE;

    }

    return edit;

  }

  public Locale getLocale() {
    return locale;
  }

  public String getISO3Country() {
    return getLocale().getISO3Country();
  }

  public String getISO3Language() {
    return getLocale().getISO3Language();
  }

  public HttpServletRequest getRequest() {
    return request;
  }

  public HttpServletResponse getResponse() {
    return response;
  }

  public void setResourceProvider(final ResourceProvider resourceProvider) {
    this.resourceProvider = resourceProvider;
  }

  public ResourceProvider getResourceProvider() {
    return resourceProvider;
  }

  public void increaseDepth() {
    this.depth++;
  }

  public void decreaseDepth() {
    this.depth--;
  }

  public void setDepth(final int depth) {
    this.depth = depth;
  }

  public int getDepth() {
    return depth;
  }

  public void setBuffer(final AsyncBuffer buffer) {
    this.buffer = buffer;
  }

  public AsyncBuffer getBuffer() {
    return buffer;
  }

  public void setInBody(final boolean inBody) {
    this.inBody = inBody;
  }

  public boolean inBody() {
    return inBody;
  }

  public void setAppLibRendered(final boolean appLibRendered) {
    this.appLibRendered = appLibRendered;
  }

  public boolean appLibRendered() {
    return appLibRendered;
  }

  public GraphObject getDataNode(String key) {
    return dataObjects.get(key);
  }

  public void putDataObject(String key, GraphObject currentDataObject) {
    dataObjects.put(key, currentDataObject);
    setDataObject(currentDataObject);

  }

  public void clearDataObject(String key) {
    dataObjects.remove(key);
    setDataObject(null);
  }

  public boolean hasDataForKey(String key) {
    return dataObjects.containsKey(key);
  }

  public void setPage(final Page page) {
    this.page = page;
  }

  public Page getPage() {
    return page;
  }

  public String getPageId() {
    return (page != null ? page.getUuid() : null);
  }

  public Result getResult() {
    return result;
  }

  public void setAnyChildNodeCreatesNewLine(final boolean anyChildNodeCreatesNewLine) {
    this.anyChildNodeCreatesNewLine = anyChildNodeCreatesNewLine;
  }

  public boolean getAnyChildNodeCreatesNewLine() {
    return anyChildNodeCreatesNewLine;
  }

  // ----- interface ActionContext -----
  @Override
  public Object getReferencedProperty(final SecurityContext securityContext, final GraphObject entity, final String refKey) throws FrameworkException {

    final String DEFAULT_VALUE_SEP = "!";
    final String[] parts = refKey.split("[\\.]+");
    String referenceKey = parts[parts.length - 1];
    String defaultValue = null;

    if (StringUtils.contains(referenceKey, DEFAULT_VALUE_SEP)) {

      String[] ref = StringUtils.split(referenceKey, DEFAULT_VALUE_SEP);
      referenceKey = ref[0];
      if (ref.length > 1) {

        defaultValue = ref[1];

      } else {

        defaultValue = "";
      }
    }

    Page _page = this.getPage();
    GraphObject _data = null;

    // walk through template parts
    for (int i = 0; (i < parts.length); i++) {

      String part = parts[i];

      if (_data != null) {

        Object value = _data.getProperty(StructrApp.getConfiguration().getPropertyKeyForJSONName(_data.getClass(), part));

        if (value instanceof GraphObject) {
          _data = (GraphObject) value;

          continue;

        }

        // special keyword "size"
        if (i > 0 && "size".equals(part)) {

          Object val = _data.getProperty(StructrApp.getConfiguration().getPropertyKeyForJSONName(_data.getClass(), parts[i - 1]));

          if (val instanceof List) {

            return ((List) val).size();

          }

        }

        // special keyword "link", works on deeper levels, too
        if ("link".equals(part) && _data instanceof AbstractNode) {

          ResourceLink rel = ((AbstractNode) _data).getOutgoingRelationship(ResourceLink.class);
          if (rel != null) {

            _data = rel.getTargetNode();

            break;

          }

          continue;

        }

        if (value == null) {

          // check for default value
          if (defaultValue != null && StringUtils.contains(refKey, "!")) {
            return numberOrString(defaultValue);
          }

          // Need to return null here to avoid _data sticking to the (wrong) parent object
          return null;

        }

      }

      // data objects from parent elements
      if (this.hasDataForKey(part)) {

        _data = this.getDataNode(part);

        if (parts.length == 1) {
          return _data;
        }

        continue;

      }

      // special keyword "request"
      if ("request".equals(part)) {

        final HttpServletRequest request = this.getRequest(); //securityContext.getRequest();
        if (request != null) {

          if (StringUtils.contains(refKey, "!")) {

            return numberOrString(StringUtils.defaultIfBlank(request.getParameter(referenceKey), defaultValue));

          } else {

            return numberOrString(StringUtils.defaultString(request.getParameter(referenceKey)));
          }
        }

      }

      // special keyword "now":
      if ("now".equals(part)) {

        return new Date();
      }

      // special keyword "me"
      if ("me".equals(part)) {

        Principal me = (Principal) securityContext.getUser(false);

        if (me != null) {

          _data = me;

          if (parts.length == 1) {
            return _data;
          }

          continue;
        }

      }

      // special boolean keywords
      if ("true".equals(part)) {
        return true;
      }

      if ("false".equals(part)) {
        return false;
      }

      // the following keywords work only on root level
      // so that they can be used as property keys for data objects
      if (_data == null) {

        // details data object id
        if ("id".equals(part)) {

          GraphObject detailsObject = this.getDetailsDataObject();

          if (detailsObject != null) {
            return detailsObject.getUuid();
          }

        }

        // details data object
        if ("current".equals(part)) {

          GraphObject detailsObject = this.getDetailsDataObject();

          if (detailsObject != null) {

            _data = detailsObject;

            if (parts.length == 1) {
              return _data;
            }

            continue;
          }

        }

        // special keyword "this"
        if ("this".equals(part)) {

          _data = this.getDataObject();

          if (parts.length == 1) {
            return _data;
          }

          continue;

        }

        // special keyword "element"
        if ("element".equals(part)) {

          _data = entity;

          if (parts.length == 1) {
            return _data;
          }

          continue;

        }

        // special keyword "template", references the closest Template node in the current page
        if ("template".equals(part)) {

          _data = ((DOMNode) entity).getClosestTemplate(_page);

          if (parts.length == 1) {
            return _data;
          }

          continue;
        }

        // special keyword "ownerDocument", works only on root level
        if ("page".equals(part)) {

          _data = _page;

          if (parts.length == 1) {
            return _data;
          }

          continue;

        }

        // special keyword "link"
        if (entity instanceof NodeInterface && "link".equals(part)) {

          ResourceLink rel = ((NodeInterface) entity).getOutgoingRelationship(ResourceLink.class);

          if (rel != null) {
            _data = rel.getTargetNode();

            if (parts.length == 1) {
              return _data;
            }

            continue;
          }

        }

        // special keyword "parent"
        if ("parent".equals(part)) {

          _data = (DOMNode) ((DOMNode) entity).getParentNode();

          if (parts.length == 1) {
            return _data;
          }

          continue;

        }

        // special keyword "children", references the children of the closest Template node in the current page
        if ("children".equals(part)) {

          if (parts.length == 1) {

            final Template template = ((DOMNode) entity).getClosestTemplate(_page);

            if (template != null) {
              return template.getChildNodes();
            }
          }

          continue;

        }

        // special keyword "owner"
        if (entity instanceof NodeInterface && "owner".equals(part)) {

          Ownership rel = ((NodeInterface) entity).getIncomingRelationship(PrincipalOwnsNode.class);
          if (rel != null) {

            _data = rel.getSourceNode();

            if (parts.length == 1) {
              return _data;
            }
          }

          continue;

        }

        // special keyword "result_size"
        if ("result_count".equals(part) || "result_size".equals(part)) {

          Result result = this.getResult();

          if (result != null) {

            return result.getRawResultCount();

          }

        }

        // special keyword "page_size"
        if ("page_size".equals(part)) {

          Result result = this.getResult();

          if (result != null) {

            return result.getPageSize();

          }

        }

        // special keyword "page_count"
        if ("page_count".equals(part)) {

          Result result = this.getResult();

          Integer pageCount = result.getPageCount();

          if (pageCount != null) {
            return pageCount;
          } else {
            return 1;
          }

        }

        // special keyword "page_no"
        if ("page_no".equals(part)) {

          Result result = this.getResult();

          if (result != null) {

            return result.getPage();

          }

        }

        // special keyword "host":
        if ("host".equals(part)) {

          return securityContext.getRequest().getServerName();
        }

        // special keyword "port":
        if ("port".equals(part)) {

          return securityContext.getRequest().getServerPort();
        }

        // special keyword "path_info":
        if ("path_info".equals(part)) {

          return securityContext.getRequest().getPathInfo();
        }
      }

    }

    if (_data != null) {

      PropertyKey referenceKeyProperty = StructrApp.getConfiguration().getPropertyKeyForJSONName(_data.getClass(), referenceKey);
      //return getEditModeValue(securityContext, renderContext, _data, referenceKeyProperty, defaultValue);
      Object value = _data.getProperty(referenceKeyProperty);

      PropertyConverter converter = referenceKeyProperty.inputConverter(securityContext);

      if (value != null && converter != null && !(referenceKeyProperty instanceof RelationProperty)) {

        try {
          value = converter.revert(value);

        } catch (Throwable t) {

          logger.log(Level.WARNING, "Unable to convert property {0} of node {1}: {2}", new Object[]{referenceKeyProperty, _data, t.getMessage()});
        }
      }

      return value != null ? value : defaultValue;

    }

    // check for default value
    if (defaultValue != null && StringUtils.contains(refKey, "!")) {
      return numberOrString(defaultValue);
    }

    return null;

  }

  @Override
  public boolean returnRawValue(final SecurityContext securityContext) {
    EditMode editMode = getEditMode(securityContext.getUser(false));
    return ((EditMode.RAW.equals(editMode) || EditMode.WIDGET.equals(editMode)));
  }

  public boolean hasTimeout(final long timeout) {
    return System.currentTimeMillis() > (renderStartTime + timeout);
  }

//  private Template getClosestTemplate(DOMNode node, final Page page) {
//
//    while (node != null) {
//
//      if (node instanceof Template) {
//
//        final Template template = (Template) node;
//
//        Document doc = template.getOwnerDocument();
//
//        if (doc == null) {
//
//          doc = getClosestPage(node);
//        }
//
//        if (doc != null && doc.equals(page)) {
//
//          try {
//            template.setProperty(DOMNode.ownerDocument, (Page) doc);
//
//            return template;
//
//          } catch (FrameworkException ex) {
//            ex.printStackTrace();
//          }
//
//        }
//
//        final List<DOMNode> syncedNodes = template.getProperty(DOMNode.syncedNodes);
//
//        for (final DOMNode syncedNode : syncedNodes) {
//
//          doc = syncedNode.getOwnerDocument();
//
//          if (doc != null && doc.equals(page)) {
//
//            return (Template) syncedNode;
//
//          }
//
//        }
//
//      }
//
//      node = (DOMNode) node.getParentNode();
//
//    }
//
//    return null;
//
//  }
//
//  private Page getClosestPage(DOMNode node) {
//
//    while (node != null) {
//
//      if (node instanceof Page) {
//
//        return (Page) node;
//      }
//
//      node = (DOMNode) node.getParentNode();
//
//    }
//
//    return null;
//  }
}
TOP

Related Classes of org.structr.web.common.RenderContext

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.