/**
* @author Elangovan
* @version 1.0
*
* Development Environment : Oracle9i JDeveloper
* Name of the Application : ObjectTypeInheritanceSample.java
* Creation/Modification History :
*
* Elangovan 21-Aug-2001 Created
* Venky 21-Feb-2003 Certfied on Linux platform
*
* This sample illustrates
*
* 1. Overloading Methods: Here the method getPersonDetails() is
* overloaded. When invoked on Student Object, this method returns
* the courses taken, grade etc information apart from Name, Address
* information. When invoked on Teacher Object, this method returns the
* information like courses taught, salary, department apart from Name and Address.
*
* 2. Dynamic Method Dispatch: This is nothing but run-time polymorphism.
* When an overridden method is invoked, the implementation of the methods is
* searched, beginning from the object from which it was invoked and then
* upwards in the type hierarchy (the type and all the super types of type).
* In other words, if setAddress() in invoked from a Student Object, then the
* method in Person Object is invoked, since there is no implementation of
* setAddress() in Student Object, but if the same method is called from
* a Teacher object, since an implementation is available in the Teacher
* Object, it is called (refer to ObjectTypeInheritanceSample.sql).
*
* 3. Substituting Types in a Type Hierarchy: A base object type can hold
* any of its sub-types object (i.e) Person is the base type and it can hold
* either a Student, Teacher or a Part-time Student object which are
* sub-types of Person.
*
* In this sample the user can View/Edit person details.
*
* For viewing person details, the overridden getpersondetails() method is
* called which returns a String representation of the Object attributes.
*
* For updating person details, the overridden setpersondetails() method is
* called, which sets the attributes and internally calls the setaddress() method for
* setting the address.
*
* The gui part of this sample is handled separately in ObjectTypeInheritanceFrame.java
*/
package oracle.otnsamples.oracle9ijdbc.objecttypeinheritance;
// import for JDBC classes
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.SQLException;
// SQLJ runtime
import sqlj.runtime.ref.DefaultContext;
// Oracle extensions
import oracle.jdbc.pool.OracleDataSource;
// Java Utility Classes
import java.util.Properties;
import java.util.Enumeration;
import java.util.ResourceBundle;
import java.io.IOException;
public class ObjectTypeInheritanceSample {
// Handles the gui for the sample
ObjectTypeInheritanceFrame gui;
private Connection connection = null;
private String userName = null;
/**
* Constructor. Initializes the gui.
*/
public ObjectTypeInheritanceSample() {
try {
gui = new ObjectTypeInheritanceFrame(this);
} catch(Exception ex) {
System.out.println(" Error : Couldn't Initialize gui : "+ex.toString());
}
}
/**
* Main entry point for the class. Calls the dbConnect() method to establish
* connection to database. Sets the map between the java classes and
* object types in the database. Displays the Person details in the JTable.
*/
public static void main(String args[]) {
// Create an object of the main sample class
ObjectTypeInheritanceSample sample = new ObjectTypeInheritanceSample();
// Connect to the database
sample.dbConnect();
if(sample.connection != null) {
// Populate JTable with person details
sample.displayPersonDetails();
}
}
/**
* This method reads a properties file which is passed as
* the parameter to it and load it into a java Properties
* object and returns it.
*/
public static Properties loadParams( String file ) throws IOException {
// Loads a ResourceBundle and creates Properties from it
Properties prop = new Properties();
ResourceBundle bundle = ResourceBundle.getBundle( file );
Enumeration enum = bundle.getKeys();
String key = null;
while( enum.hasMoreElements() ) {
key = (String)enum.nextElement();
prop.put( key, bundle.getObject( key ) );
}
return prop;
}
/**
* Creates a database connection object using DataSource object. Please
* substitute the database connection parameters with appropriate values in
* Connection.properties file
*/
public void dbConnect() {
try {
gui.putStatus("Trying to connect to the Database");
// Load the properties file to get the connection information
Properties prop = ObjectTypeInheritanceSample.loadParams("Connection");
// Create a OracleDataSource instance
OracleDataSource ods = new OracleDataSource();
// Sets the driver type
ods.setDriverType("thin");
// Sets the database server name
ods.setServerName((String)prop.get("HostName"));
// Sets the database name
ods.setDatabaseName((String)prop.get("SID"));
// Sets the port number
ods.setPortNumber(new Integer((String)prop.get("Port")).intValue());
// Sets the user name
ods.setUser((String)prop.get("UserName"));
// Sets the password
ods.setPassword((String)prop.get("Password"));
if(ods!=null) {
// Retrieve a connection from the Datasource
connection = ods.getConnection();
userName = (String)prop.get("UserName");
userName = userName.toUpperCase();
// Set the type map between the sql objects and their corresponding
// java classes.
setTypeMap(connection);
}
gui.putStatus(" Connected to " + prop.get("SID") +
" Database as " + prop.get("UserName"));
} catch(SQLException ex) { // Handle SQL errors
gui.putStatus(
"Error in Connecting to the Database "+'\n'+ex.toString());
} catch(IOException ex) { // Handle IO errors
gui.putStatus(
"Error in reading the properties file "+'\n'+ex.toString());
}
}
/**
* This method sets up a type map in the connection between the java classes and
* the Object types in the database. Whenever an object is accessed from the
* database, the entries in the type map is searched and the corresponding
* java class is used to hold the object.
*/
private void setTypeMap(Connection conn) {
try {
// Get the existing Type map
java.util.Map map = conn.getTypeMap();
// SQL Type names are in the format DatabaseSchema.TypeName and must be
// all uppercase.
// populate the type map
map.put (userName+".PERSON_TYPE",
Class.forName("oracle.otnsamples.oracle9ijdbc.objecttypeinheritance.Person"));
map.put (userName+".STUDENT_TYPE",
Class.forName("oracle.otnsamples.oracle9ijdbc.objecttypeinheritance.Student"));
map.put (userName+".TEACHER_TYPE",
Class.forName("oracle.otnsamples.oracle9ijdbc.objecttypeinheritance.Teacher"));
map.put (userName+".PARTTIME_STUDENT_TYPE",
Class.forName("oracle.otnsamples.oracle9ijdbc.objecttypeinheritance.ParttimeStudent"));
} catch(Exception ex){ // Trap errors
gui.putStatus("Error while Mapping : "+ex.toString());
}
}
/**
* This method retrieves the objects from the PersonDetails table and displays
* Id, Name and Object type of objects in a JTable.
*/
private void displayPersonDetails() {
String Id=null;
String fullName=null;
String objType=null;
Statement stmt = null;
ResultSet rset = null;
Person personObj;
try {
// Create a statement object
stmt = connection.createStatement();
// Retrieve the objects from PersonDetails table
rset = stmt.executeQuery("SELECT p.person FROM PersonDetails p");
while(rset.next()) {
// Retrieve the object and assign it to a Person object, a Person object
// can hold all its sub-type objects (substitutability)
personObj = (Person)rset.getObject(1);
// Since Part-time Student is a sub-type of Student, an object of Part-time
// Student will also be an instance of Student. Hence the retrieved
// object is first compared with a PartimeStudent and then with a
// Student(a Student object will not be an instance of Part-time Student)
// If the retrieved object is a Part-timeStudent
if(personObj instanceof ParttimeStudent)
objType=" P ";
// If the retrieved object is a student
else if(personObj instanceof Student)
objType=" S ";
// If the retrieved object is a teacher
else if(personObj instanceof Teacher)
objType=" T ";
// Some other sub-type of person
else
objType=" O ";
// Get the Id
Id = personObj.getId();
// Get the full name
fullName = personObj.getFirstname() + " " + personObj.getLastname();
// Add a row in the person table
gui.addToJTable(Id,fullName,objType);
gui.putStatus(" Select a person ...");
}
} catch(Exception ex) { // Trap errors
gui.putStatus("Error while Displaying person details : "+ex.toString());
} finally {
try{
// Close the recordset and statement objects
if(rset != null) rset.close();
if(stmt != null) stmt.close();
} catch(SQLException sqlEx) {
gui.putStatus(" Error : "+sqlEx.toString());
}
gui.repaint();
}
}
/**
* Dispatches the gui events to the appropriate method, which performs
* the required JDBC operations.
*/
public void dispatchEvent (String eventName) {
if (eventName.equals("SHOW PERSON DETAILS"))
// Display the selected person details
showPersonDetails();
else if (eventName.equals("SET PERSON DETAILS"))
// Update the person details to the table
setPersonDetails();
else if (eventName.equals("EXIT"))
// Perform clean up and close the application
exitApplication();
}
/**
* This method retrieves the person details and displays it.
*/
private void showPersonDetails() {
// Get the selected Id in the JTable
String Id = gui.getSelectedId();
// Retrieve the Person object corresponding to the selected id.
Person personObj = getPersonDetails(Id);
if(personObj != null) {
try {
// Set a connection context for object, the object uses this
// connection context to call its member functions
personObj.setConnectionContext(new DefaultContext(connection));
// Call the getpersondetails() member function of the corresponding
// object, it returns all the attributes of the object type. Display
// the attributes.
// If the retrieved object is a ParttimeStudent
if(personObj instanceof ParttimeStudent) {
ParttimeStudent pstudent = (ParttimeStudent)personObj;
gui.showPersonDetails(pstudent.getpersondetails(),'P');
// If the retrieved object is a Student
} else if(personObj instanceof Student) {
Student student = (Student)personObj;
gui.showPersonDetails(student.getpersondetails(),'S');
// If the retrieved object is a Teacher
} else if(personObj instanceof Teacher) {
Teacher teacher = (Teacher)personObj;
gui.showPersonDetails(teacher.getpersondetails(),'T');
}
} catch(Exception ex) { // Trap errors
gui.putStatus("Error while retrieving person details : "+ex.toString());
}
}
}
/**
* Update the person details to the PersonDetails table.
*/
private void setPersonDetails() {
// Prepare a person object with the updated data.
Person personObj = preparePerson(getPersonDetails(gui.getId()));
PreparedStatement pstmt = null;
try {
// Create a prepared statement object
pstmt = connection.prepareStatement(" UPDATE PersonDetails p"+
" SET p.person = ? "+
" WHERE p.person.Id= ? ");
// Set the object to be updated
pstmt.setObject(1,personObj);
// Set the Id of the person, whose details has to be updated
pstmt.setString(2,personObj.getId());
// Update the person object in the database
int updated = pstmt.executeUpdate();
gui.putStatus(updated + " Person Details Updated ");
} catch(Exception ex) { // Trap errors
gui.putStatus("Error while updating person details : "+ex.toString());
} finally {
try {
if(pstmt != null) pstmt.close();
} catch (SQLException sqlEx) {
gui.putStatus(" Error : "+sqlEx.toString());
}
}
}
/**
* Prepare a person object with the updated values.
*/
private Person preparePerson(Person person) {
// The person object that was edited
Person personObj = person;
try {
// Set a connection context for object, the object uses this
// connection context to call its member functions
personObj.setConnectionContext(new DefaultContext(connection));
// if the person is a Part-timeStudent
if(personObj instanceof ParttimeStudent) {
// Get the Part-time student object
ParttimeStudent ps = (ParttimeStudent)personObj;
// Get the edited values
String Grade = gui.getGrade();
String Yearofcompletion = gui.getYearofCompletion();
String Coursestaken = gui.getCoursesTaken();
float Hours = gui.getHours();
String Batchcode = gui.getBatchCode();
String Starttime = gui.getStartTime();
// Call the overridden setpersondetails() member procedure to set the
// updated values to the object
personObj = ps.setpersondetails(Grade,
Yearofcompletion,
Coursestaken,
Hours,
Batchcode,
Starttime);
} else if(personObj instanceof Student) {
// Get the student object
Student s = (Student)personObj;
// Get the edited values
String Grade = gui.getGrade();
String Yearofcompletion = gui.getYearofCompletion();
String Coursestaken = gui.getCoursesTaken();
// Call the overridden setpersondetails() member procedure to set the
// updated values to the object
personObj = s.setpersondetails(Grade,
Yearofcompletion,
Coursestaken);
} else if(personObj instanceof Teacher) {
// Get the student object
Teacher t = (Teacher)personObj;
// Get the edited values
float Experience = gui.getExperience();
float Salary = gui.getSalary();
String Courseshandled = gui.getCoursesHandled();
// Call the overridden setpersondetails() member procedure to set the
// updated values to the object
personObj = t.setpersondetails(Experience,
Salary,
Courseshandled);
}
} catch(Exception ex) {
gui.putStatus(" Couldn't construct a Person Object : "+ex.toString());
}
// return the updated person object
return(personObj);
}
/**
* This method gets the Id of the person who has been selected in the JTable
* and retrieves the corresponding person object from the PersonDetails table.
*/
public Person getPersonDetails(String id) {
Person personObj = null;
PreparedStatement pstmt = null;
ResultSet rset = null;
try {
pstmt = connection.prepareStatement(" SELECT p.person "+
" FROM PersonDetails p "+
" WHERE p.person.Id=? ");
// The Id of the person to be retrieved
pstmt.setString(1,id);
// select the person object from PersonDetails table
rset = pstmt.executeQuery ();
// Move the resultset pointer
rset.next();
// Retrieve the object and assign it to a person object, a person object
// can hold all its sub-type objects (substitutability)
personObj = (Person)rset.getObject(1);
} catch(SQLException sqlEx) { // Trap errors
gui.putStatus("Error at Selecting person : "+sqlEx.toString());
} finally {
// Close the recordset and the statement object
try {
if(rset != null) rset.close();
if(pstmt != null) pstmt.close();
} catch(SQLException e) {
gui.putStatus(" Error : "+e.toString());
}
}
// Return the person object
return(personObj);
}
/**
* This method performs the clean up action and closes the application
*/
private void exitApplication(){
// if connected to database
if (connection != null) {
try {
// close the connection
connection.close();
}
catch (SQLException sqlEx){ // Trap errors
gui.putStatus(" Error while Closing the connection: "+sqlEx.toString());
}
}
// Close the application
System.exit(0);
}
}