Package eu.planets_project.ifr.core.storage.impl.jcr

Source Code of eu.planets_project.ifr.core.storage.impl.jcr.DOJCRManager

/**
* This class is an JCR manager for digital objects
*/
package eu.planets_project.ifr.core.storage.impl.jcr;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.ListIterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jcr.ItemNotFoundException;
import javax.jcr.LoginException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.VersionException;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import eu.planets_project.ifr.core.common.conf.PlanetsServerConfig;
import eu.planets_project.ifr.core.storage.api.DigitalObjectManager.DigitalObjectNotFoundException;
import eu.planets_project.ifr.core.storage.api.DigitalObjectManager.DigitalObjectNotRemovedException;
import eu.planets_project.ifr.core.storage.api.DigitalObjectManager.DigitalObjectNotStoredException;
import eu.planets_project.ifr.core.storage.api.DigitalObjectManager.DigitalObjectTooLargeException;
import eu.planets_project.ifr.core.storage.api.DigitalObjectManager.DigitalObjectUpdateException;
import eu.planets_project.services.datatypes.Agent;
import eu.planets_project.services.datatypes.Content;
import eu.planets_project.services.datatypes.DigitalObject;
import eu.planets_project.services.datatypes.DigitalObjectContent;
import eu.planets_project.services.datatypes.Event;
import eu.planets_project.services.datatypes.Metadata;


/**
* This class manages lookup, connection
* and sessions to a Java Content Repository for DigitalObject. 
*
*/
public class DOJCRManager {
  // Define user data for session login
  private static final String USERNAME = "admin";
  private static final String PASSWORD = "admin";
 
  // Define repository class
  private static final String TRANSIENT_CLASS = "Transient";
 
  /**
   * String constant for PLANETS namespace prefix
   */
  public static final String PLANETS_NAMESPACE_PREFIX = "planets";
 
  private static final String DEFAULT_PROPERTY_VALUE = "default";
 
  /**
   * String constant for PLANETS namespace URI
   */
  public static final String PLANETS_NAMESPACE_URI = "http:planets_project.eu/planets";

  /**
   * String constant for content resolver URI
   */
  public static final String CONTENT_RESOLVER_URI = "/storage/jcr/contentResolver?id=";
  public static final String PROTOCOL = "http://";

  /**
   * String constant for the error handling
   */
  public static final String DIGITAL_OBJECT_NOT_FOUND = "Digital object not found. ";
  public static final String DIGITAL_OBJECT_TOO_LARGE = "Digital object too large. ";
  /**
   * String constant for PLANETS namespace URI
   */
  public static final String PERMANENT_URI = "/planets";
 
  public static final int FIRST_ENTRY = 1;
 
  /**
   * This is a buffer size and a max byte array size for reading data
   * from InputStream to byte array
   */
  public static final int BUFFER_SIZE = 1048576;
  public static final int MAX_SIZE = BUFFER_SIZE*5;

  /**
   * JCR repository variables
   */
  private Repository repository = null;
    private javax.jcr.Session session = null;
   
    /**
     * Logger for planets
     */
  private static Logger _log = Logger.getLogger(DOJCRManager.class.getName());
   
  /**
   * Constructor for DOJCRManager, connects to repository and initialises object.
   *
   * @param  repositoryName
   *       JNDI name of the JCR to connect to.
   * @param  logger
   *       A PLANETS logger instance used for logging and debugging.
   * @throws  NamingException
   *       Thrown when the JNDI lookup for the Jackrabbit repository fails. 
   *          Suggests an installation / setup problem.
   */
    public DOJCRManager(String repositoryName, Logger logger) throws NamingException
    {
    try {
      _log = logger;
      _log.log(Level.INFO, "DOJCRManager constructor");

        InitialContext ctx = new InitialContext();
      _log.log(Level.INFO, "DOJCRManager constructor after ctx");

      // JNDI Lookup of the repository
      System.out.println("DOJCRManager constructor after load");
          this.repository = (Repository)ctx.lookup(repositoryName);
      _log.log(Level.INFO, "DOJCRManager call getSession() repository: " + repository.toString());
          this.initialiseRepository();
      _log.log(Level.INFO, "DOJCRManager after call initialiseRepository()");
    } catch (Exception _exp) {
      _log.log(Level.INFO, "Error by repository creation: " + _exp.getMessage());
    }
    }

  /**
   * Constructor for DOJCRManager, connects to repository and initializes object.
   *
   * @param  repository
   *       JCR repository to connect to.
   * @param  logger
   *       A PLANETS logger instance used for logging and debugging.
   * @throws  NamingException
   *       Thrown when the JNDI lookup for the Jackrabbit repository fails. 
   *          Suggests an installation / setup problem.
   */
    public DOJCRManager(Repository _repository, Logger logger) throws NamingException
    {
    try {
      _log = logger;
      _log.log(Level.INFO, "***********************************************");
      _log.log(Level.INFO, "DOJCRManager constructor with repository object");

          this.repository = _repository;
      _log.log(Level.INFO, "DOJCRManager call getSession() repository: " + repository.toString());
          this.initialiseRepository();
    } catch (Exception _exp) {
      _log.log(Level.INFO, "Error by repository creation: " + _exp.getMessage(), _exp);
    }
    }

    /**
     * Logs in a session to the repository.
     * @throws LoginException
     * @throws RepositoryException
     */
    private void getSession() throws LoginException, RepositoryException
    {
    _log.log(Level.INFO, "DOJCRManager getSession() repository class: " + repository.getClass().getName());
        try
        {
          session = repository.login(new SimpleCredentials(USERNAME, PASSWORD.toCharArray()));
        }
        catch (Exception e)
        {
          _log.log(Level.INFO, "DOJCRManager getSession() error: " + e.getMessage(), e);
        }
    }

    /**
     * Method to open repository session.
     * Do nothing for transient repository.
     */
    private void openSession()
    {
      if (!repository.getClass().getName().contains(TRANSIENT_CLASS))
      {
         try {
         getSession();
      } catch (LoginException e) {
        e.printStackTrace();
      } catch (RepositoryException e) {
        e.printStackTrace();
      }
      }
    }
   
    /**
     * Method to close repository session.
     * Do nothing for transient repository.
     */
    private void closeSession()
    {
      if (!repository.getClass().getName().contains(TRANSIENT_CLASS))
      {
        _log.log(Level.INFO, "session logout.");
       session.logout();
      }
    }
   
    /**
     * Method to register PLANETS namespaces, nodetypes and other JCR stuff.
     */
    private void initialiseRepository()
    {
      try {
        this.getSession();
        boolean _initialiseRepository = true;
       
        // Let's see if the namespace prefix for PLANETS exists
        String[] _jcrNamespacePrefixes =
          this.session.getWorkspace().getNamespaceRegistry().getPrefixes();
        for (String _namespacePrefix : _jcrNamespacePrefixes) {
          if (_namespacePrefix.equals(PLANETS_NAMESPACE_PREFIX))
            _initialiseRepository = false;
        }
       
        // Create the PLANETS namespace
        if (_initialiseRepository) {
          this.session.getWorkspace().getNamespaceRegistry().registerNamespace
             (PLANETS_NAMESPACE_PREFIX, PLANETS_NAMESPACE_URI);
        }
      } catch (LoginException _exp) {
      _log.log(Level.INFO, "initialiseRepository LoginException: " + _exp.getMessage(), _exp);
      } catch (RepositoryException _exp) {
      _log.log(Level.INFO, "initialiseRepository RepositoryException: " + _exp.getMessage(), _exp);
      } finally {
        closeSession();
      }
    }

    /**
     * This method manages an opening or creation of node with digital object data
     * @param path
     *    The path to the node with digital object data
     * @return node
     *    The node with digital object data
     * @throws IOException
     * @throws RepositoryException
     */
    private Node createDocumentNode(String path) throws IOException, RepositoryException
    {
    // Carve the path into an array around the separator character
//    _log.log(Level.INFO, "splitting path array");
    String[] _pathArray = path.split(DOJCRConstants.JCR_PATH_SEPARATOR);

    // Get the root node for the workspace
//    _log.log(Level.INFO, "getting root node");
    Node _node = session.getRootNode();
   
    // Now loop through the path array and navigate the path, creating the nt:folder nodes that don't exist
    // We save the last part of the path as this is the name and is hence an nt:file node
//    _log.log(Level.INFO, "iterating through " + _pathArray.length + " elements");
    for (int _loop = 1; _loop < _pathArray.length - 1; _loop++) {
      // Check to see if the current node has a child matching the next path part
//      _log.log(Level.INFO, "element " + _loop);
//      _log.log(Level.INFO, "element is called:" + _pathArray[_loop]);
      if (!_node.hasNode(_pathArray[_loop])) {
        // If it doesn't then create the nt:folder node and set _node to the newly created node
//        _log.log(Level.INFO, "adding:" + _pathArray[_loop]);
        _node = _node.addNode(_pathArray[_loop]);
//        _log.log(Level.INFO, "finished the add call");
      } else {
        // Else if it exists get it and set _node to the retrieved node
//        _log.log(Level.INFO, "getting:" + _pathArray[_loop]);
        _node = _node.getNode(_pathArray[_loop]);
      }
    }
   
    // We're at the end of the loop so this is the final part of the path which is the name of the file node
    // First get the last part of the path array and check to see if the node exists
    _log.log(Level.INFO, "at last node now called:" + _pathArray[_pathArray.length - 1]);
    if (!_node.hasNode(_pathArray[_pathArray.length - 1]))
    {
      _log.log(Level.INFO, "throwing file exists exception");
    }
    // If not then create it
    _node = _node.addNode(_pathArray[_pathArray.length - 1]);
    return _node;
    }

    /**
     * This method manages a node with binary data content
     * @param path
     *    The path to the node with binary data content
     * @return node
     *    The node with binary data content
     * @throws RepositoryException
     */
    private Node createResourceNode(String path) throws RepositoryException
    {
    _log.log(Level.INFO, "createResourceNode() path: " + path);
     
    // Carve the path into an array around the separator character
    String[] _pathArray = path.split(DOJCRConstants.JCR_PATH_SEPARATOR);

    // Get the current node for the workspace
    Node _node = openNode(path);

    _log.log(Level.INFO, "createResourceNode() node evaluated.");
    dumpNode(_node);
    // We're at the end of the loop so this is the final part of the path which is the name of the file node
    // First get the last part of the path array and check to see if the node exists
    if (!_node.hasNode(_pathArray[_pathArray.length - 1]))
    {
      // If not then create it, we need to add an nt:file node and an nt:resource node named jcr:content that
      // holds the binary
      _node = _node.addNode(_pathArray[_pathArray.length - 1],
                        DOJCRConstants.NT_FILE);
      dumpNode(_node);
      _node = _node.addNode(DOJCRConstants.JCR_CONTENT,
                  DOJCRConstants.NT_RESOURCE);
      dumpNode(_node);
          _log.log(Level.INFO, "createResourceNode() add new node path: " + _node.getPath());
    }
    else {
      // If the node already existed then throw a file exists exception as the JCR is write once
          _log.log(Level.INFO, "createResourceNode() file exists node path: " + _node.getPath());
      throw new RuntimeException("File exists");
    }

    // Set the modified date
        Calendar _rightNow = Calendar.getInstance();
        _node.setProperty(DOJCRConstants.JCR_LASTMODIFIED, _rightNow);
        // Finally the mimetype property to a default
        _node.setProperty(DOJCRConstants.JCR_MIMETYPE, DOJCRConstants.DOJCR_PROPERTY_DEFAULT_MIMETYPE);

        _log.log(Level.INFO, "createResourceNode() node path: " + _node.getPath());
    dumpNode(_node);
   
    return _node;
    }
   
    /**
     * Checks whether a particular JCR node exists.
     *
     * @param  path
     *       Node path to test for node existence.
     * @return  true if node exists at path, false otherwise.
     * @throws  RepositoryException
     */
    public boolean nodeExists(String path) throws RepositoryException
    {
      boolean _retVal = false;
      try {
        // Get a JCR Session
        this.getSession();
       
        // Get the item, wee don't need it, just find if it exists.
        session.getItem(path);
        _retVal = true;
      } catch (PathNotFoundException _exp) {
        _retVal = false;
      } finally {
        session.logout();
      }
      return _retVal;
    }
   
    /**
     * This method manages an opening or creating of a node
     * @param path
     *    The path to the node
     * @return node
     *    The current node
     * @throws RepositoryException
     */
    private Node openNode(String path) throws RepositoryException
    {
    // Carve the path into an array around the separator character
    String[] _pathArray = path.split(DOJCRConstants.JCR_PATH_SEPARATOR);
//    _log.log(Level.INFO, "path length: " + _pathArray.length);

    // Get the root node for the workspace
    Node _node = session.getRootNode();
   
    // Now loop through the path array and navigate the path, creating the nt:folder nodes that don't exist
    // We save the last part of the path as this is the name and is hence an nt:file node
    for (int _loop = 1; _loop < _pathArray.length - 1; _loop++) {
      // Check to see if the current node has a child matching the next path part
      if (!_node.hasNode(_pathArray[_loop])) {
        // If it doesn't then create the nt:folder node and set _node to the newly created node
//        _log.log(Level.INFO, "create nt:folder node: " + _pathArray[_loop]);
        _node = _node.addNode(_pathArray[_loop], DOJCRConstants.NT_FOLDER);
      } else {
        // Else if it exists get it and set _node to the retrieved node
//        _log.log(Level.INFO, "get existing nt:folder node: " + _pathArray[_loop]);
        _node = _node.getNode(_pathArray[_loop]);
      }
    }
   
//        _log.log(Level.INFO, "openNode() node path: " + _node.getPath());
        dumpNode(_node);

        return _node;
    }
   
    /**
     * This method manages a retrieving of a node content
     * @param path
     *    The path to the node
     * @return node
     *    The current node
     * @throws RepositoryException
     */
    private Node retrieveDigitalObjectNode(String path) throws RepositoryException
    {
    // Carve the path into an array around the separator character
    String[] _pathArray = path.split(DOJCRConstants.JCR_PATH_SEPARATOR);
    _log.log(Level.INFO, "path length: " + _pathArray.length);

    // Get the root node for the workspace
    Node _node = session.getRootNode();
   
    // Now loop through the path array and navigate the path.
    for (int _loop = 1; _loop < _pathArray.length; _loop++) {
      // Check to see if the current node has a child matching the next path part
      if (!_node.hasNode(_pathArray[_loop])) {
        // If it doesn't then do nothing
        _log.log(Level.INFO, "retrieveDigitalObjectNode() error - not found nt:folder node: " +
               _pathArray[_loop]);
      } else {
        // Else if it exists get it and set _node to the retrieved node
        _log.log(Level.INFO, "retrieveDigitalObjectNode() get existing nt:folder node: " +
               _pathArray[_loop]);
        _node = _node.getNode(_pathArray[_loop]);
      }
    }
   
        _log.log(Level.INFO, "retrieveDigitalObjectNode() node path: " + _node.getPath());

        return _node;
    }
   
  /**
   * Persists a Metadata list to the JCR beneath
   *
   * @param  metadataList
   *       The Metadata list to persist in the JCR
   * @param  current digital object node
   * @return  The result of function
   */
    public int storeMetadataList(List<Metadata> metadataList, Node currentNode)
    {
      int res = DOJCRConstants.RESULT_OK;
     
    dumpNode(currentNode);
    ListIterator<Metadata> iter = metadataList.listIterator();
   
        if ((metadataList != null) && (metadataList.size() > 0))
        {
      while(iter.hasNext())
      {
        Metadata metadataObj = iter.next();
        try
        {
           storeMetadata(metadataObj, currentNode);
        } catch (Exception e)
        {
          _log.log(Level.INFO, "storeMetadataList() error: " + e.getMessage(), e);
              res = DOJCRConstants.RESULT_ERROR;
        }
      }
        }
        else
        {
          _log.log(Level.INFO, "storeMetadataList()  list is empty.");
          res = DOJCRConstants.RESULT_LIST_EMPTY;
        }
       
        return res;
    }
   
  /**
   * Persists an Event list to the JCR beneath
   *
   * @param  EventList
   *       The Event list to persist in the JCR
   * @param  current digital object node
   * @return  The result of function
   */
    public int storeEventsList(List<Event> eventsList, Node currentNode)
    {
      int res = DOJCRConstants.RESULT_OK;
     
    ListIterator<Event> iter = eventsList.listIterator();
   
        if ((eventsList != null) && (eventsList.size() > 0))
        {
      while(iter.hasNext())
      {
        Event eventsObj = iter.next();
        try
        {
           storeEvent(eventsObj, currentNode);
        } catch (Exception e)
        {
          _log.log(Level.INFO, "storeEventList() error: " + e.getMessage(), e);
              res = DOJCRConstants.RESULT_ERROR;
        }
      }
        }
        else
        {
          _log.log(Level.INFO, "storeEventList() list is empty.");
          res = DOJCRConstants.RESULT_LIST_EMPTY;
        }
       
        return res;
    }
   
  /**
   * Persists an Event list to the JCR beneath
   *
   * @param  EventList
   *       The Event list to persist in the JCR
   * @param  current digital object node
   * @return  The result of function
     * @throws DigitalObjectUpdateException
   */
    public int updateEvents(List<Event> eventsList, Node currentNode)
          throws DigitalObjectUpdateException
    {
      int res = DOJCRConstants.RESULT_OK;
     
        if ((eventsList != null) && (eventsList.size() > 0))
        {
          try {
                NodeIterator entries = currentNode.getNodes(DOJCRConstants.DOJCR_EVENTS);
                if (entries != null)
                {
                   _log.log(Level.INFO, "updateEvents entries size: " + entries.getSize());
                }
                else
                {
                  _log.log(Level.INFO, "updateEvents size is null");
                }
               
                while (entries.hasNext())
                {
                    Node node = entries.nextNode();
                    if (node != null)
                    {
                       _log.log(Level.INFO, "updateEvents node path: " + node.getPath());
                       node.remove();
                    }
                    else
                    {
                     _log.log(Level.INFO, "updateEvents node is null");
                    }
                }
          } catch (Exception e)
          {
             _log.log(Level.INFO, "updateEvents() error: " + e.getMessage(), e);
              throw new DigitalObjectUpdateException(
                 "updateEvents() error: " + e.getMessage());
          }
       
        storeEventsList(eventsList, currentNode);
        }
     
        return res;
    }
   
  /**
   * Persists a meta data list to the JCR beneath
   *
   * @param  MetadataList
   *       The meta data list to persist in the JCR
   * @param  current digital object node
   * @return  The result of function
     * @throws DigitalObjectUpdateException
     */
    public int updateMetadata(List<Metadata> metadataList, Node currentNode)
          throws DigitalObjectUpdateException
    {
      int res = DOJCRConstants.RESULT_OK;
     
        if ((metadataList != null) && (metadataList.size() > 0))
        {
          try {
                NodeIterator entries = currentNode.getNodes(DOJCRConstants.DOJCR_METADATA);
                if (entries != null)
                {
                   _log.log(Level.INFO, "updateMetadata entries size: " + entries.getSize());
                }
                else
                {
                  _log.log(Level.INFO, "updateMetadata size is null");
                }
               
                while (entries.hasNext())
                {
                    Node node = entries.nextNode();
                    if (node != null)
                    {
                       _log.log(Level.INFO, "updateMetadata node path: " + node.getPath());
                       node.remove();
                    }
                    else
                    {
                     _log.log(Level.INFO, "updateMetadata node is null");
                    }
                }
          } catch (Exception e)
          {
             _log.log(Level.INFO, "updateMetadata() error: " + e.getMessage(), e);
              throw new DigitalObjectUpdateException(
                 "updateMetadata() error: " + e.getMessage());
          }
       
        storeMetadataList(metadataList, currentNode);
        }
     
        return res;
    }
   
  /**
   * Persists a Property list to the JCR beneath
   *
   * @param  propertyList
   *       The Property list to persist in the JCR
   * @param  current digital object node
   * @return  The result of function
   */
    public int storePropertyList
          ( List<eu.planets_project.services.datatypes.Property> propertyList
          , Node eventNode
          )
    {
      int res = DOJCRConstants.RESULT_OK;
     
    ListIterator<eu.planets_project.services.datatypes.Property> iter = propertyList.listIterator();
   
        if ((propertyList != null) && (propertyList.size() > 0))
        {
      while(iter.hasNext())
      {
        eu.planets_project.services.datatypes.Property propertyObj = iter.next();
        try
        {
           storeProperty(propertyObj, eventNode);
        } catch (Exception e)
        {
          _log.log(Level.INFO, "storePropertyList() error: " + e.getMessage(), e);
              res = DOJCRConstants.RESULT_ERROR;
        }
      }
        }
        else
        {
          _log.log(Level.INFO, "storePropertyList() list is empty.");
          res = DOJCRConstants.RESULT_LIST_EMPTY;
        }
       
        return res;
    }
   
  /**
   * Persists a Metadata object to the JCR beneath
   *
   * @param  metadataObj
   *       The Metadata object to persist in the JCR
   * @param  current digital object node
   * @return  The result of function
   * @throws  IOException
   * @throws  ItemNotFoundException
   * @throws  RepositoryException
   */
    public int storeMetadata(Metadata metadataObj, Node currentNode)
          throws IOException, ItemNotFoundException, RepositoryException
    {
      int res = DOJCRConstants.RESULT_OK;
     
      try {
        Node metadataNode = currentNode.addNode(DOJCRConstants.DOJCR_METADATA);
        dumpNode(metadataNode);
        _log.log(Level.INFO, "Creating node for the Metadata. path: " + metadataNode.getPath());
       
        // Add the specific node properties from the metadata properties
        if (metadataObj.getType() != null)
          metadataNode.setProperty( DOJCRConstants.DOJCR_METADATA_TYPE
                              , metadataObj.getType().toString());
        if (metadataObj.getContent() != null)
          metadataNode.setProperty( DOJCRConstants.DOJCR_METADATA_CONTENT
                              , metadataObj.getContent());
        if (metadataObj.getName() != null)
          metadataNode.setProperty( DOJCRConstants.DOJCR_METADATA_NAME
                              , metadataObj.getName());
        _log.log(Level.INFO, "metadataObj.getName(): " + metadataObj.getName() +
               ", content: " + metadataObj.getContent());
        session.save();
      } catch (Exception e)
      {
        _log.log(Level.INFO, "storeMetadata error: " + e.getMessage(), e);
      }
      return res;
    }

  /**
   * Persists an Event object to the JCR beneath
   *
   * @param  eventsObj
   *       The Event object to persist in the JCR
   * @param  current digital object node
   * @return  The result of function
   * @throws  IOException
   * @throws  ItemNotFoundException
   * @throws  RepositoryException
   */
    public int storeEvent(Event eventsObj, Node currentNode)
          throws IOException, ItemNotFoundException, RepositoryException
    {
      int res = DOJCRConstants.RESULT_OK;
     
      try {
        Node eventsNode = currentNode.addNode(DOJCRConstants.DOJCR_EVENTS);
        dumpNode(eventsNode);
        _log.log(Level.INFO, "Creating node for the Event. path: " + eventsNode.getPath());
        // Add the specific node properties from the events properties
        if (eventsObj.getSummary() != null)
          eventsNode.setProperty( DOJCRConstants.DOJCR_EVENTS_SUMMARY
                            , eventsObj.getSummary().toString());
        if (eventsObj.getDatetime() != null)
          eventsNode.setProperty(DOJCRConstants.DOJCR_EVENTS_DATETIME, eventsObj.getDatetime());
        if (eventsObj.getDuration() >= 0)
          eventsNode.setProperty(DOJCRConstants.DOJCR_EVENTS_DURATION, eventsObj.getDuration());
        if (eventsObj.getAgent() != null)
        {
          Node agentNode = eventsNode.addNode(DOJCRConstants.DOJCR_EVENTS_AGENT);
          agentNode.setProperty( DOJCRConstants.DOJCR_EVENTS_AGENT_ID
                           , eventsObj.getAgent().getId());
          agentNode.setProperty( DOJCRConstants.DOJCR_EVENTS_AGENT_NAME
                           , eventsObj.getAgent().getName());
          agentNode.setProperty( DOJCRConstants.DOJCR_EVENTS_AGENT_TYPE
                           , eventsObj.getAgent().getType());
        }
        if (eventsObj.getProperties() != null)
        {
              res = storePropertyList(eventsObj.getProperties(), eventsNode);
              if (res != DOJCRConstants.RESULT_OK)
              {
                _log.log(Level.INFO, "Error in storePropertyList");
              }
        }
      } catch (Exception e)
      {
        _log.log(Level.INFO, "storeEvent error: " + e.getMessage(), e);
      }
      return res;
    }

  /**
   * Persists a Property object to the JCR beneath
   *
   * @param  propertyObj
   *       The Property object to persist in the JCR
   * @param  current digital object node
   * @return  The result of function
   * @throws  IOException
   * @throws  ItemNotFoundException
   * @throws  RepositoryException
   */
    public int storeProperty(eu.planets_project.services.datatypes.Property propertyObj, Node eventNode)
          throws IOException, ItemNotFoundException, RepositoryException
    {
      int res = DOJCRConstants.RESULT_OK;
     
      try {
        Node propertyNode = eventNode.addNode(DOJCRConstants.DOJCR_EVENTS_PROPERTIES);
        // Add the specific node properties from the Property properties
        if (propertyObj.getUri() != null)
          propertyNode.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_URI
                                  , propertyObj.getUri().toString());
        if (propertyObj.getName() != null)
          propertyNode.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_NAME
                              , propertyObj.getName());
        if (propertyObj.getValue() != null)
          propertyNode.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_VALUE
                              , propertyObj.getValue());
        if (propertyObj.getDescription() != null)
          propertyNode.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_DESCRIPTION
                              , propertyObj.getDescription());
        if (propertyObj.getUnit() != null)
          propertyNode.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_UNIT
                              , propertyObj.getUnit());
        if (propertyObj.getType() != null)
          propertyNode.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_TYPE
                              , propertyObj.getType());
      } catch (Exception e)
      {
        _log.log(Level.INFO, "storeProperty error: " + e.getMessage(), e);
      }
      return res;
    }

    /**
     * Returns the persisted Metadata list identified by the passed node.
     *
     * @param  node
     *       The Metadata node to be retrieved.
     * @return  The Metadata list.
     */
    public List<Metadata> retrieveMetadataList(Node currentNode)
    {
      List<Metadata> _retVal = null;
      _retVal = new ArrayList<Metadata>();
      dumpNode(currentNode);
     
      try
      {
           NodeIterator entries = currentNode.getNodes(DOJCRConstants.DOJCR_METADATA);
           if (entries != null)
           {
              _log.log(Level.INFO, "retrieveMetadataList entries size: " + entries.getSize());
           }
           else
           {
             _log.log(Level.INFO, "retrieveMetadataList size is null");
           }
          
           while (entries.hasNext())
           {
               Node node = entries.nextNode();
               if (node != null)
               {
                  _log.log(Level.INFO, "retrieveMetadataList node path: " + node.getPath());
               }
               else
               {
                _log.log(Level.INFO, "retrieveMetadataList node is null");
               }
               Metadata metadataObj = retrieveMetadata(node);
               _retVal.add(metadataObj);
           }

    } catch (Exception e)
    {
      _log.log(Level.INFO, "retrieveMetadataList() error: " + e.getMessage(), e);
    }
       
      return _retVal;
    }
   
    /**
     * Returns the persisted Event list identified by the passed node.
     *
     * @param  node
     *       The Event node to be retrieved.
     * @return  The Event list.
     */
    public List<Event> retrieveEventList(Node currentNode)
    {
      List<Event> _retVal = null;
      _retVal = new ArrayList<Event>();
     
      try
      {
           NodeIterator entries = currentNode.getNodes(DOJCRConstants.DOJCR_EVENTS);
          
           while (entries.hasNext())
           {
               Node node = entries.nextNode();
               Event eventObj = retrieveEvent(node);
               _retVal.add(eventObj);
           }

    } catch (Exception e)
    {
      _log.log(Level.INFO, "retrieveEventList() error: " + e.getMessage(), e);
    }
       
      return _retVal;
    }
   
    /**
     * Returns the persisted Property list identified by the passed node.
     *
     * @param  node
     *       The Property node to be retrieved.
     * @return  The Property list.
     */
    public List<eu.planets_project.services.datatypes.Property> retrievePropertyList(Node eventNode)
    {
      List<eu.planets_project.services.datatypes.Property> _retVal = null;
      _retVal = new ArrayList<eu.planets_project.services.datatypes.Property>();
     
      try
      {
           NodeIterator entries = eventNode.getNodes(DOJCRConstants.DOJCR_EVENTS_PROPERTIES);
          
           while (entries.hasNext())
           {
               Node node = entries.nextNode();
               eu.planets_project.services.datatypes.Property propertyObj = retrieveProperty(node);
               _retVal.add(propertyObj);
           }

    } catch (Exception e)
    {
      _log.log(Level.INFO, "retrievePropertyList() error: " + e.getMessage(), e);
    }
       
      return _retVal;
    }
   
    /**
     * Returns the persisted details of the Metadata identified by the passed node.
     *
     * @param  node
     *       The String id of the Metadata node to be retrieved.
     * @return  The Metadata object.
     * @throws  ItemNotFoundException
     * @throws  RepositoryException
     * @throws  URISyntaxException
     */
    public Metadata retrieveMetadata(Node node) throws ItemNotFoundException,
      RepositoryException, URISyntaxException {
    Metadata _retVal = null;
    try {
      Property _propType = node
          .getProperty(DOJCRConstants.DOJCR_METADATA_TYPE);
      Property _propContent = node
          .getProperty(DOJCRConstants.DOJCR_METADATA_CONTENT);
      if (!node.hasProperty(DOJCRConstants.DOJCR_METADATA_NAME)) {
        _retVal = new Metadata(new URI(_propType.getString()),
            _propContent.getString());
      } else {
        Property _propName = node
            .getProperty(DOJCRConstants.DOJCR_METADATA_NAME);
        _retVal = new Metadata(new URI(_propType.getString()),
            _propName.getString(), _propContent.getString());
      }
      _retVal.toString();
    } catch (Exception e) {
      _log
          .log(Level.INFO, "retrieveMetadata error: "
              + e.getMessage(), e);
    }

    return _retVal;
  }
   
    /**
   * Returns the persisted details of the Event identified by the passed node.
   *
   * @param node
   *            The String id of the Event node to be retrieved.
   * @return The Event object.
   * @throws ItemNotFoundException
   * @throws RepositoryException
   * @throws URISyntaxException
   */
    public Event retrieveEvent(Node node)
          throws ItemNotFoundException, RepositoryException, URISyntaxException
    {
      Event res = null;
      try {
        Property _propSummary = node.getProperty(DOJCRConstants.DOJCR_EVENTS_SUMMARY);
        Property _propDatetime = node.getProperty(DOJCRConstants.DOJCR_EVENTS_DATETIME);
        Property _propDuration = node.getProperty(DOJCRConstants.DOJCR_EVENTS_DURATION);
        Agent agentObj = retrieveAgent(node);
          List<eu.planets_project.services.datatypes.Property> propertyResList =
            retrievePropertyList(node);
        res = new Event
              ( _propSummary.getString()
              , _propDatetime.getString()
              , _propDuration.getDouble()
              , agentObj
              , propertyResList
              );
        res.toString();
      } catch (Exception e)
      {
        _log.log(Level.INFO, "retrieveEvent error: " + e.getMessage(), e);
      }
     
      return res;
    }
   
    /**
     * Returns the persisted details of the Property identified by the passed node.
     *
     * @param  node
     *       The String id of the Property node to be retrieved.
     * @return  The Property object.
     * @throws  ItemNotFoundException
     * @throws  RepositoryException
     * @throws  URISyntaxException
     */
    public eu.planets_project.services.datatypes.Property retrieveProperty(Node node)
          throws ItemNotFoundException, RepositoryException, URISyntaxException
    {
      eu.planets_project.services.datatypes.Property res = null;
      try {
        if (!node.hasProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_URI)) {
          node.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_URI
                                  , DEFAULT_PROPERTY_VALUE);
        }
        if (!node.hasProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_NAME)) {
          node.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_NAME
                                  , DEFAULT_PROPERTY_VALUE);
        }
        if (!node.hasProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_VALUE)) {
          node.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_VALUE
                                  , DEFAULT_PROPERTY_VALUE);
        }
        if (!node.hasProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_DESCRIPTION)) {
          node.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_DESCRIPTION
                                  , DEFAULT_PROPERTY_VALUE);
        }
        if (!node.hasProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_UNIT)) {
          node.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_UNIT
                                  , DEFAULT_PROPERTY_VALUE);
        }
        if (!node.hasProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_TYPE)) {
          node.setProperty( DOJCRConstants.DOJCR_EVENTS_PROPERTIES_TYPE
                                  , DEFAULT_PROPERTY_VALUE);
        }
        Property _propUri = node.getProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_URI);
        Property _propName = node.getProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_NAME);
        Property _propValue = node.getProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_VALUE);
        Property _propDescription =
          node.getProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_DESCRIPTION);
        Property _propUnit = node.getProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_UNIT);
        Property _propType = node.getProperty(DOJCRConstants.DOJCR_EVENTS_PROPERTIES_TYPE);
        res = new eu.planets_project.services.datatypes.Property.Builder(
            new URI (_propUri.getString()))
                 .name(_propName.getString())
                 .value(_propValue.getString())
                 .description(_propDescription.getString())
                 .unit(_propUnit.getString())
                 .type(_propType.getString())
                 .build();
        res.toString();
      } catch (Exception e)
      {
        _log.log(Level.INFO, "retrieveProperty error: " + e.getMessage(), e);
      }
     
      return res;
    }
   
    /**
     * Returns the persisted Agent identified by the passed node.
     *
     * @param  eventNode
     *       The Event node containing Agent node to be retrieved.
     * @return  The Agent object.
     * @throws ItemNotFoundException
     * @throws RepositoryException
     * @throws URISyntaxException
     */
    public Agent retrieveAgent(Node eventNode)
          throws ItemNotFoundException, RepositoryException, URISyntaxException
    {
      Agent res = null;
     
      try
      {
           Node agentNode = eventNode.getNode(DOJCRConstants.DOJCR_EVENTS_AGENT);
          
        Property _propId = agentNode.getProperty(DOJCRConstants.DOJCR_EVENTS_AGENT_ID);
        Property _propName = agentNode.getProperty(DOJCRConstants.DOJCR_EVENTS_AGENT_NAME);
        Property _propType = agentNode.getProperty(DOJCRConstants.DOJCR_EVENTS_AGENT_TYPE);
        res = new Agent(
               _propId.getString(),
             _propName.getString(),
             _propType.getString()
             );
        res.toString();
    } catch (Exception e)
    {
      _log.log(Level.INFO, "retrieveAgent() error: " + e.getMessage(), e);
    }
       
      return res;
    }
       
    /**
     * This method represents a node info.
     * @param node
     *        This is a JCR node
     */
    public void dumpNode(Node node)
    {
      String res = "";
      try {
      if (node.getName().length() > 0)
      {
          res = res + "name: " + node.getName() + "; ";
      }
      if (node.getPath().length() > 0)
      {
        res = res + "path: " + node.getPath() + "; ";
      }
      if (node.hasProperties())
      {
        res = res + "hasProperties" + "; ";
      }
      if (node.getPrimaryNodeType() != null)
      {
        res = res + "type: " + node.getPrimaryNodeType().getName() + "; ";
      }
      if (node.getIndex() >= 0)
      {
        res = res + "index: " + node.getIndex() + "; ";
      }
      if (node.getDepth() >= 0)
      {
        res = res + "depth: " + node.getDepth() + "; ";
      }
      if (node.holdsLock())
      {
        res = res + "holdsLock" + "; ";
      }
      if (node.isCheckedOut())
      {
        res = res + "isCheckedOut" + "; ";
      }
      if (node.isLocked())
      {
        res = res + "isLocked" + "; ";
      }
      if (node.isModified())
      {
        res = res + "isModified" + "; ";
      }
      if (node.isNew())
      {
        res = res + "isNew" + "; ";
      }
      _log.log(Level.INFO, "[NODE] " + res);
      }
    catch (Exception e)
    {
      _log.log(Level.INFO, "dumpNode() error: " + e.getMessage(), e);
    }
    }
   
    /**
     * This method stores a string value in JCR.
     * @param node
     *        The current node
     * @param value
     *        The property value
     * @param constant
     *        The property JCR constant
     */
    public void storeStringValue(Node node, String value, String constant)
    {
    _log.log(Level.INFO, "storeStringValue() value: " + value + ", constant: " + constant);
    if (value != null)
    {
            try {
        node.setProperty(constant, value);
      } catch (ValueFormatException e) {
        e.printStackTrace();
      } catch (VersionException e) {
        e.printStackTrace();
      } catch (LockException e) {
        e.printStackTrace();
      } catch (ConstraintViolationException e) {
        e.printStackTrace();
      } catch (RepositoryException e) {
        e.printStackTrace();
      }
      }
    }
   
    /**
     * This method stores digital object content in JCR.
     * @param streamContent
     * @param path
     * @return storing result
     */
    public int storeContent(InputStream streamContent, String path)
    {
      int res = DOJCRConstants.RESULT_OK;
    _log.log(Level.INFO, "storeContent() path: " + path);
      Value contentData;
    try {
      contentData = session.getValueFactory().createValue(streamContent);
          Node node = createResourceNode
                ( path
                + DOJCRConstants.JCR_PATH_SEPARATOR
                + DOJCRConstants.DOJCR_CONTENT_FOLDER
                );
          node.setProperty(DOJCRConstants.JCR_DATA, contentData);
    } catch (UnsupportedRepositoryOperationException e) {
      e.printStackTrace();
    } catch (RepositoryException e) {
      e.printStackTrace();
    }
        return res;
    }
   
    /**
     * This method stores digital object content in JCR.
     * @param streamContent
     * @param path
     * @return storing result
     */
    public int updateContent(InputStream streamContent, String path)
    {
      int res = DOJCRConstants.RESULT_OK;
    _log.log(Level.INFO, "updateContent() path: " + path);
      Value contentData;
    try {
      contentData = session.getValueFactory().createValue(streamContent);
          Node contentNode = retrieveDigitalObjectNode
               ( path
               + DOJCRConstants.JCR_PATH_SEPARATOR
               + DOJCRConstants.DOJCR_CONTENT_FOLDER
               + DOJCRConstants.JCR_PATH_SEPARATOR
               + DOJCRConstants.JCR_CONTENT
               );
        dumpNode(contentNode);
          contentNode.setProperty(DOJCRConstants.JCR_DATA, contentData);
    } catch (UnsupportedRepositoryOperationException e) {
      e.printStackTrace();
    } catch (RepositoryException e) {
      e.printStackTrace();
    }
        return res;
    }
   
    /**
     * This method extends path with node index
     * @param index
     *    The node index
     * @return res
     *    The string representing node path extension
     */
    private String insertNodeIndexToPath(int index)
    {
      String res = "";
      if (index > FIRST_ENTRY)
      {
        res = DOJCRConstants.NODE_INDEX_BEGIN + index + DOJCRConstants.NODE_INDEX_END;
      }
      return res;
    }
   
    /**
     * This method estimates a method result
     * @param res
     *        This is a storing result as an integer value.
     */
    public void checkResult(int res)
    {
        if (res != DOJCRConstants.RESULT_OK)
      {
          switch (res)
          {
              case DOJCRConstants.RESULT_LIST_EMPTY:
                  _log.log(Level.INFO, "List is empty.");
                  break;
               
              default:
                  _log.log(Level.INFO, "Error occured.");
                  break;               
          }
      }
    }
   
  /**
   * This method stores digital object in JCR.
   *
   * @param pdURI
   *            the URI
   * @param digitalObject
   *            the object
   * @param includeContent
   *        This flag is true if content should be stored in JCR and false if not
   * @return create DigitalObject with content by reference pointing to content resolver
   * @throws DigitalObjectNotStoredException
   */
  public DigitalObject storeDigitalObjectDefinition
        ( URI uri
        , DigitalObject digitalObject
        , boolean includeContent
        )
    throws DigitalObjectNotStoredException
    {
    DigitalObject resVal = digitalObject;
      try {                 
      _log.log(Level.INFO, "storeDigitalObjectDefinition()" + digitalObject.toString());
        openSession();

        uri = URI.create(PERMANENT_URI + uri.toString());
      _log.log(Level.INFO, "storeDigitalObjectDefinition() uri: " + uri.toString());
            Node doNode = createDocumentNode
                  (uri.toString().concat(DOJCRConstants.JCR_PATH_SEPARATOR + DOJCRConstants.DOJCR));
        dumpNode(doNode);
            String path = doNode.getPath();
        if (doNode.getIndex() > 1)
            {
              path = doNode.getPath().substring
                    (0, doNode.getPath().indexOf(DOJCRConstants.NODE_INDEX_BEGIN));
            }
        _log.log(Level.INFO, "+++ path: " + path);
        URI permanentUri = URI.create(path + DOJCRConstants.JCR_PATH_SEPARATOR + doNode.getIndex());
      _log.log(Level.INFO, "storeDigitalObjectDefinition() calculated permanentUri: " +
             permanentUri.toString());
          storeStringValue(doNode, digitalObject.getTitle(), DOJCRConstants.DOJCR_TITLE);
          if (permanentUri != null)
             storeStringValue(doNode, permanentUri.toString(), DOJCRConstants.DOJCR_PERMANENT_URI);
          if (digitalObject.getFormat() != null)
          {
             storeStringValue
                   ( doNode
                 , digitalObject.getFormat().toString()
                 , DOJCRConstants.DOJCR_FORMAT
                 );
          }
          if (digitalObject.getManifestationOf() != null)
          {
                storeStringValue
                   ( doNode
                   , digitalObject.getManifestationOf().toString()
                   , DOJCRConstants.DOJCR_MANIFESTATION_OF
                   );
          }
       
          if (digitalObject.getContent() != null)
        {
              _log.log(Level.INFO, "store content.");
        if (includeContent)
        {
          long contentLen = digitalObject.getContent().length();
            _log.log(Level.INFO, "contentLen: " + contentLen);         
            storeContent
               ( digitalObject.getContent().getInputStream()
               , uri.toString().concat
                     ( DOJCRConstants.JCR_PATH_SEPARATOR
                 + DOJCRConstants.DOJCR
                 + insertNodeIndexToPath(doNode.getIndex())
                 )
               );
        }
        }
     
          checkResult (storeMetadataList(digitalObject.getMetadata(), doNode));
            checkResult (storeEventsList(digitalObject.getEvents(), doNode));
        session.save();

            _log.log(Level.INFO, "storing permanentUri: " + permanentUri.toString());
        /*try {
                _log.log(Level.INFO, "storing digitalObject.content: " + digitalObject.getContent().read().read());
        } catch (IOException e) {
          e.printStackTrace();
        }  */
        if (digitalObject.getTitle() != null) {
               _log.log(Level.INFO, "storing digitalObject.title: " + digitalObject.getTitle());
        }
           
        DigitalObject.Builder b = new DigitalObject.Builder(
            Content.byReference(URI.create((getResolverPath() + permanentUri)).toURL()));
        if (digitalObject.getTitle() != null) b.title(digitalObject.getTitle());
        if (permanentUri != null) b.permanentUri(permanentUri);
        if (digitalObject.getFormat() != null) b.format(digitalObject.getFormat());
        if (digitalObject.getManifestationOf() != null)
          b.manifestationOf(digitalObject.getManifestationOf());
        if (digitalObject.getMetadata() != null)
          b.metadata((Metadata[]) digitalObject.getMetadata().toArray(new Metadata[0]));
        if (digitalObject.getEvents() != null)
          b.events((Event[]) digitalObject.getEvents().toArray(new Event[0]));
            resVal = b.build();
            _log.log(Level.INFO, "storing completed. ");
            resVal.toString();
      } catch (Exception e) {
        _log.log(Level.INFO, "storeDigitalObjectDefinition() error: " + e.getMessage(), e);       
      throw new DigitalObjectNotStoredException("storeDigitalObjectDefinition() error: ", e);
      } finally {
        closeSession();
      }

    return resVal;
  }
   
  /**
   * This method removes digital object from JCR identified by
   * the passed permanent URI.
   *
   * @param permanentURI
   *        The permanent URI of digital object to be removed
   * @return result of remove method
   * @throws DigitalObjectNotRemovedException
   */
  public int removeDigitalObject
        ( URI permanentUri
        )
    throws DigitalObjectNotRemovedException
    {
    int res = DOJCRConstants.RESULT_OK;
      try {                 
        openSession();
           Node node = findNodeByPermanentUri(permanentUri);
           node.remove();
      } catch (Exception e) {
        _log.log(Level.INFO, "removeDigitalObject() error: " + e.getMessage(), e);
        res = DOJCRConstants.RESULT_ERROR;
      throw new DigitalObjectNotRemovedException("removeDigitalObject() error: ", e);
      } finally {
        closeSession();
      }

    return res;
  }

  /**
   * This method removes all digital objects from JCR.
   *
   * @return result of remove method
   * @throws DigitalObjectNotRemovedException
   */
  public int removeAll()
    throws DigitalObjectNotRemovedException
    {
    int res = DOJCRConstants.RESULT_OK;
      try {                 
        openSession();
        session.getRootNode().getNode(PLANETS_NAMESPACE_PREFIX).remove();
        session.save();
      } catch (Exception e) {
        _log.log(Level.INFO, "removeAll() error: " + e.getMessage(), e);
        res = DOJCRConstants.RESULT_ERROR;
      throw new DigitalObjectNotRemovedException("removeAll() error: ", e);
      } finally {
        closeSession();
      }

    return res;
  }

  /**
     * This method checks and retrieves a string property from JCR
     * @param node
     *    This is a node to which property belongs
     * @param name
     *    This is a property name
     * @return property content as a string
     */
    public String getStrProperty(Node node, String name)
    {
      String res = null;
        try {
      if (node.hasProperty(name))
      {
         _log.log(Level.INFO, "retrieveDigitalObjectDefinition() " + name + ": " +
             node.getProperty(name).getString());
         Property _prop = node.getProperty(name);
         res = _prop.getString();
      }
    } catch (ValueFormatException e) {
      e.printStackTrace();
      _log.log(Level.INFO, e.getMessage(), e);
    } catch (PathNotFoundException e) {
      e.printStackTrace();
      _log.log(Level.INFO, e.getMessage(), e);
    } catch (RepositoryException e) {
      e.printStackTrace();
      _log.log(Level.INFO, e.getMessage(), e);
    }
        return res;
    }

    /**
     * This method returns HTTP content resolver path for permanent URI
     * @return path
     */
    public static String getResolverPath()
    {
      return PROTOCOL + PlanetsServerConfig.getHostname() + ":"
        + PlanetsServerConfig.getPort() + CONTENT_RESOLVER_URI;
    }
   
    /**
     * This method evaluates digital object content by reference using permanent URI
     * @param permanentUri
     * @return digital object content
     * @throws MalformedURLException
     */
    public DigitalObjectContent evaluateContentByReference(String permanentUri)
          throws MalformedURLException
    {
       DigitalObjectContent resultContent = null;
     
        _log.log(Level.INFO, "Create DO with content by reference");             
     URI contentResolverUri = URI.create(getResolverPath() + permanentUri);
     resultContent = Content.byReference(contentResolverUri.toURL());

     return resultContent;
    }
   
    /**
     * This method evaluates digital object content from JCR. It could be content by value
     * or content by reference.
     * @param node
     *        The JCR node storing contentNode with content data
     * @param includeContent
     *        If this flag is true - read content by value otherwise read by reference
     * @param permanentUri
     *        This is a permanent URI needed for content resolver request
     * @return resultContent
     *         This is a content retrieved from JCR for the particular digital object
     * @throws ItemNotFoundException
     * @throws RepositoryException
     * @throws DigitalObjectNotFoundException
     * @throws MalformedURLException
     * @throws DigitalObjectTooLargeException
     */
    public DigitalObjectContent evaluateContent(Node node, boolean includeContent, String permanentUri)
       throws ItemNotFoundException, RepositoryException, DigitalObjectNotFoundException,
              MalformedURLException, DigitalObjectTooLargeException
    {
       DigitalObjectContent resultContent = null;
    
      if (includeContent)
     {
          _log.log(Level.INFO, "evaluateContent() retrieve content.");
          dumpNode(node);
           Node contentNode = retrieveDigitalObjectNode
               ( node.getPath()
               + DOJCRConstants.JCR_PATH_SEPARATOR
               + DOJCRConstants.DOJCR_CONTENT_FOLDER
               + DOJCRConstants.JCR_PATH_SEPARATOR
               + DOJCRConstants.JCR_CONTENT
               );
      dumpNode(contentNode);
      InputStream contentStream =
        (InputStream) contentNode.getProperty(DOJCRConstants.JCR_DATA).getStream();
     
      // Transfer bytes from InputStream to byte array
          try
          {
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       byte[] buf = new byte[BUFFER_SIZE];
       int len;
//       _log.log(Level.INFO, "##### inputstream available: " + contentStream.available());
       while ((len = contentStream.read(buf)) > 0)
       {
//        _log.log(Level.INFO, "##### buf length: " + len + ", out.len: " + out.size());
        if (out.size() > MAX_SIZE)
        {
          _log.log(Level.INFO, "File size is larger then " + MAX_SIZE);
          out.close();
                contentStream.close();
          throw new DigitalObjectTooLargeException("File size is larger then " + MAX_SIZE);
        }
          out.write(buf, 0, len);
       }
//       _log.log(Level.INFO, "##### buf length: " + len + ", out.len: " + out.size());
       byte[] byteContent = out.toByteArray();
             _log.log(Level.INFO, "evaluateContent() byteContent.length: " + byteContent.length);
             resultContent = Content.byValue(byteContent);
       out.close();
             contentStream.close();
          } catch (Exception e)
          {
           _log.log(Level.INFO, "contentStream.close():  " + e.getMessage(), e);
          }
     }
      else
      {
      resultContent = evaluateContentByReference(permanentUri);
      }

      return resultContent;
    }
   
    /**
     * This method evaluates digital object content stream from JCR.
     * @param node
     *        The JCR node storing contentNode with content data
     * @param permanentUri
     *        This is a permanent URI needed for content resolver request
     * @return resultStream
     *         This is a content stream retrieved from JCR for the particular digital object
     * @throws ItemNotFoundException
     * @throws RepositoryException
     * @throws DigitalObjectNotFoundException
     * @throws MalformedURLException
     */
    public InputStream evaluateContentAsStream(Node node, String permanentUri)
       throws ItemNotFoundException, RepositoryException, DigitalObjectNotFoundException,
              MalformedURLException
    {
       InputStream contentStream = null;
    
      _log.log(Level.INFO, "evaluateContentAsSteam() retrieve content stream.");
      dumpNode(node);
       Node contentNode = retrieveDigitalObjectNode
           ( node.getPath()
           + DOJCRConstants.JCR_PATH_SEPARATOR
           + DOJCRConstants.DOJCR_CONTENT_FOLDER
           + DOJCRConstants.JCR_PATH_SEPARATOR
           + DOJCRConstants.JCR_CONTENT
           );
    dumpNode(contentNode);
    contentStream = contentNode.getProperty(DOJCRConstants.JCR_DATA).getStream();
     
     return contentStream;
    }
   
    /**
     * This method returns a node in JCR for particular permanent URI
     * @param permanentUri
     *        This is an identifier for the node
     * @return node
     *         This is a node containing permanent URI
     * @throws ItemNotFoundException
     * @throws RepositoryException
     * @throws DigitalObjectNotFoundException
     */
    public Node findNodeByPermanentUri(URI permanentUri)
          throws ItemNotFoundException, RepositoryException, DigitalObjectNotFoundException
    {
      Node node = null;
      try {
        _log.log(Level.INFO, "findNodeByPermanentUri() permanentUri: " + permanentUri.toString());

        // Carve the permanent URI into an array around the separator character
    String[] _pathArray = permanentUri.toString().split(DOJCRConstants.JCR_PATH_SEPARATOR);
        String digitalObjectIndex = _pathArray[_pathArray.length - 1];
    _log.log(Level.INFO, "findNodeByPermanentUri() digitalObjectIndex: " + digitalObjectIndex);

        node = openNode
              ( permanentUri.toString().replace
                  ( DOJCRConstants.DOJCR
                , DOJCRConstants.DOJCR + DOJCRConstants.NODE_INDEX_BEGIN
                                       + digitalObjectIndex
                                       + DOJCRConstants.NODE_INDEX_END
                )
            );
      } catch (Exception e) {
        _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + e.getMessage(), e);
          throw new DigitalObjectNotFoundException(DIGITAL_OBJECT_NOT_FOUND + e.getMessage());
       }

      return node;
    }
   
    /**
     * Returns the persisted details of the DigitalObject identified by the passed JCR node
     * and content.
     * @param node
     *        This is an JCR node containing persisted data
     * @param content
     *        This is a content for digital object
     * @return  The DigitalObject with id property equal to the passed id String.
     * @throws  ItemNotFoundException
     * @throws  RepositoryException
     * @throws  DigitalObjectNotFoundException
     */
    public DigitalObject fillDigitalObject(Node node, DigitalObjectContent content)
       throws ItemNotFoundException, RepositoryException, DigitalObjectNotFoundException
    {
      DigitalObject _retVal = null;
      try {
          String _title = getStrProperty(node, DOJCRConstants.DOJCR_TITLE);
          String _format = getStrProperty(node, DOJCRConstants.DOJCR_FORMAT);
          String _permanentUri = getStrProperty(node, DOJCRConstants.DOJCR_PERMANENT_URI);
          String _manifestationOf = getStrProperty(node, DOJCRConstants.DOJCR_MANIFESTATION_OF);
         List<Metadata> metadataResList = retrieveMetadataList(node);
         Metadata[] metaList = (Metadata[]) metadataResList.toArray(new Metadata[0])
         List<Event> eventResList = retrieveEventList(node);
         Event[] eventList = (Event[]) eventResList.toArray(new Event[0]);

       DigitalObject.Builder b = new DigitalObject.Builder(content);
       if (_title != null) b.title(_title);
       if (_permanentUri != null) b.permanentUri(URI.create(_permanentUri));
       if (_format != null) b.format(URI.create(_format));
       if (_manifestationOf != null) b.manifestationOf(URI.create(_manifestationOf));
       if (metaList != null) b.metadata(metaList);
       if (eventList != null) b.events(eventList);
           _retVal = b.build();
           _log.log(Level.INFO, "fillDigitalObject() retrieve completed. " + _retVal.toString());
      } catch (Exception e) {
        _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + e.getMessage(), e);
          throw new DigitalObjectNotFoundException(DIGITAL_OBJECT_NOT_FOUND + e.getMessage());
      }
     
      return _retVal;
    }
   
    /**
     * Returns the persisted details of the DigitalObject identified by the passed id String.
     *
     * @param  permanentUri
     *       The String id of the DigitalObject to be retrieved.
     * @param includeContent
     *        If this flag is true - retrieve digital object with content otherwise without content.
     * @return  The DigitalObject with id property equal to the passed id String.
     * @throws ItemNotFoundException
     * @throws RepositoryException
     * @throws DigitalObjectNotFoundException
     * @throws DigitalObjectUpdateException
     */
    public DigitalObject retrieveDigitalObjectDefinition(URI permanentUri, boolean includeContent)
       throws ItemNotFoundException, RepositoryException, DigitalObjectNotFoundException,
              DigitalObjectUpdateException
    {
      return updateDigitalObjectExt(permanentUri, includeContent, null);
    }
   
    /**
     * This method updates persisted in JCR repository details of the DigitalObject.
     *
   * @param node
   *        The node to update.
   * @param includeContent
   *        This is a flag to process an action including content (flag is true) or not
   * @param newObject
   *        This is an updated digital object
     * @return  The DigitalObject with id property equal to the passed id String.
     * @throws DigitalObjectUpdateException
     */
    public int updateDigitalObjectParameters(Node node, boolean includeContent, DigitalObject newObject)
          throws DigitalObjectUpdateException
    {
       int res = DOJCRConstants.RESULT_OK;
      
       try {
        String _title = getStrProperty(node, DOJCRConstants.DOJCR_TITLE);
        String _format = getStrProperty(node, DOJCRConstants.DOJCR_FORMAT);
        String _permanentUri = getStrProperty(node, DOJCRConstants.DOJCR_PERMANENT_URI);
        String _manifestationOf = getStrProperty(node, DOJCRConstants.DOJCR_MANIFESTATION_OF);
         List<Metadata> metadataResList = retrieveMetadataList(node);
         Metadata[] metaList = (Metadata[]) metadataResList.toArray(new Metadata[0])
         List<Event> eventResList = retrieveEventList(node);
         Event[] eventList = (Event[]) eventResList.toArray(new Event[0]);     
         DigitalObjectContent content = evaluateContent(node, includeContent, _permanentUri);
 
         if (newObject.getTitle() != null)
             if (!newObject.getTitle().equals(_title))
                storeStringValue( node
                            , newObject.getTitle()
                            , DOJCRConstants.DOJCR_TITLE);  
         if (newObject.getFormat() != null)
             if (!newObject.getFormat().toString().equals(_format))
                storeStringValue( node
                            , newObject.getFormat().toString()
                            , DOJCRConstants.DOJCR_FORMAT);
         if (newObject.getManifestationOf() != null)
           if (!newObject.getManifestationOf().toString().equals(_manifestationOf))
              storeStringValue( node
                           , newObject.getManifestationOf().toString()
                           , DOJCRConstants.DOJCR_MANIFESTATION_OF);        
         if (includeContent && newObject.getContent() != null)
         {
             if (!newObject.getContent().equals(content))
             {
          long contentLen = newObject.getContent().length();
          _log.log(Level.INFO, "contentLen: " + contentLen)
          //if persistent content is empty - store new content else update with new content
          if (content != null)
          {
            updateContent(newObject.getContent().getInputStream(), node.getPath());
          }
          else
          {
            storeContent(newObject.getContent().getInputStream(), node.getPath());
          }
             }
         }
        
         if (newObject.getMetadata() != null)
           if (!newObject.getMetadata().equals(metaList))
             checkResult (updateMetadata(newObject.getMetadata(), node));
         if (newObject.getEvents() != null)
           if (!newObject.getEvents().equals(eventList))
             checkResult (updateEvents(newObject.getEvents(), node));
 
         node.save();
       } catch (Exception e)
       {
         _log.log(Level.INFO, "updateDigitalObjectParameters() error: " + e.getMessage(), e);
         throw new DigitalObjectUpdateException(
             "updateDigitalObjectParameters() error: " + e.getMessage());
       }
   
       return res;
    }

    /**
     * Returns the updated persisted details of the DigitalObject identified
     * by the passed permanent URI from newObject.
     *
   * @param newObject
   *        This is an updated digital object
   * @param includeContent
   *        This is a flag to process an action including content (flag is true) or not
     * @return  The DigitalObject with id property equal to the passed id String.
     * @throws  ItemNotFoundException
     * @throws  RepositoryException
     * @throws DigitalObjectNotFoundException
     * @throws DigitalObjectUpdateException
     */
    public DigitalObject updateDigitalObject( DigitalObject newObject
                                        , boolean includeContent
                                        )
       throws ItemNotFoundException, RepositoryException, DigitalObjectNotFoundException,
              DigitalObjectUpdateException
    {
       return updateDigitalObjectExt(newObject.getPermanentUri(), includeContent, newObject);
    }

    /**
     * Returns the updated persisted details of the DigitalObject identified
     * by the passed permanent URI.
     *
     * @param permanentUri
     *       The String id of the DigitalObject to be retrieved.
   * @param includeContent
   *        This is a flag to process an action including content (flag is true) or not
   * @param newObject
   *        This is an updated digital object
     * @return  The DigitalObject with id property equal to the passed id String.
     * @throws  ItemNotFoundException
     * @throws  RepositoryException
     * @throws DigitalObjectNotFoundException
     * @throws DigitalObjectUpdateException
     */
    public DigitalObject updateDigitalObjectExt( URI permanentUri
                                           , boolean includeContent
                                           , DigitalObject newObject
                                           )
       throws ItemNotFoundException, RepositoryException, DigitalObjectNotFoundException,
              DigitalObjectUpdateException
    {
      DigitalObject _retVal = null;
      Node node = null;
      try {
         openSession();
       
         node = findNodeByPermanentUri(permanentUri);
         // new object contains new parameters to be updated
         if (newObject != null)
         {
           int updateRes = updateDigitalObjectParameters(node, includeContent, newObject);
           if (updateRes != DOJCRConstants.RESULT_OK)
           {
             _log.log(Level.INFO, "Could not update digital object. Result: " + updateRes);
             throw new DigitalObjectUpdateException(
                 "Could not update digital object. Result: " + updateRes);
           }
         }
         DigitalObjectContent content = evaluateContent(node, includeContent, permanentUri.toString());
         _retVal = fillDigitalObject(node, content);
           _log.log(Level.INFO, "retrieveDigitalObjectDefinition() retrieve completed. " + _retVal.toString());
      } catch (DigitalObjectTooLargeException tle) {
        _log.log(Level.INFO, DIGITAL_OBJECT_TOO_LARGE + tle.getMessage(), tle);
         try {
          DigitalObjectContent content =
            evaluateContentByReference(permanentUri.toString());
           _retVal = fillDigitalObject(node, content);
         } catch (MalformedURLException e) {
           _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + " MalformedURLException: " + e.getMessage(), e);
             throw new DigitalObjectNotFoundException(DIGITAL_OBJECT_NOT_FOUND + e.getMessage());
          }
      } catch (Exception e) {
        _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + e.getMessage(), e);
          throw new DigitalObjectNotFoundException(DIGITAL_OBJECT_NOT_FOUND + e.getMessage());
       } finally {
        closeSession();
      }
     
      return _retVal;
    }
   
    /**
     * Returns the persisted content input stream of the DigitalObject identified
     * by the passed permanent URI.
     *
     * @param  permanentUri
     *       The URI of the digital object content to be retrieved.
     * @return  The digital object content stream.
     * @throws  ItemNotFoundException
     * @throws  RepositoryException
     * @throws URISyntaxException
     * @throws DigitalObjectNotFoundException
     */
    public InputStream retrieveContentAsStream(URI permanentUri)
          throws ItemNotFoundException, RepositoryException,
                 URISyntaxException, DigitalObjectNotFoundException
    {
      _log.log(Level.INFO, "DOJCRManager.retrieveContentAsStream()");
      InputStream _retVal = null;
      try {
         openSession();
          Node node = findNodeByPermanentUri(permanentUri);
           _retVal = evaluateContentAsStream(node, permanentUri.toString());
      } catch (Exception e) {
        _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + e.getMessage(), e);
          throw new DigitalObjectNotFoundException(DIGITAL_OBJECT_NOT_FOUND + e.getMessage());
      } finally {
        closeSession();
      }
     
      return _retVal;
    }
   
    /**
     * Returns the persisted content of the DigitalObject identified by
     * the passed permanent URI.
     *
     * @param  permanentUri
     *        The URI of the digital object content to be retrieved.
     * @return The digital object content stream.
     * @throws ItemNotFoundException
     * @throws RepositoryException
     * @throws URISyntaxException
     * @throws DigitalObjectNotFoundException
     */
    public InputStream retrieveContent(URI permanentUri)
          throws ItemNotFoundException, RepositoryException,
                 URISyntaxException, DigitalObjectNotFoundException
    {
      _log.log(Level.INFO, "DOJCRManager.retrieveContent()");
      InputStream _retVal = null;
      try {
         openSession();
          Node node = findNodeByPermanentUri(permanentUri);
           _retVal = evaluateContent(node, true, permanentUri.toString()).getInputStream();
      } catch (Exception e) {
        _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + e.getMessage(), e);
          throw new DigitalObjectNotFoundException(DIGITAL_OBJECT_NOT_FOUND + e.getMessage());
      } finally {
        closeSession();
      }
     
      return _retVal;
    }
   
    /**
     * This method retrieves the parent node for all digital objects saved in JCR
     * for particular path.
     * @param _node
     *        This node is a root node evaluated from the path.
     * @param _list
     *        This is a list containing found URIs
     */
    public void findPermanentUris(Node _node, ArrayList<URI> _list)
    {
      try {
      // Iterate through the JCR nodes and add their permanent URIs to the list
        // if any exist
      NodeIterator _iterator = _node.getNodes();
      while (_iterator.hasNext())
      {
            Node _nextNode = _iterator.nextNode();
            String uriStr = getStrProperty(_nextNode, DOJCRConstants.DOJCR_PERMANENT_URI);
            if (uriStr != null)
            {
                  URI newUri = URI.create(uriStr);
                  if (newUri != null)
                  {
                 _list.add(newUri);
                }
            }
            findPermanentUris(_nextNode, _list);
      }
      } catch (LoginException _exp) {
        throw new RuntimeException(_exp);
      } catch (RepositoryException _exp) {
        throw new RuntimeException(_exp);
      }
    }
   
    /**
     * This method retrieves the parent node for all digital objects saved in JCR
     * for particular path.
     * @param _node
     *        This node is a root node evaluated from the path.
     * @param _list
     *        This is a list containing found digital objects
     */
    public void findDigitalObjects(Node _node, ArrayList<DigitalObject> _list)
       throws DigitalObjectNotFoundException, DigitalObjectUpdateException
    {
      try {
      // Iterate through the JCR nodes and add their digital objects to the list
        // if any exist
      NodeIterator _iterator = _node.getNodes();
      while (_iterator.hasNext())
      {
            Node _nextNode = _iterator.nextNode();
            String uriStr = getStrProperty(_nextNode, DOJCRConstants.DOJCR_PERMANENT_URI);
            if (uriStr != null)
            {
                  URI newUri = URI.create(uriStr);
                  if (newUri != null)
                  {
                  DigitalObject newDigitalObject = retrieveDigitalObjectDefinition(newUri, false);
                      if (newDigitalObject != null)
                      {
                     _list.add(newDigitalObject);
                      }
                }
            }
            findDigitalObjects(_nextNode, _list);
      }
      } catch (LoginException _exp) {
        throw new RuntimeException(_exp);
      } catch (RepositoryException _exp) {
        throw new RuntimeException(_exp);
      }
    }
   

    /**
     * Get an array list of permanent URIs held beneath a digital object node
     * identified by the passed path
     *
     * @param  path
     *       A JCR path to node.
     * @return  An ArrayList of digital object permanent URIs
     *          null if the node referred to by path is deeper then the digital object node
     */
    public ArrayList<URI> list(URI pathUri)
    {
      String path = pathUri.toString();
      _log.log(Level.INFO, "DOJCRManager.list() start path: " + path + ", path length: " + path.length());
      ArrayList<URI> _list = new ArrayList<URI>(0);
      try {
        // Get a repository session
          openSession();
        // First navigate to the node and get the type
        Node _node = session.getRootNode();
        // Find out the place of digital object node in the path
          int digitalObjectNodeIndex = path.indexOf(DOJCRConstants.DOJCR);
          if (digitalObjectNodeIndex > 0)
          { // digital object node exists in the path
              if (path.length() > digitalObjectNodeIndex + DOJCRConstants.DOJCR.length())
              {
                 _log.log(Level.INFO, "DOJCRManager() list() path is too deep. Return null array.");
                return null;
              }
          }
          if (path.length() > FIRST_ENTRY && _node.hasNode(path.substring(FIRST_ENTRY)))
        {
          _node = _node.getNode(path.substring(FIRST_ENTRY));
          findPermanentUris(_node, _list);
        }
      } catch (LoginException _exp) {
        throw new RuntimeException(_exp);
      } catch (RepositoryException _exp) {
        throw new RuntimeException(_exp);
      } finally {
        if( session != null )
            closeSession();
      }
      return _list;
    }
   
    /**
     * Get an array list of digital objects held beneath a digital object node
     * identified by the passed path
     *
     * @param  path
     *       A JCR path to node.
     * @return  An ArrayList of digital objects
     *          null if the node referred to by path is deeper then the digital object node
     */
    public ArrayList<DigitalObject> listDigitalObject(URI pathUri)
    {
      String path = pathUri.toString();
      _log.log(Level.INFO, "DOJCRManager.list() of digital objects. start path: " +
          path + "path length: " + path.length());
      ArrayList<DigitalObject> _list = new ArrayList<DigitalObject>(0);
      try {
        // Get a repository session
          openSession();
        // First navigate to the node and get the type
        Node _node = session.getRootNode();
        // Find out the place of digital object node in the path
          int digitalObjectNodeIndex = path.indexOf(DOJCRConstants.DOJCR);
          if (digitalObjectNodeIndex > 0)
          { // digital object node exists in the path
              if (path.length() > digitalObjectNodeIndex + DOJCRConstants.DOJCR.length())
              {
                 _log.log(Level.INFO, "DOJCRManager.listDigitalObject() path is too deep. Return null array.");
                return null;
              }
          }
          if (path.length() > FIRST_ENTRY && _node.hasNode(path.substring(FIRST_ENTRY)))
        {
          _node = _node.getNode(path.substring(FIRST_ENTRY));
          try {
             findDigitalObjects(_node, _list);
            } catch (DigitalObjectNotFoundException e) {
                 _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + e.getMessage(), e);
          } catch (DigitalObjectUpdateException e) {
               _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + e.getMessage(), e);
             }             
        }
      } catch (LoginException _exp) {
        _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + _exp.getMessage(), _exp);       
        throw new RuntimeException(_exp);
      } catch (RepositoryException _exp) {
        _log.log(Level.INFO, DIGITAL_OBJECT_NOT_FOUND + _exp.getMessage(), _exp);       
        throw new RuntimeException(_exp);
      } finally {
        if( session != null )
            closeSession();
      }
      return _list;
    }

}
TOP

Related Classes of eu.planets_project.ifr.core.storage.impl.jcr.DOJCRManager

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.