Package org.openbel.framework.api.internal

Source Code of org.openbel.framework.api.internal.KAMUpdateDaoImpl

package org.openbel.framework.api.internal;

import static org.openbel.framework.api.EdgeDirectionType.FORWARD;
import static org.openbel.framework.api.EdgeDirectionType.REVERSE;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.openbel.framework.api.Kam;
import org.openbel.framework.api.Kam.KamEdge;
import org.openbel.framework.api.Kam.KamNode;
import org.openbel.framework.common.InvalidArgument;
import org.openbel.framework.common.enums.RelationshipType;
import org.openbel.framework.core.df.AbstractJdbcDAO;
import org.openbel.framework.core.df.DBConnection;

/**
* KAMUpdateDaoImpl implements {@link Kam} update operations.
*/
public class KAMUpdateDaoImpl extends AbstractJdbcDAO implements KAMUpdateDao {

    private static final int MAX_BATCH_COUNT = 500;
    private static final String UPDATE_KAM_EDGES_SOURCE = "update @.kam_edge " +
        "set kam_source_node_id = ? where kam_edge_id = ?";
    private static final String UPDATE_KAM_EDGES_TARGET = "update @.kam_edge " +
            "set kam_target_node_id = ? where kam_edge_id = ?";
    private static final String UPDATE_TERM = "update @.term set kam_node_id = ? " +
        "where kam_node_id = ?";
    private static final String SELECTED_ORDERED_EDGES =
            "select kam_edge_id, kam_source_node_id, relationship_type_id, " +
            "kam_target_node_id from @.kam_edge order by kam_source_node_id, " +
            "relationship_type_id, kam_target_node_id";
    private static final String SELECT_KAM_EDGE_BY_RELATIONSHIP =
            "select kam_edge_id from @.kam_edge " +
            "where relationship_type_id = ?";
    private static final String UPDATE_KAM_EDGE_STATEMENT =
            "update @.kam_edge_statement_map set kam_edge_id = ? " +
            "where kam_edge_id = ?";
    private static final String DELETE_KAM_NODE_PARAMETER =
            "delete from @.kam_node_parameter where kam_node_id = ?";
    private static final String DELETE_KAM_NODE =
            "delete from @.kam_node where kam_node_id = ?";
    private static final String DELETE_EDGE_STATEMENT =
            "delete from @.kam_edge_statement_map where kam_edge_id = ?";
    private static final String DELETE_KAM_EDGES =
            "delete from @.kam_edge where kam_edge_id = ?";
//    private static final String DELETE_ORTHOLOGOUS_STATEMENTS =
//            "delete from @.statement where relationship_type_id = ?";

    /**
     * Constructs the dao.
     *
     * @param c {@link DBConnection}; may not be {@code null}
     * @param schema {@link String}; may not be {@code null}
     * @throws SQLException when an error occurs checking if {@code c} is open
     * @throws InvalidArgument when {@code c} is {@code null}, {@code c} is
     * closed, or {@code schema} is {@code null}
     */
    public KAMUpdateDaoImpl(DBConnection c, String schema)
            throws SQLException {
        super(c, schema);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean collapseKamNode(KamNode collapsing, KamNode collapseTo)
            throws SQLException {
        if (collapsing == null)
            throw new InvalidArgument("collapsing node is null");
        if (collapseTo == null)
            throw new InvalidArgument("collapseTo node is null");
        if (collapsing.getKam() == null || collapseTo.getKam() == null
                || collapsing.getKam() != collapseTo.getKam())
            throw new InvalidArgument("nodes reference invalid kams");
        if (collapsing.getId() == null || collapseTo.getId() == null)
            throw new InvalidArgument("node id is null");

        Kam kam = collapsing.getKam();

        PreparedStatement esps = getPreparedStatement(UPDATE_KAM_EDGES_SOURCE);
        PreparedStatement etps = getPreparedStatement(UPDATE_KAM_EDGES_TARGET);
        remapEdges(collapsing, collapseTo, kam, esps, etps);

        PreparedStatement utps = getPreparedStatement(UPDATE_TERM);
        remapTerms(collapsing, collapseTo, utps);

        PreparedStatement knps = getPreparedStatement(DELETE_KAM_NODE);
        PreparedStatement knpps = getPreparedStatement(DELETE_KAM_NODE_PARAMETER);
        removeKamNode(collapsing, knps, knpps);

        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int removeKamEdges(int[] edgeIds) throws SQLException {
        if (edgeIds == null)
            throw new InvalidArgument("edgeIds is null");
        if (edgeIds.length == 0)
            return 0;

        int batch = 0;
        int deletes = 0;
        PreparedStatement kesps = getPreparedStatement(DELETE_EDGE_STATEMENT);
        PreparedStatement keps = getPreparedStatement(DELETE_KAM_EDGES);

        // add delete command; submit batches per MAX_BATCH_COUNT
        for (int e : edgeIds) {
            kesps.setInt(1, e);
            kesps.addBatch();
            keps.setInt(1, e);
            keps.addBatch();
            batch++;

            if (batch == MAX_BATCH_COUNT) {
                // remove from kam_edge_statement_map
                kesps.executeBatch();

                // remove from kam_edge
                int[] rowsAffected = keps.executeBatch();
                for (int d : rowsAffected) deletes += d;
            }
        }

        // submit batch for anything left over
        if (batch > 0) {
            // remove from kam_edge_statement_map
            kesps.executeBatch();

            // remove from kam_edge
            int[] rowsAffected = keps.executeBatch();
            for (int d : rowsAffected) deletes += d;
        }
        return deletes;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int removeKamEdges(RelationshipType relationship)
            throws SQLException {
        if (relationship == null || relationship.getValue() == null)
            throw new InvalidArgument("relationship is null");

        PreparedStatement ps = getPreparedStatement(SELECT_KAM_EDGE_BY_RELATIONSHIP);
        ResultSet rset = null;

        try {
            // set relationships to remove
            int rvalue = relationship.getValue();
            ps.setInt(1, rvalue);

            // cursor all edge ids
            List<Integer> ids = new ArrayList<Integer>();
            rset = ps.executeQuery();
            while (rset.next()) {
                int edgeId = rset.getInt(1);
                ids.add(edgeId);
            }

            // convert to int[]
            int sz = ids.size();
            int[] edgeIds = new int[sz];
            for (int i = 0; i < sz; i++) edgeIds[i] = ids.get(i);

            // remove edges for edge id int[]
            return removeKamEdges(edgeIds);
        } finally {
            if (rset != null) {
                try {
                    rset.close();
                } catch (Exception e) {
                    // ignored
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int coalesceKamEdges() throws SQLException {
        PreparedStatement eps = getPreparedStatement(SELECTED_ORDERED_EDGES);
        PreparedStatement kesps = getPreparedStatement(UPDATE_KAM_EDGE_STATEMENT);
        ResultSet rset = null;
        int coalesced = 0;
        try {
            rset = eps.executeQuery();
            if (rset.next()) {
                int xSource = rset.getInt(2);
                int xRel = rset.getInt(3);
                int xTarget = rset.getInt(4);

                int xEdgeId = rset.getInt(1);
                int[] xTriple = new int[] {xSource, xRel, xTarget};
                while (rset.next()) {
                    int edgeId = rset.getInt(1);
                    int source = rset.getInt(2);
                    int rel = rset.getInt(3);
                    int target = rset.getInt(4);
                    int[] triple = new int[] {source, rel, target};

                    if (Arrays.equals(triple, xTriple)) {
                        // duplicate triple, move over statements
                        kesps.setInt(1, xEdgeId);
                        kesps.setInt(2, edgeId);
                        kesps.executeUpdate();

                        // remove duplicate
                        removeKamEdges(new int[] {edgeId});

                        coalesced++;
                    } else {
                        // move to next unseen triple
                        xTriple = triple;
                        xEdgeId = edgeId;
                    }
                }
            }
        } finally {
            if (rset != null) {
                try {
                    rset.close();
                } catch (Exception e) {
                    // ignored
                }
            }
        }
        return coalesced;
    }

    /**
     * Remaps outgoing and incoming edges to {@code collapseTo}.
     *
     * @param collapsing {@link KamNode} being collapsed
     * @param collapseTo {@link KamNode} collapsing to
     * @param kam {@link Kam} to retrieve adjacent edges
     * @param esps {@link PreparedStatement} for updating edge source
     * @param etps {@link PreparedStatement} for updating edge target
     * @return {@code int} update count
     * @throws SQLException when a SQL error occurred with update
     */
    private static int remapEdges(KamNode collapsing, KamNode collapseTo,
            Kam kam, PreparedStatement esps, PreparedStatement etps)
            throws SQLException {
        int updates = 0;
        Set<KamEdge> outgoing = kam.getAdjacentEdges(collapsing, FORWARD);
        int collapseToId = collapseTo.getId();
        for (KamEdge edge : outgoing) {
            esps.setInt(1, collapseToId);
            esps.setInt(2, edge.getId());
            updates += esps.executeUpdate();
        }
        Set<KamEdge> incoming = kam.getAdjacentEdges(collapsing, REVERSE);
        for (KamEdge edge : incoming) {
            etps.setInt(1, collapseToId);
            etps.setInt(2, edge.getId());
            updates += etps.executeUpdate();
        }
        return updates;
    }

    /**
     * Remaps terms to {@code collapseTo}.
     *
     * @param collapsing {@link KamNode} being collapsed
     * @param collapseTo {@link KamNode} collapsing to
     * @param utps {@link PreparedStatement} for updating term
     * @return {@code int} update count
     * @throws SQLException when a SQL error occurred with update
     */
    private static int remapTerms(KamNode collapsing, KamNode collapseTo,
            PreparedStatement utps) throws SQLException {
        int collapsingId = collapsing.getId();
        int collapseToId = collapseTo.getId();

        utps.setInt(1, collapseToId);
        utps.setInt(2, collapsingId);
        return utps.executeUpdate();
    }

    /**
     * Removes {@code collapsing} node.
     *
     * @param collapsing {@link KamNode} being collapsed
     * @param knps {@link PreparedStatement} for updating kam_node
     * @param knpps {@link PreparedStatement} for updating kam_node_parameter
     * @return {@code int} update count
     * @throws SQLException when a SQL error occurred with delete
     */
    private static int removeKamNode(KamNode collapsing,
            PreparedStatement knps, PreparedStatement knpps)
            throws SQLException {
        int collapsingId = collapsing.getId();

        int updates = 0;
        knpps.setInt(1, collapsingId);
        updates += knpps.executeUpdate();
        knps.setInt(1, collapsingId);
        updates += knps.executeUpdate();
        return updates;
    }
}
TOP

Related Classes of org.openbel.framework.api.internal.KAMUpdateDaoImpl

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.