package context.arch.storage; import java.lang.reflect.Constructor; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ResourceBundle; import context.arch.comm.DataObject; //import context.arch.util.Constants; /** * This class allows storage and retrieval of data in String, Integer, Long, Float, * Double, or Short format. It uses a default storage class * (context.arch.storage.VectorStorage), but can use any given storage class that * implements the Storage interface. * * This expects to connect to a database, and grabs connection configuration from widgets-storage-db.properties * which should be in the classpath. * * TODO: this seems to be some delegate class; it should be renamed. What is its true relation to Storage? * * @see context.arch.storage.Storage * * @author Anind Dey * @author Brian Y. Lim */ public class StorageObject { private Attributes lastStored = null; private String storageClass = ""; private Storage storage = null; /** * Tag for debugging. */ private static final boolean DEBUG = false; /** * Tag for retrieving data */ public static final String RETRIEVE_DATA = "retrieveData"; /** * Tag for reply to retrieve data request */ public static final String RETRIEVE_DATA_REPLY = "retrieveDataReply"; /** * The default storage class is context.arch.storage.VectorStorage */ public static final String DEFAULT_STORAGE_CLASS = VectorStorage.class.getName(); /** * Basic constructor that uses the default storage class * * @param table Name of the table to use - should be the id of the calling object * @exception InvalidStorageException when the default storage class can't be created * @see #DEFAULT_STORAGE_CLASS */ public StorageObject(String table) throws InvalidStorageException { this(DEFAULT_STORAGE_CLASS, table); } public StorageObject() { // TODO } /** * Constructor that sets the storage class to use and creates the * storage class. If the class is null, the default class is used. * If the table is null, an exception is thrown. * * @param storageClass Class to use for storage * @param table Name of the table to use - should be the id of the calling object * @exception InvalidStorageException thrown when there are any errors creating the * storage class object or connecting to the persistent storage * @exception InvalidStorageException when the given storage class can't be created * @see #DEFAULT_STORAGE_CLASS */ public StorageObject(String storeClass, String table) throws InvalidStorageException { if (storeClass == null) { storageClass = DEFAULT_STORAGE_CLASS; } else { storageClass = storeClass; } if (table == null) { throw new InvalidStorageException(table); } if (DEBUG) { System.out.println("Storage table is: " + table + storageClass); } try { // if (System.getProperty("os.name").equals(Constants.WINCE)) { // this is an obsolete OS // storage = new VectorStorage(table); // } // else { Constructor<?> constructor = Class.forName(storageClass).getConstructor(String.class); storage = (Storage) constructor.newInstance(table); // } } catch (Exception e) { e.printStackTrace(); throw new InvalidStorageException(storageClass); } } /** * Constructor that sets the storage class to use * * @param storageClass Class to use for storage * @param table Name of the table to use - should be the id of the calling object * @param flushType Flush to database based on TIME or DATA * @param flushCondition Condition to flush local storage to database * @exception InvalidStorageException when the given storage class can't be created */ public StorageObject(String storageClass, String table, Integer flushType, Long flushCondition) throws InvalidStorageException { try { Constructor<?> constructor = Class.forName(storageClass).getConstructor(String.class, Integer.class, Long.class); storage = (Storage)constructor.newInstance(table, flushType, flushCondition); } catch (Exception e) { e.printStackTrace(); throw new InvalidStorageException(storageClass); } } /** * For getting a connection from the database. * The application needs the property file storage-db.properties in the classpath with properties:<pre> * Driver=com.mysql.jdbc.Driver * URL=jdbc:mysql://host:port/dbname * Username= * Password= * </pre> * @return * @throws SQLException * @throws ClassNotFoundException */ public static Connection getConnection() { ResourceBundle bundle = ResourceBundle.getBundle("widgets-storage-db"); String driver = bundle.getString("Driver"); String url = bundle.getString("URL"); String username = bundle.getString("Username"); String password = bundle.getString("Password"); try { Class.forName(driver); return DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return null; } /** * This method stores the given AttributeNameValues object and checks whether the locally * stored data should be flushed to persistent storage. It is a stub method that * simply calls the store(), checkFlushCondition() and flushStorage() methods in the * Storage interface. * * @param atts AttributeNameValues to store * @see context.arch.storage.Storage#store(context.arch.storage.AttributeNameValues) * @see context.arch.storage.Storage#flushStorage() * @see context.arch.storage.Storage#checkFlushCondition() */ public void store(Attributes atts) { storage.store(atts); if (storage.checkFlushCondition()) { storage.flushStorage(); } lastStored = atts; } /** * This method stores the attributes in the given DataObject * and checks whether the locally stored data should be flushed to persistent storage. * It assumes that the DataObject has the starting tag <ATTRIBUTENAMEVALUES>. It is * a stub method that converts the DataObject to an AttributeNameValues object and calls * the store(AttributeNameValues) method in this class. * * @param data DataObject containing the attributes to store * @see #store(context.arch.storage.AttributeNameValues) */ public void store(DataObject data) { store(Attributes.fromDataObject(data)); } /** * Returns the last AttributeNameValues object stored * * @return the last AttributeNameValues object stored */ public Attributes retrieveLastAttributes() { return lastStored; } /** * Flushes the locally stored data to persistent storage */ public void flushStorage() { storage.flushStorage(); } /** * This method returns a vector containing AttributeNameValues objects that matches * the given conditions in the Retrieval object * * @param retrieval Retrieval object that contains conditions for retrievalcompare Flag that dictates the type of comparison * @return RetrievalResults containing AttributeNameValues objects that matches the given compare * flag and value */ public RetrievalResults retrieveAttributes(Retrieval retrieval) { return storage.retrieveAttributes(retrieval); } /** * This method returns a vector containing AttributeNameValues objects that matches * the given conditions in the Retrieval object, and that the given requestorId * is allowed to have access to * * @param accessorId Id of the "user" trying to retrieve data * @param retrieval Retrieval object that contains conditions for retrievalcompare Flag that dictates the type of comparison * @return RetrievalResults containing AttributeNameValues objects that matches the given compare * flag and value */ public RetrievalResults retrieveAttributes(String requestorId, Retrieval retrieval) { return storage.retrieveAttributes(requestorId, retrieval); } /** * This method sets the attributes to use for storage. * * @param attributes AttributeNameValues containing attribute info for this object */ public void setAttributes(Attributes attributes) { storage.setAttributes(attributes); } }