/******************************************************************************/ /* File: main.beh */ /* */ /* Describes the driver class "XMLandDB" which accepts a request to query a */ /* database or insert data into a database, and then invokes the services of */ /* appropriate classes to process the request. */ /* */ /* To start the application from the command prompt, use: */ /* java XMLandDB [debug] < InputFile */ /* where InputFile is a text file containing the request specification. */ /* Specifying the debug option will produce additional output such as the */ /* input arguments, the SQL statement generated, etc. */ /* */ /* To invoke the service from another java class, call the static method */ /* XMLandDB.process(input) */ /* where input can be a String or an InputStream containing the request */ /* specification. */ /* */ /******************************************************************************/ XMLandDB { {{ // Define the two possible request types public final static String INSERT = "INSERT"; public final static String QUERY = "QUERY"; // Private instance variable to indicate the "debug" mode. // In this mode, the application produces additional informaive output. // Use the method debugPrint (instead of System.out.println) to print // something only in the debug mode. private static boolean debugMode = false; public static void main(String args[]) throws Exception { if ((args.length > 0) && (args[0].equalsIgnoreCase("debug"))) debugMode = true; process(System.in); } public static void process(java.io.InputStream input) throws Exception { processRequest(Request.parse(input)); } public static void process(String input) throws Exception { processRequest(Request.parse(input)); } private static void processRequest(Request request) throws Exception { // Break the complete request structure into the individual components: // the connection arguments, // the target data - table(s) and corresponding column(s) // the structure of the hierarchy (if requested) // the generated SQL statement (as needed by the specified vendor) ClassGraph cg = new ClassGraph(true, false); ConnectionArgs connArgs = request.getConnectionArgs(cg); debugPrint("Database connection arguments -\n" + "\tVendor: " + connArgs.vendor + "\n" + "\tDriver: " + connArgs.driver + "\n" + "\tURL: " + connArgs.url + "\n" + "\tUserid: " + connArgs.userid + "\n" + "\tPassword: " + connArgs.password); debugPrint(""); String requestType = request.getRequestType(cg); debugPrint("Request Type: " + requestType); debugPrint(""); EntityStructure entityStruct[] = request.getEntityStructure(cg); debugPrint("Target data -"); for (int i = 0; i < entityStruct.length; i++) { debugPrint(" Table " + entityStruct[i].tableName); for (int j = 0; j < entityStruct[i].columns.length; j++) debugPrint("\tColumn " + (j+1) + ": " + entityStruct[i].columns[j].name + " (Type " + entityStruct[i].columns[j].type + ")"); } debugPrint(""); HierarchyArgs hierArgs = request.getHierarchyArgs(cg); if (hierArgs != null) { debugPrint("Hierarchy structure -"); debugPrint("\tParent column: " + hierArgs.parentTable + "." + hierArgs.parentColumn + "\n" + "\tChild column: " + hierArgs.childTable + "." + hierArgs.childColumn + "\n" + "\tConnecting column: " + hierArgs.relationColumn); debugPrint(""); } String SQLStmt = request.getSQLStmt(cg); if (SQLStmt == null) throw new Exception("Formats not set up correctly for vendor '" + connArgs.vendor + "'"); debugPrint("Generated SQL Statement:\n" + SQLStmt); debugPrint(""); // Use the datamanager to retrieve the data (for a query request) from // the database or insert data (for an insert request) into the database DataManager dm = new DataManager(connArgs); if (requestType.equals(QUERY)) { Vector data = dm.getData(SQLStmt); // Stringify the data retrieved from the database in a form accepted // by the parser for the resultset, and parse it in to create the // resultset object structure. // In case of a join between two tables (when a row in the data // retrieved contains columns involving both tables), each row gives // rise to two objects (one for each of the two entities involved). // The first table specified in the request is always assumed to be // the "one" side in the one-to-many relationship, and so this // entity's data may be repeated over multiple rows. Such duplicates // are detected here and only a distinct object representation is // created. // Currently the code supports only one-to-many relationships // involving one or two tables. String prevParentColumnValues = ""; String resultString = ""; for (int rowNo = 0; rowNo < data.size(); rowNo++) { Vector row = (Vector) data.elementAt(rowNo); String entityColumnValues = ""; int tableNo = -1, columnNoInTable = -1; for (int columnIndex = 0; columnIndex < row.size(); columnIndex++) { if ((columnIndex == 0) || (columnNoInTable >= (entityStruct[tableNo].columns.length - 1))) { if ((hierArgs != null) && (tableNo >= 0) && entityStruct[tableNo].tableName.equals( hierArgs.parentTable)) { if (entityColumnValues.equals(prevParentColumnValues)) entityColumnValues = ""; else prevParentColumnValues = entityColumnValues; } if (! entityColumnValues.equals("")) { resultString = resultString + " " + entityStruct[tableNo].tableName + " " + entityColumnValues; } tableNo ++; entityColumnValues = ""; columnNoInTable = -1; } columnNoInTable ++; Object columnValue = row.elementAt(columnIndex); if (columnValue != null) { entityColumnValues = entityColumnValues + " " + entityStruct[tableNo].columns[columnNoInTable].name + " \"" + columnValue.toString() + "\""; } } if ((hierArgs != null) && entityStruct[tableNo].tableName.equals(hierArgs.parentTable)) { if (entityColumnValues.equals(prevParentColumnValues)) entityColumnValues = ""; else prevParentColumnValues = entityColumnValues; } if (! entityColumnValues.equals("")) resultString = resultString + " " + entityStruct[tableNo].tableName + " " + entityColumnValues; } Resultset results = Resultset.parse(resultString); // Transform the structure into a hierarchy of objects, if requested if (hierArgs != null) results.createHierarchy(cg, hierArgs); // Print out the final structure of the resultset using the visitor // defined to print it in an XML format results.print(); debugPrint(""); } else if (requestType.equals(INSERT)) { dm.putData(SQLStmt); } debugPrint("\nStatus: Operation Successful\n"); } // Use this method to print messages selectively only in the "debug" mode public static void debugPrint(String message) { if (debugMode) System.out.println(message); } }} }