// The following Specification is courtesy of Prof. I. Budak Arpinar // of CS department at UGa. import java.io.*; import java.util.*; // This class support the creation of database relations, several // relational algebra operators and basic data manipulation operators. public class Relation { // C O N S T A N T F I E L D S // Shorthand for standard output stream. private static final PrintStream OP = System.out; // F I E L D S // Name of the relation. private String relName=null; // Attribute names for the relation private String [] attributes=null; // Domain classes (types of attributes) private Class [] domains=null; // Whether relation has been modified since last commit. private boolean modified =false; // Attribute making up the primary key (unique identifier). private String primaryKey=null; // Actual data storage (list of tuples) for the relation. private List table=null; // Counter to facilitate creating uniques names. private int counter=0; // List of relation names in the database. private static List catalog=null; // Map associating relation names with relation memory images. private static Map catalogMap=null; // Static block to load the system catalog and all relations listed // in the catalog. static { String rName; FileInputStream inFile; ObjectInputStream inStream; catalogMap = new HashMap (); try { inFile = new FileInputStream ("catalog.dat"); inStream = new ObjectInputStream (inFile); catalog = (LinkedList) inStream.readObject (); inStream.close (); // Fill in code to read in the Relations into the catalogMap // Examples of names in the cataloog: employee, department, etc... // Examples of names of Relations in disk: employee.dat, // department.dat, etc... } catch (Exception ex) { OP.println ("static block: no catalog found" + " - Creating it." ); catalog = new LinkedList (); }; // try OP.println ("static block: catalog = " + catalog); OP.println ("static block: catalogMap = " + catalogMap); }; // static block // C O N S T R U C T O R S /******************************************************************* * Construct a relation with given domain classes. * @param relName name of the relation * @param attributes attribute names for the relation * @param domains domain classes (types of attributes) * @param primaryKey attribute making up the primary key */ public Relation (String relName, String [] attributes, Class [] domains, String primaryKey) { counter = 0; this.relName = relName; this.attributes = attributes; this.domains = domains; this.modified = false; this.primaryKey = primaryKey; table = new LinkedList (); }; // Relation /******************************************************************* * Construct a relation with given domain names. * @param relName name of the relation * @param attributes attribute names for the relation * @param dNames domain names (type names of attributes) * @param primaryKey attribute making up the primary key */ public Relation (String relName, String [] attributes, String [] dNames, String primaryKey) { domains = new Class [dNames.length]; for (int j = 0; j < dNames.length; j++) { try { domains [j] = Class.forName ("java.lang." + dNames [j]); } catch (ClassNotFoundException ex) { OP.println ("Error in Relation: " + ex); }; // try }; // for counter = 0; this.relName = relName; this.attributes = attributes; this.modified = false; this.primaryKey = primaryKey; table = new LinkedList (); }; // Relation // M E T H O D S /******************************************************************* * Method gets access to the memory image of the relation named 'relName'. * @param relName name of the relation * @return Relation reference to relation in memory, null if not there */ public static Relation getRelation (String relName) { return null; }; // getRelation /******************************************************************* * Method saves all relations that have been modified since the last save. * Also saves the catalog list to disk. */ public static void save () { OP.println ("save: save all modified relations, update catalog."); }; // save /******************************************************************* * Project this relation onto the column attributes. * If key is not in projection, use all attributes as key. * @param columns attributes to project onto * @return Relation resultant projected relation */ public Relation project (String [] columns) { OP.println ("\nperform project operation"); Class [] colDomains = new Class [columns.length]; for (int j = 0; j < columns.length; j++) { boolean match = false; for (int k = 0; k < attributes.length; k++) { if (columns [j].equals (attributes [k])) { match = true; colDomains [j] = domains [k]; }; // for }; // for if ( ! match) { OP.println ("Error in project: domain not found for " + columns [j]); }; // if }; // for return new Relation (relName + "_P" + counter++, columns, colDomains, null); }; // project /******************************************************************* * Project this relation onto the column attributes. * @param columnStr attribute string to project onto * @return Relation resultant projected relation */ public Relation project (String columnStr) { StringTokenizer st = new StringTokenizer (columnStr); int nt = st.countTokens (); String [] columns = new String [nt]; for (int i = 0; i < nt; i++) { columns [i] = st.nextToken (); }; // while return project (columns); }; // project /******************************************************************* * Select tuples from this relation that satisfy the predicate. * @param predicate Boolean expression for selecting tuples * @return Relation resultant selected relation */ public Relation select (String predicate) { OP.println ("\nperform select operation"); String token; String op; Stack stack = new Stack (); StringTokenizer st = new StringTokenizer (predicate); while (st.hasMoreTokens ()) { token = st.nextToken (); OP.println (token); }; // while return null; }; // select /******************************************************************* * Join this relation with the other relation based on the predicate. * @param predicate Boolean expression for joining tuples * @param other second operand/relation * @return Relation resultant joined relation */ public Relation join (String predicate, Relation other) { return null; }; // join /******************************************************************* * Join this relation with the other relation based on the predicate. * @param predicate Boolean expression for joining tuples * @param other second operand/relation * @param alias alias/abbreviation for the second operand/relation * @return Relation resultant joined relation */ public Relation join (String predicate, Relation other, String alias) { return null; }; // join /******************************************************************* * Union this relation with the other relation (eliminate duplicates) * @param other second operand/relation * @return Relation resultant unioned relation */ public Relation union (Relation other) { return null; }; // union /******************************************************************* * Subtract the other relation from this relation. * @param other second operand/relation * @return Relation resultant subtracted relation */ public Relation minus (Relation other) { return null; }; // minus /******************************************************************* * Insert the tuple consisting of the attribute values into relation. * @param atrValues attribute values to be inserted * @return boolean whether the insertion succeeded */ public boolean insert (Comparable [] atrValues) { this.modified = true; return (typeCheck (atrValues)) ? table.add (atrValues) : false; }; // insert /******************************************************************* * Delete all tuples matching the predicate. * @param predicate Boolean expression for choosing tuples to delete * @return int number of tuples deleted */ public int delete (String predicate) { return 0; }; // delete /******************************************************************* * Print the relation (attributes names on the first line, followed * by the tuples, one per line). */ public void print () { Comparable [] row; for (int j = 0; j < attributes.length; j++) { OP.print (" | " + attributes [j]); }; // for OP.println (" |"); for (Iterator it = table.iterator (); it.hasNext (); ) { row = (Comparable []) it.next (); for (int j = 0; j < row.length; j++) { OP.print (" | " + row [j]); }; // for OP.println (" |"); }; // for }; // print /******************************************************************* * Check that the types of inserted objects agree with the relation's * domains. * @param atrValues attribute values to be inserted * @return boolean whether the types match */ private boolean typeCheck (Comparable [] atrValues) { Class vClass; for (int j = 0; j < atrValues.length; j++) { vClass = atrValues [j].getClass (); if (vClass != domains [j]) { OP.println ("Error in typeCheck: mismatch " + vClass + " != " + domains [j]); return false; }; // if }; // for return true; }; // typeCheck /******************************************************************* * Main method for testing purposes. * @param args command-line arguments */ public static void main (String [] args) { Relation employee = new Relation ( "employee", new String [] { "ssn", "fname", "minit", "lname", "bdate", "address", "gender", "salary", "superssn", "dno" }, new String [] { "Integer", "String", "String", "String", "String", "String", "String", "Double", "Integer", "Integer" }, new String ( "ssn" ) ); employee.insert (new Comparable [] { new Integer (123456789), "John", "B", "Smith", "1965-01-09", "731 Fondren, Houston, TX", "M", new Double (30000), new Integer (333445555), new Integer (5) }); OP.println ("\nemployee = "); employee.print (); Relation department = new Relation ( "department", new String [] { "dnumber", "dname", "mgrssn", "mstartdate" }, new String [] { "Integer", "String", "Integer", "String" }, new String ( "dnumber" ) ); department.insert (new Comparable [] { new Integer (5), "Research", new Integer (333445555), "1988-05-22" }); OP.println ("\ndepartment = "); department.print (); Relation r3; r3 = employee.project ("fname minit lname"); OP.println ("\nr3 = "); r3.print (); }; // main }; // Relation