This chapter provides the source code for the following Personalization application classes:
Source Code for UserManager.java
Source Code for TestDriver.java
Source Code for PersonalizationException.java
package COM.odi.tutorial; import COM.odi.*; /** * The Interest class models a particular interest that a user may * have. It contains a name and a value. For example, the name of * an interest might be "food" and the value might be "pizza". */ public class Interest { /* the name of the interest */ private String name; /* the value of the interest */ private String value; /* the user who has this interest */ private User user; /* accessor functions */ public String getName() { return name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public User getUser() { return user; } /** * Constructs a new interest object given a name and a value */ public Interest(String name, String value, User user) { this.name = name; this.value = value; this.user = user; } /* * Destroy the interest's associated objects */ public void preDestroyPersistent() { if (!ObjectStore.isDestroyed(name)) ObjectStore.destroy(name); if (!ObjectStore.isDestroyed(value)) ObjectStore.destroy(value); } }
package COM.odi.tutorial; import java.util.*; import COM.odi.*; import COM.odi.util.*; /** * The User class models users. Users have names, email addresses, * and PINS. Each user also has a set of interests. The application * uses PINs to validate a user's identity. */ public class User { /* The name of the user */ private String name; /* The user's email address */ private String email; /* The user's Personal Identification Number */ private int PIN; /* The set of user's interests */ private OSHashMap interests; /* accessors */ public String getName() { return name; } public String getEmail() { return email; } public int getPIN() { return PIN; } public Map getInterests() { return interests; } /** * Constructs a user object given the name, email and PIN */ public User(String name, String email, int PIN) { this.name = name; this.email = email; this.PIN = PIN; this.interests = new OSHashMap(5); /* initial hashtable size */ } /* * Destroy the associated objects */ public void preDestroyPersistent() { if (!ObjectStore.isDestroyed(name)) ObjectStore.destroy(name); if (!ObjectStore.isDestroyed(email)) ObjectStore.destroy(email); /* destroy each of the interests */ Iterator interestIter = interests.values().iterator(); while (interestIter.hasNext()) { Interest interest = (Interest) interestIter.next(); ObjectStore.destroy(interest); } /* destroy the interests list too */ ObjectStore.destroy(interests); } /** * Add an interest to the User's list of interests. * * @param interestName the name of the interest * @param interestValue the value of the interest * * @exception PersonalizationException If the interest is * already there (the same name as another interest) */ public Interest addInterest(String interestName, String interestValue) throws PersonalizationException { Object previous = interests.get(interestName); if (previous != null) throw new PersonalizationException("Interest already there: " + interestName); Interest interest = new Interest(interestName, interestValue, this); interests.put(interestName, interest); return interest; } /** * Update an interest in the User's list of interests. * * @param interestName the name of the interest * @param interestValue the new value of the interest * * @exception PersonalizationException is thrown if the interest is * already not there. */ public Interest changeInterest(String interestName, String interestValue) throws PersonalizationException { Interest interest = (Interest)interests.get(interestName); if (interest == null) throw new PersonalizationException("No such registered interest: " + interestName); interest.setValue(interestValue); return interest; } /** * Remove an interest from the User's list of interests. * * @param interestName The name of the Interest to remove. * * @exception PersonalizationException if the interest is not * found in the user's list of interests */ public Interest removeInterest(String interestName) throws PersonalizationException { Interest interest = (Interest)interests.remove(interestName); if (interest == null) /* did not find the interest */ throw new PersonalizationException("Interest not found: " + name); return interest; } }
package COM.odi.tutorial; import java.util.*; import java.io.*; import COM.odi.*; import COM.odi.util.*; import COM.odi.util.query.*; /** * The UserManager acts as the interface to the Personalization data * that is stored persistently. In real use, it might serve as an * application service that would receive requests (RMI or ORB * requests perhaps) and service those requests by accessing the * database. */ public class UserManager { /* The database that this UserManager is operating against. */ private static Database db; /* The active session for this UserManager */ private static Session session; /* The extent of all users in the database is held in a root. We use a map, whose key is the name of the user. */ private static Map allUsers; /* The extent of all interests in the database is held in a root. We use a Set, which might have one or more indexes. */ private static Set allInterests; /* This is used to allocate the Personal Identification Number (PIN) */ private static Random pinGenerator; public static void initialize(String dbName) { /* initialize a random number generator to allocate PINs */ pinGenerator = new Random(); /* Create a session and join this thread to the new session. */ session = Session.create(null, null); session.join(); /* Open the database or create a new one if necessary. */ try { db = Database.open(dbName, ObjectStore.UPDATE); } catch (DatabaseNotFoundException e) { db = Database.create(dbName, ObjectStore.ALL_READ | ObjectStore.ALL_WRITE); } /* Find the allUsers and allInterests roots or create them if not there. */ Transaction tr = Transaction.begin(ObjectStore.UPDATE); try { allUsers = (Map) db.getRoot("allUsers"); allInterests = (Set) db.getRoot("allInterests"); } catch (DatabaseRootNotFoundException e) { /* Create the database roots and give them appropriate values */ db.createRoot("allUsers", allUsers = new OSHashMap()); db.createRoot("allInterests", allInterests = new OSHashSet()); } /* End the transaction and retain a handle to allUsers and allInterests */ tr.commit(ObjectStore.RETAIN_HOLLOW); return; } /** * Close the database and terminate the session. */ public static void shutdown() { db.close(); session.terminate(); } /** * Add a new user to the database; if the user's name already * exists, throw an exception. * * @param name: The name of the user to be added * @param email: The email address of the user * * @return The PIN of the new user. * * @exception PersonalizationException is thrown if the user * is already there. */ public static int subscribe(String name, String email) throws PersonalizationException { Transaction tr = Transaction.begin(ObjectStore.UPDATE); /* First check to see if the user's name is already there. */ if (allUsers.get(name) != null) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw new PersonalizationException("User already there: " + name); } /* The user name is not there so add the new user; first generate a PIN in the range 0..10000. */ int pin = pinGenerator.nextInt() % 10000; if (pin < 0) pin = pin * -1; User newUser = new User(name, email, pin); allUsers.put(name, newUser); tr.commit(ObjectStore.RETAIN_HOLLOW); return pin; } /** * Removes the user from the database. * * @param name: The name of the user to be removed. * * @exception PersonalizationException is thrown if the user is * not found. */ public static void unsubscribe(String name) throws PersonalizationException { Transaction tr = Transaction.begin(ObjectStore.UPDATE); User user = (User) allUsers.get(name); if (user == null) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw new PersonalizationException ("Could not find user: " + name); } /* remove the user from the allUsers collection, and * remove all of the user's interests from the allInterests collection */ allUsers.remove(name); Iterator interests = user.getInterests().values().iterator(); while (interests.hasNext()) allInterests.remove(interests.next()); /* finally destroy the user and all its subobjects */ ObjectStore.destroy(user); tr.commit(ObjectStore.RETAIN_HOLLOW); } /** * Validates a username / PIN pair, and returns the user object. */ public static User validateUser(String userName, int PIN) { Transaction tr = Transaction.begin(ObjectStore.READONLY); User user = (User) allUsers.get(userName); if (user == null) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw new PersonalizationException ("Could not find user: " + userName ); } if (user.getPIN() != PIN) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw new PersonalizationException ("Invalid PIN for user: " + userName ); } tr.commit(ObjectStore.RETAIN_READONLY); return user; } /** * Add an interest to an existing user's set of interests. * * @param userName: The name of the user. * @param interestName: The name of the interest to create. * @param interestValue: The value of the new interest. * * @exception PersonalizationException: thrown if the user is * not found or if the user already has this interest. */ public static void addInterest(String userName, String interestName, String interestValue) throws PersonalizationException { Transaction tr = Transaction.begin(ObjectStore.UPDATE); User user = (User) allUsers.get(userName); if (user == null) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw new PersonalizationException("User not found: " + userName); } else { try { Interest interest = user.addInterest(interestName, interestValue); allInterests.add(interest); } catch (PersonalizationException e) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw e; } } tr.commit(ObjectStore.RETAIN_HOLLOW); return; } /** * Remove an interest from a user's set of interests. * * @param userName: The name of the user. * @param interestName: The name of the interest to remove. * * @exception PersonalizationException: thrown if the user is * not found or the interest is not found. */ public static void removeInterest(String userName, String interestName) throws PersonalizationException { Transaction tr = Transaction.begin(ObjectStore.UPDATE); User user = (User) allUsers.get(userName); if (user == null) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw new PersonalizationException("User not found: " + userName); } else { try { Interest interest = user.removeInterest(interestName); allInterests.remove(interest); ObjectStore.destroy(interest); } catch (PersonalizationException e) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw e; } } tr.commit(ObjectStore.RETAIN_HOLLOW); return; } /** * Update an interest in an existing user's set of interests. * * @param userName: The name of the user. * @param interestName: The name of the interest to modify. * @param interestValue: The new value of the interest. * * @exception PersonalizationException: thrown if the user is * not found or if the user does not already have this interest. */ public static void changeInterest(String userName, String interestName, String interestValue) throws PersonalizationException { Transaction tr = Transaction.begin(ObjectStore.UPDATE); User user = (User) allUsers.get(userName); if (user == null) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw new PersonalizationException("User not found: " + userName); } else { try { user.changeInterest(interestName, interestValue); } catch (PersonalizationException e) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw e; } } tr.commit(ObjectStore.RETAIN_HOLLOW); return; } /** * Get the interests for a particular user. * * @param userName: The name of the user. * * @return a Set of interests. * * @exception PersonalizationException: thrown if the user is * not found. */ public static Collection getInterests(String userName) throws PersonalizationException { Transaction tr = Transaction.begin(ObjectStore.READONLY); User user = (User) allUsers.get(userName); if (user == null) { tr.abort(ObjectStore.RETAIN_HOLLOW); throw new PersonalizationException ("User not found: " + userName); } /* recursively fetch all of the objects accessible from the users * set of interests, so that they can be returned and accessed * outside of a transaction */ ObjectStore.deepFetch(user.getInterests()); /* Commit using retain-readonly so the interests can be accessed * outside of this transaction. */ tr.commit(ObjectStore.RETAIN_READONLY); return user.getInterests().values(); } /** * Retrieves all of the users. * * @return an array containing the names of all registered users. * * @exception Exception: */ public static String[] getUserNames() { Transaction tr = Transaction.begin(ObjectStore.READONLY); String[] names = new String[allUsers.size()]; Iterator userIter = allUsers.values().iterator(); int userIndex = 0; while (userIter.hasNext()) names[userIndex++] = ((User)userIter.next()).getName(); tr.commit(ObjectStore.RETAIN_HOLLOW); return names; } }
package COM.odi.tutorial; import COM.odi.util.*; import java.util.*; import java.io.*; /** * The TestDriver class exercises the UserManager code. It * implements a simple UI that is driven by terminal I/O. */ public class TestDriver { /* Main: reads input commands from the terminal and exercises * the UserManager code. */ public static void main(String argv[]) { if (argv.length < 1) { System.out.println("Usage: java TestDriver <databaseName>"); return; } /* the database to operate on is a command-line argument; * the file to read commands from is an optional second argument * (if no input file is specified, commands are read from System.in) */ String dbName = argv[0]; InputStream input = System.in; if (argv.length > 1) try { input = new FileInputStream(argv[1]); } catch (FileNotFoundException e){} /* initialize the UserManager, which opens the database */ UserManager.initialize(dbName); /* read command input */ BufferedReader instream = new BufferedReader(new InputStreamReader(input)); /* print help message describing the legal commands */ printHelp(); while (true) { try { System.out.println(); /* read a line of command input */ String inputLine = instream.readLine(); if (inputLine == null) { /* end of input */ UserManager.shutdown(); return; } /* tokenize the command input with a StringTokenizer */ StringTokenizer tokenizer = new StringTokenizer(inputLine, ""); if (!tokenizer.hasMoreTokens()) continue; String command = tokenizer.nextToken(); System.out.println(); /* ******************* */ /*HELP*/ /* ******************* */ if ("help".startsWith(command)) { printHelp(); } /* ******************* */ /* SUBSCRIBE NEW USER*/ /* ******************* */ else if ("subscribe".startsWith(command)) { int PIN = UserManager.subscribe(readString(tokenizer) /*userName */, readString(tokenizer) /*userEmail */); System.out.println(" Your personal identification number is " + PIN); } /* ******************* */ /* UNSUBSCRIBE USER */ /* ******************* */ else if ("unsubscribe".startsWith(command)) { UserManager.unsubscribe(readString(tokenizer) /* userName */); } /* ******************* */ /* VALIDATE USER PIN */ /* ******************* */ else if ("validate".startsWith(command)) { User usr = UserManager.validateUser(readString(tokenizer) /*userName */, readInt(tokenizer) /* PIN*/); System.out.println(" User name " + usr.getName()); System.out.println(" PIN: " + usr.getPIN()); System.out.println(" email: " + usr.getEmail()); } /* ******************* */ /* LIST ALL USERS */ /* ******************* */ else if ("listusers".startsWith(command)) { String[] names = UserManager.getUserNames(); if (names.length == 0) System.out.println(" There are no registered users."); for (int i = 0; i<names.length; i++) { System.out.println(" " + names[i]); } } /* ******************* */ /* ADD AN INTEREST */ /* ******************* */ else if ("addinterest".startsWith(command)) { UserManager.addInterest(readString(tokenizer) /* userName */, readString(tokenizer) /* interest name */, readString(tokenizer) /* interest value */); } /* ******************* */ /* REMOVE AN INTEREST */ /* ******************* */ else if ("removeinterest".startsWith(command)) { UserManager.removeInterest(readString(tokenizer) /* userName */, readString(tokenizer) /* interest name */); } /* ******************* */ /* CHANGE AN INTEREST */ /* ******************* */ else if ("changeinterest".startsWith(command)) { UserManager.changeInterest(readString(tokenizer) /* userName */, readString(tokenizer) /* interest name */, readString(tokenizer) /* interest value */); } /* ******************* */ /* LIST USER INTERESTS */ /* ******************* */ else if ("interests".startsWith(command)) { String userName = readString(tokenizer); Collection interests = UserManager.getInterests(userName); Iterator iter = interests.iterator(); if (!iter.hasNext()) System.out.println(" " + userName + " has no registered interests."); while (iter.hasNext()) { Interest i = (Interest)iter.next(); System.out.println(" " + i.getUser().getName() + " is interested in " + i.getName() + ": " + i.getValue()); } } /* ******************* */ /* EXIT PROGRAM */ /* ******************* */ else if ("exit".startsWith(command)) { UserManager.shutdown(); return; } /* ******************** */ /* UNRECOGNIZED COMMAND */ /* ******************** */ else { System.out.println(" Command not recognized. Try \"help\""); } } catch (PersonalizationException e) { System.out.println(" " + e.toString()); } catch (Exception e) { System.out.println(" " + e.toString()); UserManager.shutdown(); return; } } } static void printHelp() { System.out.println(); System.out.println("Each command consists of the command name, and a (possibly empty)"); System.out.println("list of arguments, separated by spaces."); System.out.println(); System.out.println("Legal commands are:"); System.out.println("help // print this message"); System.out.println("subscribe <username> <email> // enter a new user into the db"); System.out.println("unsubscribe <username> // remove a user from the db"); System.out.println("validate <username> <PIN> // validate PIN and display user data"); System.out.println("listusers // list all users"); System.out.println("addinterest <username> <interestname> <value> // register an interest "); System.out.println("removeinterest <username> <interestname> // unregister an interest "); System.out.println("changeinterest <username> <interestname> <value> // change an interest "); System.out.println("interests <username> //display all interests for a user"); System.out.println("exit// exit the program"); } static String readString(StringTokenizer tokenizer) { if (tokenizer.hasMoreElements()) return tokenizer.nextToken(); else throw new PersonalizationException("unexpected end of command input"); } static int readInt(StringTokenizer tokenizer) { if (tokenizer.hasMoreElements()) { String token = tokenizer.nextToken(); try { return Integer.valueOf(token).intValue(); } catch (NumberFormatException e) { throw new PersonalizationException( "Number Format Exception reading \"" + token + "\""); } } else throw new PersonalizationException("unexpected end of command input"); } }
package COM.odi.tutorial; import java.util.*; /** * The PersonalizationException is thrown when certain error * conditions arise. For example * -- a uid is not found * -- a user already exists in the database * -- an interest is not found * -- an interest already exists in the user's set of interests */ public final class PersonalizationException extends RuntimeException { public PersonalizationException (String message) { super (message); } }
Updated: 10/07/98 07:06:01