Package de.metalcon.socialgraph

Source Code of de.metalcon.socialgraph.NeoUtils

package de.metalcon.socialgraph;

import java.io.File;
import java.nio.channels.NonWritableChannelException;
import java.util.HashMap;
import java.util.Map;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.index.Index;
import org.neo4j.kernel.AbstractGraphDatabase;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import org.neo4j.kernel.EmbeddedReadOnlyGraphDatabase;

/**
* collection of useful functions for neo4j
*
* @author Jonas Kunze, Rene Pickhardt, Sebastian Schlicht
*
*/
public class NeoUtils {

  /**
   * active graph database
   */
  private static AbstractGraphDatabase DATABASE;

  /**
   * lucene index identifier
   */
  private static final String IDENTIFIER = "id";

  /**
   * lucene status update template node index
   */
  private static Index<Node> INDEX_STATUS_UPDATE_TEMPLATES;

  /**
   * lucene user node index
   */
  private static Index<Node> INDEX_USERS;

  /**
   * lucene status update node index
   */
  private static Index<Node> INDEX_STATUS_UPDATES;

  /**
   * load the database configuration map for neo4j databases
   *
   * @param config
   *            Graphity configuration containing the configuration values
   * @return neo4j database configuration map
   */
  private static Map<String, String> loadDatabaseConfig(
      final Configuration config) {
    // create database configuration
    final Map<String, String> databaseConfig = new HashMap<String, String>();

    // fill database configuration
    databaseConfig.put("cache_type", config.getCacheType());
    databaseConfig.put("use_memory_mapped_buffers",
        config.getUseMemoryMappedBuffers());

    return databaseConfig;
  }

  /**
   * load the lucene indices for a database
   *
   * @param graphDatabase
   *            social graph database to operate on
   */
  private static void loadLuceneIndices(
      final AbstractGraphDatabase graphDatabase) {
    INDEX_STATUS_UPDATE_TEMPLATES = graphDatabase.index().forNodes("tmpl");
    INDEX_USERS = graphDatabase.index().forNodes("user");
    INDEX_STATUS_UPDATES = graphDatabase.index().forNodes("stup");
  }

  /**
   * open the neo4j graph database
   *
   * @param config
   *            Graphity configuration
   * @return abstract graph database
   */
  public static AbstractGraphDatabase getSocialGraphDatabase(
      final Configuration config) {
    // prepare neo4j graph configuration
    final Map<String, String> graphConfig = loadDatabaseConfig(config);

    // load database from path specified
    AbstractGraphDatabase database;
    if (config.getReadOnly()) {
      database = new EmbeddedReadOnlyGraphDatabase(
          config.getDatabasePath(), graphConfig);
    } else {
      database = new EmbeddedGraphDatabase(config.getDatabasePath(),
          graphConfig);
    }

    // load lucene indices
    DATABASE = database;
    loadLuceneIndices(database);

    return database;
  }

  /**
   * delete file or directory
   *
   * @param file
   *            file path
   * @return true - if the file/directory has been deleted<br>
   *         false otherwise
   */
  public static boolean deleteFile(final File file) {
    // delete directory content recursively
    if (file.isDirectory()) {
      final File[] children = file.listFiles();
      for (File child : children) {
        if (!deleteFile(child)) {
          return false;
        }
      }
    }

    // delete file/empty directory
    return file.delete();
  }

  /**
   * find an incoming relation from the user passed of the specified type
   *
   * @param user
   *            destination user node
   * @param relationshipType
   *            relationship type of the relation being searched
   * @return source node of the relation<br>
   *         null - if there is no relation of the type specified
   */
  public static Node getPrevSingleNode(final Node user,
      RelationshipType relationshipType) {
    // find an incoming relation of the type specified
    final Relationship rel = user.getSingleRelationship(relationshipType,
        Direction.INCOMING);

    return (rel == null) ? (null) : (rel.getStartNode());
  }

  /**
   * find an outgoing relation from the user passed of the specified type
   *
   * @param user
   *            source user node
   * @param relType
   *            relationship type of the relation being searched
   * @return node targeted by the relation<br>
   *         null - if there is no relation of the type specified
   */
  public static Node getNextSingleNode(final Node user,
      RelationshipType relationshipType) {
    // find an outgoing relation of the type specified
    Relationship rel = null;
    try {
      rel = user.getSingleRelationship(relationshipType,
          Direction.OUTGOING);
    } catch (final NonWritableChannelException e) {
      // TODO: why is this here? Bug for read-only databases in previous
      // version?
    }

    return (rel == null) ? (null) : (rel.getEndNode());
  }

  /**
   * Search for a relationship between two nodes
   *
   * @param source
   *            source node to loop through relationships
   * @param target
   *            target node of the relationship
   * @param relationshipType
   *            relationship type of the relation being searched
   * @param direction
   *            direction of the relationship being searched
   * @return relationship instance matching the passed arguments if existing<br>
   *         <b>null</b> - otherwise
   */
  public static Relationship getRelationshipBetween(final Node source,
      final Node target, final RelationshipType relationshipType,
      final Direction direction) {
    for (Relationship relationship : source.getRelationships(
        relationshipType, direction)) {
      if (relationship.getEndNode().equals(target)) {
        return relationship;
      }
    }

    return null;
  }

  /**
   * create a user node in the active database
   *
   * @param userId
   *            user identifier
   * @return user node having its identifier stored
   * @throws IllegalArgumentException
   *             if the identifier is already in use
   */
  public static Node createUserNode(final String userId) {
    if (INDEX_USERS.get(IDENTIFIER, userId).getSingle() == null) {
      final Node user = DATABASE.createNode();
      user.setProperty(Properties.User.IDENTIFIER, userId);
      INDEX_USERS.add(user, IDENTIFIER, userId);
      return user;
    }

    throw new IllegalArgumentException("user node with identifier \""
        + userId + "\" already existing!");
  }

  /**
   * create a status update node in the active database
   *
   * @param statusUpdateId
   *            status update identifier
   * @return status update node having its identifier stored
   * @throws IllegalArgumentException
   *             if the identifier is already in use
   */
  public static Node createStatusUpdateNode(final String statusUpdateId) {
    if (INDEX_STATUS_UPDATES.get(IDENTIFIER, statusUpdateId).getSingle() == null) {
      final Node statusUpdate = DATABASE.createNode();
      statusUpdate.setProperty(Properties.StatusUpdate.IDENTIFIER,
          statusUpdateId);
      INDEX_STATUS_UPDATES.add(statusUpdate, IDENTIFIER, statusUpdateId);
      return statusUpdate;
    }

    throw new IllegalArgumentException(
        "status update node with identifier \"" + statusUpdateId
            + "\" already existing!");
  }

  /**
   * get a user node from the active database
   *
   * @param userId
   *            user node identifier
   * @return user node with the identifier passed<br>
   *         <b>null</b> if there is no user with such identifier
   */
  public static Node getUserByIdentifier(final String userId) {
    return INDEX_USERS.get(IDENTIFIER, userId).getSingle();
  }

  /**
   * get a status update node from the active database
   *
   * @param statusUpdateId
   *            status update node identifier
   * @return status update node with the identifier passed<br>
   *         <b>null</b> if there is no status update with such identifier
   */
  public static Node getStatusUpdateByIdentifier(final String statusUpdateId) {
    return INDEX_STATUS_UPDATES.get(IDENTIFIER, statusUpdateId).getSingle();
  }

  /**
   * store a status update template node in the index replacing previous
   * occurrences
   *
   * @param graphDatabase
   *            graph database to operate on
   * @param templateId
   *            template identifier
   * @param templateNode
   *            template node that shall be stored
   * @param previousTemplateNode
   *            node of the latest previous template version
   */
  public static void storeStatusUpdateTemplateNode(
      final AbstractGraphDatabase graphDatabase, final String templateId,
      final Node templateNode, final Node previousTemplateNode) {
    // remove node of the latest previous template version
    if (previousTemplateNode != null) {
      INDEX_STATUS_UPDATE_TEMPLATES.remove(previousTemplateNode,
          IDENTIFIER, templateId);
    }

    // add the new template node
    INDEX_STATUS_UPDATE_TEMPLATES.add(templateNode, IDENTIFIER, templateId);
  }

  /**
   * get a status update template node from the active database via its
   * identifier
   *
   * @param templateId
   *            status update template node identifier
   * @return status update template node with the identifier passed<br>
   *         <b>null</b>if there is no template with such identifier
   */
  public static Node getStatusUpdateTemplateByIdentifier(
      final String templateId) {
    return INDEX_STATUS_UPDATE_TEMPLATES.get(IDENTIFIER, templateId)
        .getSingle();
  }

}
TOP

Related Classes of de.metalcon.socialgraph.NeoUtils

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.