All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.graphaware.relcount.common.internal.cache.BaseRelationshipCountCache Maven / Gradle / Ivy

package com.graphaware.relcount.common.internal.cache;

import com.graphaware.framework.config.BaseFrameworkConfigured;
import com.graphaware.propertycontainer.dto.common.relationship.SerializableTypeAndDirection;
import com.graphaware.propertycontainer.wrapper.NodeWrapper;
import com.graphaware.relcount.common.internal.node.RelationshipCountCachingNode;
import org.apache.log4j.Logger;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;

/**
 * Base-class for {@link RelationshipCountCache} implementations that cache relationship counts as properties on {@link Node}s.
 *
 * @param  type of relationship representation that can be used as a cached relationship description.
 *                 Must be {@link Comparable}; the resulting order is essential for determining, which representation
 *                 corresponds to an about-to-be-cached relationship count.
 */
public abstract class BaseRelationshipCountCache extends BaseFrameworkConfigured {
    private static final Logger LOG = Logger.getLogger(BaseRelationshipCountCache.class);

    protected final String id;

    /**
     * Construct a new cache.
     *
     * @param id of the module this cache is for.
     */
    protected BaseRelationshipCountCache(String id) {
        this.id = id;
    }

    /**
     * @see {@link RelationshipCountCache#handleCreatedRelationship(org.neo4j.graphdb.Relationship, org.neo4j.graphdb.Node, org.neo4j.graphdb.Direction)}
     */
    public final void handleCreatedRelationship(Relationship relationship, Node pointOfView, Direction defaultDirection) {
        throwExceptionIfDirectionIsNullOrBoth(defaultDirection);

        CACHED createdRelationship = newCachedRelationship(relationship, pointOfView, defaultDirection);
        int relationshipWeight = relationshipWeight(relationship, pointOfView);

        RelationshipCountCachingNode cachingNode = newCachingNode(unwrap(pointOfView));
        cachingNode.incrementCount(createdRelationship, relationshipWeight);
    }


    /**
     * @see {@link RelationshipCountCache#handleDeletedRelationship(org.neo4j.graphdb.Relationship, org.neo4j.graphdb.Node, org.neo4j.graphdb.Direction)}
     */
    public final void handleDeletedRelationship(Relationship relationship, Node pointOfView, Direction defaultDirection) {
        throwExceptionIfDirectionIsNullOrBoth(defaultDirection);

        CACHED deletedRelationship = newCachedRelationship(relationship, pointOfView, defaultDirection);
        int relationshipWeight = relationshipWeight(relationship, pointOfView);

        RelationshipCountCachingNode cachingNode = newCachingNode(unwrap(pointOfView));
        cachingNode.decrementCount(deletedRelationship, relationshipWeight);
    }

    /**
     * Create a cached relationship representation from a Neo4j relationship.
     *
     * @param relationship     to create a cached representation from.
     * @param pointOfView      node whose point of view the relationship is being looked at.
     * @param defaultDirection in case the relationship direction would be resolved to {@link org.neo4j.graphdb.Direction#BOTH}, what
     *                         should it actually be resolved to? This is guaranteed to be {@link org.neo4j.graphdb.Direction#OUTGOING} or {@link org.neo4j.graphdb.Direction#INCOMING},
     *                         never {@link org.neo4j.graphdb.Direction#BOTH}.
     * @return representation of the cached relationship.
     */
    protected abstract CACHED newCachedRelationship(Relationship relationship, Node pointOfView, Direction defaultDirection);

    /**
     * Get the weight of a relationship, i.e. how much it counts for?
     *
     * @param relationship to get weight for.
     * @param pointOfView  node whose point of view the relationship is being looked at.
     * @return relationship weight, 1 by default, can be overridden by subclasses. Should be positive.
     */
    protected int relationshipWeight(Relationship relationship, Node pointOfView) {
        return 1;
    }

    /**
     * Create a caching node from an unfiltered Neo4j node.
     *
     * @param node to wrap / represent.
     * @return caching node.
     */
    protected abstract RelationshipCountCachingNode newCachingNode(Node node);

    /**
     * Unwrap a potentially filtered Neo4j node.
     *
     * @param node to unwrap.
     * @return node with no filtering decorators around it.
     */
    protected Node unwrap(Node node) {
        if (node instanceof NodeWrapper) {
            return ((NodeWrapper) node).getWrapped();
        }

        LOG.warn("Unwrapping a non-wrapper node...");
        return node.getGraphDatabase().getNodeById(node.getId());
    }

    /**
     * Check that the given direction is not null or {@link Direction#BOTH} and throw an exception if it is.
     *
     * @param direction to check.
     * @throws IllegalArgumentException in case direction is null or {@link Direction#BOTH}.
     */
    private void throwExceptionIfDirectionIsNullOrBoth(Direction direction) {
        if (direction == null || direction.equals(Direction.BOTH)) {
            throw new IllegalArgumentException("Default direction must not be null or BOTH. This is a bug.");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy