dao.versions.neo4j.Neo4jVersionHistoryDagFactory.java Source code

Java tutorial

Introduction

Here is the source code for dao.versions.neo4j.Neo4jVersionHistoryDagFactory.java

Source

/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dao.versions.neo4j;

import com.google.common.base.CaseFormat;

import dao.versions.VersionHistoryDagFactory;
import db.DbDataContainer;
import db.Neo4jClient;
import exceptions.GroundException;
import models.models.Structure;
import models.versions.GroundType;
import models.versions.Item;
import models.versions.Version;
import models.versions.VersionHistoryDag;
import models.versions.VersionSuccessor;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.neo4j.driver.v1.types.Relationship;

public class Neo4jVersionHistoryDagFactory implements VersionHistoryDagFactory {
    private final Neo4jClient dbClient;
    private final Neo4jVersionSuccessorFactory versionSuccessorFactory;

    public Neo4jVersionHistoryDagFactory(Neo4jClient dbClient,
            Neo4jVersionSuccessorFactory versionSuccessorFactory) {
        this.dbClient = dbClient;
        this.versionSuccessorFactory = versionSuccessorFactory;
    }

    @Override
    public <T extends Version> VersionHistoryDag<T> create(long itemId) throws GroundException {
        return new VersionHistoryDag<T>(itemId, new ArrayList<>());
    }

    /**
     * Retrieve a DAG from the database.
     *
     * @param itemId the id of the item whose dag we are retrieving
     * @param <T> the type of the versions in this dag
     * @return the retrieved DAG
     * @throws GroundException an error retrieving the DAG
     */
    @Override
    public <T extends Version> VersionHistoryDag<T> retrieveFromDatabase(long itemId) throws GroundException {

        List<Relationship> result = this.dbClient.getDescendantEdgesByLabel(itemId, "VersionSuccessor");

        if (result.isEmpty()) {
            // do nothing' this just means that no versions have been added yet.
            return new VersionHistoryDag<T>(itemId, new ArrayList<>());
        }

        List<VersionSuccessor<T>> edges = new ArrayList<>();

        for (Relationship relationship : result) {
            edges.add(this.versionSuccessorFactory.retrieveFromDatabase(relationship.get("id").asLong()));
        }

        return new VersionHistoryDag<T>(itemId, edges);
    }

    /**
     * Add an edge to the DAG.
     *
     * @param dag the DAG to update
     * @param parentId the parent's id
     * @param childId the child's id
     * @param itemId the id of the Item whose DAG we're updating
     * @throws GroundException an error adding the edge
     */
    @Override
    public void addEdge(VersionHistoryDag dag, long parentId, long childId, long itemId) throws GroundException {

        VersionSuccessor successor = this.versionSuccessorFactory.create(parentId, childId);

        dag.addEdge(parentId, childId, successor.getId());
    }

    /**
     * Truncate the DAG to only have a certain number of levels, removing everything before that.
     *
     * @param dag the DAG to truncate
     * @param numLevels the number of levels to keep
     */
    @Override
    public void truncate(VersionHistoryDag dag, int numLevels, Class<? extends Item> itemType)
            throws GroundException {

        int keptLevels = 1;
        List<Long> lastLevel = new ArrayList<>();
        List<Long> previousLevel = dag.getLeaves();

        while (keptLevels <= numLevels) {
            List<Long> currentLevel = new ArrayList<>();

            previousLevel.forEach(id -> currentLevel.addAll(dag.getParent(id)));

            lastLevel = previousLevel;
            previousLevel = currentLevel;

            keptLevels++;
        }

        List<Long> deleteQueue = previousLevel;
        Set<Long> deleted = new HashSet<>();

        for (long id : lastLevel) {
            this.addEdge(dag, dag.getItemId(), id, dag.getItemId());
        }

        List<DbDataContainer> predicates = new ArrayList<>();

        while (deleteQueue.size() > 0) {
            long id = deleteQueue.get(0);

            String[] splits = itemType.getName().split("\\.");
            String className = splits[splits.length - 1];
            String tableNamePrefix = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, className);

            if (itemType.equals(Structure.class)) {
                predicates.add(new DbDataContainer("structure_version_id", GroundType.LONG, id));
                this.dbClient.deleteNode(predicates, "structure_version_attribute");
                predicates.clear();
            }

            if (itemType.getName().toLowerCase().contains("graph")) {
                predicates.add(new DbDataContainer(tableNamePrefix + "_version_id", GroundType.LONG, id));
                this.dbClient.deleteNode(predicates, tableNamePrefix + "_version_edge");
                predicates.clear();
            }

            predicates.add(new DbDataContainer("id", GroundType.LONG, id));

            this.dbClient.deleteNode(predicates, className + "Version");

            deleteQueue.remove(0);
            List<Long> parents = dag.getParent(id);

            predicates.clear();
            predicates.add(new DbDataContainer("rich_version_id", GroundType.LONG, id));
            this.dbClient.deleteNode(predicates, "RichVersionTag");
            deleted.add(id);

            parents.forEach(parentId -> {
                if (!deleted.contains(parentId)) {
                    deleteQueue.add(parentId);
                }
            });
        }
    }
}