Package org.chromattic.core

Source Code of org.chromattic.core.DomainSessionImpl

/*
* Copyright (C) 2003-2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.chromattic.core;

import org.chromattic.common.logging.Logger;
import org.chromattic.api.Status;
import org.chromattic.api.DuplicateNameException;
import org.chromattic.core.mapper.TypeMapper;
import org.chromattic.core.jcr.SessionWrapper;
import org.chromattic.core.jcr.NodeDef;
import org.chromattic.core.jcr.LinkType;

import javax.jcr.Session;
import javax.jcr.RepositoryException;
import javax.jcr.Node;
import javax.jcr.ItemNotFoundException;
import javax.jcr.PathNotFoundException;
import javax.jcr.nodetype.NodeType;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
class DomainSessionImpl extends DomainSession {

  /** . */
  final Domain domain;

  /** . */
  private final SessionWrapper sessionWrapper;

  /** . */
  private final Map<String, ObjectContext> contexts;

  /** . */
  private final Logger log = Logger.getLogger(DomainSession.class);

  public DomainSessionImpl(Domain domain, SessionWrapper sessionWrapper) {
    super(domain);

    //
    this.domain = domain;
    this.sessionWrapper = sessionWrapper;
    this.contexts = new HashMap<String, ObjectContext>();
  }

  public Session getJCRSession() {
    return sessionWrapper.getSession();
  }

  protected <O> O _findByPath(Object o, Class<O> clazz, String relPath) throws RepositoryException {
    Node origin;
    if (o != null) {
      ObjectContext ctx = unwrap(o);
      origin = ctx.state.getNode();
    } else {
      origin = sessionWrapper.getSession().getRootNode();
      nodeRead(origin);
    }
    try {
      Node node = origin.getNode(relPath);
      nodeRead(node);
      return findByNode(clazz, node);
    }
    catch (PathNotFoundException e) {
      return null;
    }
  }

  protected String _persist(ObjectContext ctx, String relPath) throws RepositoryException {
    if (ctx == null) {
      throw new NullPointerException("No null object context accepted");
    }
    if (relPath == null) {
      throw new NullPointerException("No relative path specified");
    }

    //
    if (ctx.getStatus() != Status.TRANSIENT) {
      String msg = "Attempt to persist non transient object " + ctx;
      log.error(msg);
      throw new IllegalArgumentException(msg);
    }

    //
    NodeDef nodeDef = ctx.mapper.getNodeDef();
    log.trace("Setting context {} for insertion", ctx);
    log.trace("Adding node for context {} and node type {}", ctx, nodeDef);
    Node node = sessionWrapper.addNode(relPath, nodeDef);
    nodeAdded(node, ctx);
    String id = node.getUUID();
    log.trace("Added context {} for id {}", ctx, id);
    return id;
  }

  /**
   * Insert a context as a child of a parent context.
   *
   * @param parentCtx the parent context
   * @param relPath the child path relative to the parent context
   * @param childCtx
   * @return the id of the inserted context
   * @throws NullPointerException
   * @throws IllegalArgumentException
   * @throws IllegalStateException
   * @throws RepositoryException
   */
  protected String _persist(ObjectContext parentCtx, String relPath, ObjectContext childCtx) throws
    NullPointerException,
    IllegalArgumentException,
    IllegalStateException,
    RepositoryException {
    if (parentCtx == null) {
      String msg = "Cannot insert context " + childCtx + " as a child of a null context";
      log.error(msg);
      throw new NullPointerException(msg);
    }
    if (childCtx.getStatus() != Status.TRANSIENT) {
      String msg = "Attempt to insert non transient context " + childCtx + " as child of " + parentCtx;
      log.error(msg);
      throw new IllegalStateException(msg);
    }
    if (relPath == null) {
      String msg = "Attempt to insert context " + childCtx + " with no relative path to " + parentCtx;
      log.error(msg);
      throw new NullPointerException(msg);
    }
    if (parentCtx.getStatus() != Status.PERSISTENT) {
      String msg = "Attempt to insert context " + childCtx + " as child of non persistent context " + parentCtx;
      log.error(msg);
      throw new IllegalStateException(msg);
    }

    //
    Node parentNode = parentCtx.state.getNode();

    // Check insertion capability
    if (parentNode.hasNode(relPath)) {
      String msg = "Attempt to insert context " + childCtx + " as an existing child with name " + relPath + " child of context " + parentCtx;
      log.error(msg);
      throw new DuplicateNameException(msg);
    }

    //
    NodeDef nodeDef = childCtx.mapper.getNodeDef();
    log.trace("Setting context {} for insertion", childCtx);
    log.trace("Adding node for context {} and node type {} as child of context {}", childCtx, nodeDef, parentCtx);

    //
    Node childNode = sessionWrapper.addNode(parentNode, relPath, nodeDef);

    //
    nodeAdded(childNode, childCtx);
    String relatedId = childNode.getUUID();

    //
    log.trace("Added context {} for id {}", childCtx, relatedId);
    return relatedId;
  }

  protected void _orderBefore(ObjectContext parentCtx, ObjectContext srcCtx, ObjectContext dstCtx) throws RepositoryException {

    if (parentCtx == null) {
      throw new NullPointerException();
    }
    if (srcCtx == null) {
      throw new NullPointerException();
    }

    //
    Node parentNode = parentCtx.state.getNode();
    Node srcNode = srcCtx.state.getNode();
    Node dstNode = dstCtx != null ? dstCtx.state.getNode() : null;

    //
    sessionWrapper.orderBefore(parentNode, srcNode, dstNode);
  }

  protected <O> O _create(Class<O> clazz, String name) throws NullPointerException, IllegalArgumentException, RepositoryException {
    if (clazz == null) {
      throw new NullPointerException();
    }

    //
    TypeMapper typeMapper = domain.getTypeMapper(clazz);
    NodeType nodeType = sessionWrapper.getNodeType(typeMapper.getNodeDef().getPrimaryNodeTypeName());
    TransientContextState state = new TransientContextState(this, nodeType);

    //
    ObjectContext ctx = new ObjectContext(typeMapper, state);

    //
    if (name != null) {
      ctx.setName(name);
    }

    //
    broadcaster.created(ctx.getObject());

    //
    return clazz.cast(ctx.getObject());
  }

  protected <O> O _findById(Class<O> clazz, String id) throws RepositoryException {
    if (clazz == null) {
      throw new NullPointerException();
    }
    if (id == null) {
      throw new NullPointerException();
    }

    //
    ObjectContext ctx = contexts.get(id);

    // Attempt to load the object
    if (ctx == null) {
      try {
        log.trace("About to load node with id {} and class {}", id, clazz.getName());
        Node node = sessionWrapper.getNodeByUUID(id);
        nodeRead(node);
        log.trace("Loaded node with id {}", id, clazz.getName());
        ctx = contexts.get(id);
        log.trace("Obtained context {} node for id {} and class {}", ctx, id, clazz.getName());
      }
      catch (ItemNotFoundException e) {
        log.trace("Could not find node with id {}", id, clazz.getName());
        return null;
      }
      catch (RepositoryException e) {
        throw new RuntimeException(e);
      }
    }

    //
    if (ctx == null) {
      return null;
    } else {
      Object object = ctx.object;
      if (clazz.isInstance(object)) {
        return clazz.cast(object);
      } else {
        String msg = "Could not cast context " + ctx + " with class " + object.getClass().getName() + " to class " + clazz.getName();
        throw new ClassCastException(msg);
      }
    }
  }

  protected void _save() throws RepositoryException {
    sessionWrapper.save();
  }

  protected void _remove(Object o) throws RepositoryException {
    if (o == null) {
      throw new NullPointerException();
    }
    ObjectContext context = unwrap(o);
    _remove(context);
  }

  protected void _remove(ObjectContext context) throws RepositoryException {
    if (context == null) {
      throw new NullPointerException();
    }
    switch (context.state.getStatus()) {
      case TRANSIENT:
        throw new IllegalStateException("Cannot remove transient node");
      case PERSISTENT:
        Node node = context.state.getNode();
        remove(node);
        break;
      case REMOVED:
        throw new IllegalStateException("Cannot remove removed node");
      default:
        throw new AssertionError();
    }
  }

  private void remove(Node node) throws RepositoryException {
    Iterator<String> ids = sessionWrapper.remove(node);
    while (ids.hasNext()) {
      String id = ids.next();
      nodeRemoved(id);
    }
  }

  protected Object _getReferenced(ObjectContext referentCtx, String name, LinkType linkType) throws RepositoryException {
    if (referentCtx.getStatus() != Status.PERSISTENT) {
      throw new IllegalStateException();
    }
    Node referent = referentCtx.state.getNode();
    Node referenced = sessionWrapper.getReferenced(referent, name, linkType);
    if (referenced != null) {
      return findByNode(Object.class, referenced);
    } else {
      return null;
    }
  }

  protected boolean _setReferenced(ObjectContext referentCtx, String name, ObjectContext referencedCtx, LinkType linkType) throws RepositoryException {
    if (referentCtx.getStatus() != Status.PERSISTENT) {
      throw new IllegalStateException("Cannot create a relationship with a non persisted context " + this);
    }

    //
    Node referent = referentCtx.state.getNode();

    // Then create
    if (referencedCtx != null) {
      if (referencedCtx.getStatus() != Status.PERSISTENT) {
        throw new IllegalStateException();
      }

      // Should do some type checking probably!!!!

      //
      Node referenced = referencedCtx.state.getNode();

      //
      return referenced != sessionWrapper.setReferenced(referent, name, referenced, linkType);
    } else {
      return null != sessionWrapper.setReferenced(referent, name, null, linkType);
    }
  }

  protected <T> Iterator<T> _getReferents(ObjectContext referencedCtx, String name, Class<T> filterClass, LinkType linkType) throws RepositoryException {
    Node referenced = referencedCtx.state.getNode();
    Iterator<Node> referents = sessionWrapper.getReferents(referenced, name, linkType);
    return new ReferentCollectionIterator<T>(this, referents, filterClass, name);
  }

  protected void _removeChild(ObjectContext ctx, String name) throws RepositoryException {
    name = encodeName(name);
    Node node = ctx.state.getNode();
    if (node.hasNode(name)) {
      Node childNode = node.getNode(name);
      remove(childNode);
    }
  }

  protected Object _getChild(ObjectContext ctx, String name) throws RepositoryException {
    name = encodeName(name);
    Node node = ctx.state.getNode();
    log.trace("About to load the name child {} of context {}", name, this);
    Node child = sessionWrapper.getChild(node, name);
    if (child != null) {
      log.trace("Loaded named child {} of context {} with id {}", name, this, child.getUUID());
      return findByNode(Object.class, child);
    } else {
      log.trace("No child named {} to load for context {}", name, this);
      return null;
    }
  }

  protected <T> Iterator<T> _getChildren(ObjectContext ctx, Class<T> filterClass) throws RepositoryException {
    Node node = ctx.state.getNode();
    Iterator<Node> iterator = sessionWrapper.getChildren(node);
    return new ChildCollectionIterator<T>(this, iterator, filterClass);
  }

  protected Object _getParent(ObjectContext ctx) throws RepositoryException {
    if (ctx.getStatus() != Status.PERSISTENT) {
      throw new IllegalStateException();
    }
    Node node = ctx.state.getNode();
    Node parent = sessionWrapper.getParent(node);
    return findByNode(Object.class, parent);
  }

  public void nodeRead(Node node) throws RepositoryException {
    NodeType nodeType = node.getPrimaryNodeType();
    String nodeTypeName = nodeType.getName();
    TypeMapper mapper = domain.getTypeMapper(nodeTypeName);
    if (mapper != null) {
      String id = node.getUUID();
      ObjectContext ctx = contexts.get(id);
      if (ctx == null) {
        ctx = new ObjectContext(mapper);
        log.trace("Inserted context {} loaded from node id {}", ctx, id);
        contexts.put(id, ctx);
        ctx.state = new PersistentContextState(mapper, node, this);
        broadcaster.loaded(ctx.getObject());
      }
      else {
        log.trace("Context {} is already present for id ", ctx, id);
      }
    }
    else {
      log.trace("Could not find mapper for node type {}", nodeTypeName);
    }
  }

  public void nodeAdded(Node node, ObjectContext ctx) throws RepositoryException {
    NodeType nodeType = node.getPrimaryNodeType();
    String nodeTypeName = nodeType.getName();
    TypeMapper mapper = domain.getTypeMapper(nodeTypeName);
    if (mapper != null) {
      String id = node.getUUID();
      if (contexts.containsKey(id)) {
        String msg = "Attempt to replace an existing context " + ctx + " with id " + id;
        log.error(msg);
        throw new AssertionError(msg);
      }
      log.trace("Inserted context {} for id {}", ctx, id);
      contexts.put(id, ctx);
      ctx.state = new PersistentContextState(mapper, node, this);
      broadcaster.persisted(ctx.getObject());
    }
    else {
      log.trace("Could not find mapper for node type {}", nodeTypeName);
    }
  }

  public void nodeRemoved(String nodeId) throws RepositoryException {
    log.trace("Removing context for id {}", nodeId);
    ObjectContext ctx = contexts.remove(nodeId);
    if (ctx != null) {
      ctx.state = new RemovedContextState(nodeId, ctx.state.getPrimaryNodeType());
      broadcaster.removed(ctx.getObject());
      log.trace("Removed context {} for id {}", ctx, nodeId);
    } else {
      log.trace("Context absent for removal for id {}", ctx, nodeId);
    }
  }

  public void close() {
    sessionWrapper.close();
  }
}
TOP

Related Classes of org.chromattic.core.DomainSessionImpl

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.