Untitled

 avatar
unknown
plain_text
24 days ago
7.8 kB
9
Indexable
import java.io.IOException;

/**
 * The database implementation for this project. We have two hash tables and
 * graph.
 *
 * @author Leguejou Awunganyi
 * @author Ishita Punna
 * @version 2026-02-08
 */
public class GraphDB implements GPInterface {

    /**
     * Artist hash table.
     */
    private Hash artistTable;

    /**
     * Song hash table.
     */
    private Hash songTable;

    /**
     * Relationship graph.
     */
    private Graph graph;

    /**
     * True once the database has been initialized.
     */
    private boolean initialized;
    
    /**
     * Initial hash table size used for resetting the database on clear.
     */
    private int hashSize;

    /**
     * Create a new GraphDB object.
     */
    public GraphDB() {
        initialized = false;
    }

    /**
     * Create a brave new World.
     *
     * @param inHash Initial size for hash tables
     * @return Error messages if appropriate
     */
    public String create(int inHash) {
        if (inHash <= 0) {
            return "Initial hash table size must be positive";
        }
        if (initialized) {
            return "Database already exists";
        }
        hashSize = inHash;
        artistTable = new Hash("artist", inHash);
        songTable = new Hash("song", inHash);
        graph = new Graph(inHash);
        initialized = true;
        return null;
    }

    /**
     * Re-initialize the database.
     *
     * @return true on successful clear of database
     */
    public boolean clear() {
        if (!initialized) {
            return false;
        }
        artistTable = new Hash("artist", hashSize);
        songTable = new Hash("song", hashSize);
        graph = new Graph(hashSize);
        return true;
    }

    /**
     * Insert into the database.
     *
     * @param artistString artist string to insert
     * @param songString song string to insert
     * @return status message
     * @throws IOException not used here, but required by interface
     */
    public String insert(String artistString, String songString)
        throws IOException {

        if (!initialized) {
            return "Database not initialized";
        }
        if (isBlank(artistString) || isBlank(songString)) {
            return "Input strings cannot be null or empty";
        }

        GraphNode artistNode = artistTable.find(artistString);
        GraphNode songNode = songTable.find(songString);

        if (artistNode != null && songNode != null
            && graph.hasEdge(artistNode, songNode)) {
            return "|" + artistString + "<SEP>" + songString
                + "| duplicates a record already in the database\r\n";
        }

        StringBuilder builder = new StringBuilder();

        if (artistNode == null) {
            Graph.AddNodeResult artistAdd = graph.addNode(artistString, true);
            artistNode = artistAdd.node;

            if (artistAdd.resized) {
                builder.append("Graph size doubled to ")
                    .append(graph.capacity())
                    .append("\r\n");
            }

            Hash.InsertResult artistInsert =
                artistTable.insert(artistString, artistNode);

            if (artistInsert.resized) {
                builder.append("artist hash table size doubled\r\n");
            }

            builder.append("|")
                .append(artistString)
                .append("| is added to the Artist database\r\n");
        }

        if (songNode == null) {
            Graph.AddNodeResult songAdd = graph.addNode(songString, false);
            songNode = songAdd.node;

            if (songAdd.resized) {
                builder.append("Graph size doubled to ")
                    .append(graph.capacity())
                    .append("\r\n");
            }

            Hash.InsertResult songInsert =
                songTable.insert(songString, songNode);

            if (songInsert.resized) {
                builder.append("song hash table size doubled\r\n");
            }

            builder.append("|")
                .append(songString)
                .append("| is added to the Song database\r\n");
        }

        if (!graph.hasEdge(artistNode, songNode)) {
            graph.addEdge(artistNode, songNode);
        }

        return builder.toString();
    }

    /**
     * Remove from the database.
     *
     * @param type type to remove from
     * @param nameString record name
     * @return status message
     * @throws IOException not used here, but required by interface
     */
    public String remove(String type, String nameString)
        throws IOException {

        if (!initialized) {
            return "Database not initialized";
        }
        if (isBlank(type) || isBlank(nameString)) {
            return "Input strings cannot be null or empty";
        }

        if (equalsIgnoreCase(type, "artist")) {
            GraphNode node = artistTable.remove(nameString);
            if (node == null) {
                return "|" + nameString
                    + "| does not exist in the Artist database\r\n";
            }
            graph.removeNode(node);
            return "|" + nameString
                + "| is removed from the Artist database\r\n";
        }

        if (equalsIgnoreCase(type, "song")) {
            GraphNode node = songTable.remove(nameString);
            if (node == null) {
                return "|" + nameString
                    + "| does not exist in the Song database\r\n";
            }
            graph.removeNode(node);
            return "|" + nameString
                + "| is removed from the Song database\r\n";
        }

        return "Bad type value |" + type + "| on remove";
    }

    /**
     * Print a hash table.
     *
     * @param type what to print
     * @return formatted table contents
     * @throws IOException not used here, but required by interface
     */
    public String print(String type) throws IOException {
        if (!initialized) {
            return "Database not initialized";
        }
        if (isBlank(type)) {
            return "Input strings cannot be null or empty";
        }

        if (equalsIgnoreCase(type, "artist")) {
            return artistTable.print();
        }
        if (equalsIgnoreCase(type, "song")) {
            return songTable.print();
        }

        return "Bad print parameter";
    }

    /**
     * Print graph statistics.
     *
     * @return graph stats string
     * @throws IOException not used here, but required by interface
     */
    public String printgraph() throws IOException {
        if (!initialized) {
            return "Database not initialized";
        }

        Graph.Stats stats = graph.stats();
        return "There are " + stats.components + " connected components\r\n"
            + "The largest connected component has " + stats.largestSize
            + " elements\r\n"
            + "The diameter of the largest component is " + stats.diameter
            + "\r\n";
    }

    /**
     * Check if a string is null or empty.
     *
     * @param value string to test
     * @return true when null or empty
     */
    private boolean isBlank(String value) {
        return value == null || value.length() == 0;
    }

    /**
     * Compare two strings ignoring case.
     *
     * @param left first string
     * @param right second string
     * @return true when the strings match ignoring case
     */
    private boolean equalsIgnoreCase(String left, String right) {
        return left.equalsIgnoreCase(right);
    }
}
Editor is loading...
Leave a Comment