From: <mwl...@us...> - 2009-01-14 22:32:19
|
Revision: 834 http://cishell.svn.sourceforge.net/cishell/?rev=834&view=rev Author: mwlinnem Date: 2009-01-14 22:20:41 +0000 (Wed, 14 Jan 2009) Log Message: ----------- Moved to the correct place. Added Paths: ----------- trunk/core/org.cishell.reference.service.database/ Removed Paths: ------------- trunk/core/org.cishell.docs/org.cishell.reference.service.database/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mwl...@us...> - 2009-01-22 16:57:02
|
Revision: 849 http://cishell.svn.sourceforge.net/cishell/?rev=849&view=rev Author: mwlinnem Date: 2009-01-22 16:56:57 +0000 (Thu, 22 Jan 2009) Log Message: ----------- Made DataSourceWithID into an interface, and moved the implementation to the reference plugin. Modified Paths: -------------- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.java trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java Added Paths: ----------- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java Copied: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java (from rev 848, trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java) =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java (rev 0) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java 2009-01-22 16:56:57 UTC (rev 849) @@ -0,0 +1,79 @@ +package org.cishell.reference.service.database; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.cishell.service.database.DataSourceWithID; + +public class DataSourceWithIDImpl implements DataSource, DataSourceWithID { + private static int idCounter = 0; + + private DataSource wrappedDataSource; + private int id; + + private static int generateNewID() { + int newID = idCounter; + + idCounter++; + + return newID; + } + + public DataSourceWithIDImpl(DataSource wrappedDataSource) { + this.wrappedDataSource = wrappedDataSource; + this.id = generateNewID(); + } + + /* (non-Javadoc) + * @see org.cishell.service.database.DataSourceWithIDI#getID() + */ + public int getID() { + return id; + } + + /* (non-Javadoc) + * @see org.cishell.service.database.DataSourceWithIDI#getConnection() + */ + public Connection getConnection() throws SQLException { + return this.wrappedDataSource.getConnection(); + } + + /* (non-Javadoc) + * @see org.cishell.service.database.DataSourceWithIDI#getConnection(java.lang.String, java.lang.String) + */ + public Connection getConnection(String username, String password) + throws SQLException { + return this.wrappedDataSource.getConnection(username, password); + } + + /* (non-Javadoc) + * @see org.cishell.service.database.DataSourceWithIDI#getLogWriter() + */ + public PrintWriter getLogWriter() throws SQLException { + return this.wrappedDataSource.getLogWriter(); + } + + /* (non-Javadoc) + * @see org.cishell.service.database.DataSourceWithIDI#setLogWriter(java.io.PrintWriter) + */ + public void setLogWriter(PrintWriter out) throws SQLException { + this.wrappedDataSource.setLogWriter(out); + } + + /* (non-Javadoc) + * @see org.cishell.service.database.DataSourceWithIDI#getLoginTimeout() + */ + public int getLoginTimeout() throws SQLException { + return this.wrappedDataSource.getLoginTimeout(); + } + + /* (non-Javadoc) + * @see org.cishell.service.database.DataSourceWithIDI#setLoginTimeout(int) + */ + public void setLoginTimeout(int seconds) throws SQLException { + this.wrappedDataSource.setLoginTimeout(seconds); + } +} \ No newline at end of file Property changes on: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java ___________________________________________________________________ Added: svn:mergeinfo + Modified: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.java 2009-01-21 21:57:08 UTC (rev 848) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.java 2009-01-22 16:56:57 UTC (rev 849) @@ -33,6 +33,7 @@ /* TODO: Using a rolling counter like this may have bad implications later on, but it's decent for now. */ + //Not used for now private static int dbNameCounter = 0; private ServiceRegistration databaseServiceRegistration; @@ -82,7 +83,7 @@ // Driver jdbcDriver = (Driver) Class.forName(driver).newInstance(); String newDatabaseName = - DEFAULT_DB_NAME + Integer.toString(dbNameCounter); + DEFAULT_DB_NAME; String newDatabaseConnectionURL = DEFAULT_PROTOCOL + newDatabaseName + DEFAULT_CREATE_CONNECTION_STRING; @@ -131,6 +132,6 @@ } public DataSourceWithID createDatabase() throws DatabaseCreationException { - return new DataSourceWithID(getConnectionPool()); + return new DataSourceWithIDImpl(getConnectionPool()); } } Modified: trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java =================================================================== --- trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java 2009-01-21 21:57:08 UTC (rev 848) +++ trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java 2009-01-22 16:56:57 UTC (rev 849) @@ -1,56 +1,23 @@ -package org.cishell.service.database; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - -public class DataSourceWithID implements DataSource { - private static int idCounter = 0; - - private DataSource wrappedDataSource; - private int id; - - private static int generateNewID() { - int newID = idCounter; - - idCounter++; - - return newID; - } - - public DataSourceWithID(DataSource wrappedDataSource) { - this.wrappedDataSource = wrappedDataSource; - this.id = generateNewID(); - } - - public int getID() { - return id; - } - - public Connection getConnection() throws SQLException { - return this.wrappedDataSource.getConnection(); - } - - public Connection getConnection(String username, String password) - throws SQLException { - return this.wrappedDataSource.getConnection(username, password); - } - - public PrintWriter getLogWriter() throws SQLException { - return this.wrappedDataSource.getLogWriter(); - } - - public void setLogWriter(PrintWriter out) throws SQLException { - this.wrappedDataSource.setLogWriter(out); - } - - public int getLoginTimeout() throws SQLException { - return this.wrappedDataSource.getLoginTimeout(); - } - - public void setLoginTimeout(int seconds) throws SQLException { - this.wrappedDataSource.setLoginTimeout(seconds); - } +package org.cishell.service.database; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; + +public interface DataSourceWithID { + + public abstract int getID(); + + public abstract Connection getConnection() throws SQLException; + + public abstract Connection getConnection(String username, String password) throws SQLException; + + public abstract PrintWriter getLogWriter() throws SQLException; + + public abstract void setLogWriter(PrintWriter out) throws SQLException; + + public abstract int getLoginTimeout() throws SQLException; + + public abstract void setLoginTimeout(int seconds) throws SQLException; + } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mwl...@us...> - 2009-12-17 20:09:08
|
Revision: 993 http://cishell.svn.sourceforge.net/cishell/?rev=993&view=rev Author: mwlinnem Date: 2009-12-17 20:09:00 +0000 (Thu, 17 Dec 2009) Log Message: ----------- Changed to create entirely new databases (not just new data sources) for each new database datamanager item. Not compatible with previous version. Still in development, but uploading so Patrick can use it in his algorithm as is. Modified Paths: -------------- trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java Added Paths: ----------- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java Removed Paths: ------------- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java Modified: trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF 2009-12-17 20:09:00 UTC (rev 993) @@ -13,7 +13,11 @@ org.apache.derby.jdbc, org.cishell.framework.algorithm;version="1.0.0", org.cishell.service.database, + org.eclipse.core.internal.runtime, org.osgi.framework;version="1.4.0", + org.osgi.service.cm;version="1.2.0", org.osgi.service.component;version="1.0.0", - org.osgi.service.log;version="1.3.0" + org.osgi.service.log;version="1.3.0", + org.osgi.util.tracker;version="1.3.3" Service-Component: OSGI-INF/component.xml +Require-Bundle: org.junit4 Deleted: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java 2009-12-17 20:09:00 UTC (rev 993) @@ -1,79 +0,0 @@ -package org.cishell.reference.service.database; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - -import org.cishell.service.database.DataSourceWithID; - -public class DataSourceWithIDImpl implements DataSource, DataSourceWithID { - private static int idCounter = 0; - - private DataSource wrappedDataSource; - private int id; - - private static int generateNewID() { - int newID = idCounter; - - idCounter++; - - return newID; - } - - public DataSourceWithIDImpl(DataSource wrappedDataSource) { - this.wrappedDataSource = wrappedDataSource; - this.id = generateNewID(); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getID() - */ - public int getID() { - return id; - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getConnection() - */ - public Connection getConnection() throws SQLException { - return this.wrappedDataSource.getConnection(); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getConnection(java.lang.String, java.lang.String) - */ - public Connection getConnection(String username, String password) - throws SQLException { - return this.wrappedDataSource.getConnection(username, password); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getLogWriter() - */ - public PrintWriter getLogWriter() throws SQLException { - return this.wrappedDataSource.getLogWriter(); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#setLogWriter(java.io.PrintWriter) - */ - public void setLogWriter(PrintWriter out) throws SQLException { - this.wrappedDataSource.setLogWriter(out); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getLoginTimeout() - */ - public int getLoginTimeout() throws SQLException { - return this.wrappedDataSource.getLoginTimeout(); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#setLoginTimeout(int) - */ - public void setLoginTimeout(int seconds) throws SQLException { - this.wrappedDataSource.setLoginTimeout(seconds); - } -} \ No newline at end of file Modified: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2009-12-17 20:09:00 UTC (rev 993) @@ -2,11 +2,12 @@ import java.sql.Connection; import java.sql.DatabaseMetaData; -import java.sql.DriverManager; import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; import javax.sql.DataSource; @@ -17,73 +18,57 @@ import org.apache.commons.pool.KeyedObjectPoolFactory; import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory; import org.apache.commons.pool.impl.GenericObjectPool; -import org.cishell.service.database.DataSourceWithID; +import org.cishell.service.database.Database; import org.cishell.service.database.DatabaseCreationException; import org.cishell.service.database.DatabaseService; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; - public class DerbyDatabaseService implements DatabaseService, BundleActivator { - /* - * Variables used to connect to the internal derby database - * - * TODO: Eventually support connecting databases other than derby, - * and connecting to databases other than our internal one - * (maybe not by modifying this class directly though). - */ - private static final String DERBY_DRIVER_NAME = + public static final String DERBY_DRIVER_NAME = "org.apache.derby.jdbc.EmbeddedDriver"; - private static final String DERBY_PROTOCOL = "jdbc:derby:"; - private static final String DEFAULT_CREATE_CONNECTION_STRING = ";create=true"; - private static final String DEFAULT_SHUTDOWN_CONNECTION_STRING =";shutdown=true"; - private static final String DEFAULT_DB_NAME = "cishell_database"; + public static final String DERBY_PROTOCOL = "jdbc:derby:"; + public static final String DEFAULT_CREATE_CONNECTION_STRING = ";create=true"; + public static final String DEFAULT_SHUTDOWN_CONNECTION_STRING =";shutdown=true"; //where the database exists on the filesystem (relative to the application root directory) private static final String DATABASE_DIRECTORY = "database/"; - //(new connections to the database will come from a pool of connections, improving performance) - private PoolingDataSource poolingDataSource = null; - //hold on to our service registration so we can unregister when this plugin stops. private ServiceRegistration databaseServiceRegistration; + private List internalDatabases = new ArrayList(); + public void start(BundleContext context) throws Exception { /* * Tell Derby to look for an existing database or create a new database - * in the default directory (within our application's directory) + * in the default directory (within our application's directory) */ System.setProperty("derby.system.home", DATABASE_DIRECTORY); - /* - * Make sure we don't have any leftover cruft in the db from previous sessions. - * This is our second chance, if the database wasn't properly cleaned out - * in the stop() method on application exit. - * TODO: If we ever implement some kind of persistence we may not want to do this so bluntly - */ - removeAllNonSystemDatabaseTables(); - //allow the database service to be found by other services/plugins databaseServiceRegistration = context.registerService (DatabaseService.class.getName(), this, new Hashtable()); - } public void stop(BundleContext context) { //disallow the database service to be found by other services/plugins this.databaseServiceRegistration.unregister(); - //try to clean out the database and shut it down. + //try to clean out the databases and shut them down. try { - removeAllNonSystemDatabaseTables(); - String shutdownDatabaseCommand = - DERBY_PROTOCOL + DEFAULT_SHUTDOWN_CONNECTION_STRING; - DriverManager.getConnection(shutdownDatabaseCommand); + + + for (Iterator it = internalDatabases.iterator(); it.hasNext();) { + InternalDerbyDatabase activeDatabase = (InternalDerbyDatabase) it.next(); + Connection activeDatabaseConnection = activeDatabase.getConnection(); + removeAllNonSystemDatabaseTables(activeDatabaseConnection); + activeDatabase.shutdown(); + } } catch (Exception e) { String message = "An unexpected exception occurred while shutting down the internal database." + @@ -92,22 +77,86 @@ throw new RuntimeException(message, e); } } + - //Return a link to a "database" that cannot interfere with other "databases" in the system. - //TODO: May need to refactor to improve the terminology used surrounding this functionality. - public DataSourceWithID createDatabase() throws DatabaseCreationException { - return new DataSourceWithIDImpl(getDataSource()); + private static final String DB_NAME_PREFIX = "cishell_database"; + private static int id = 0; + + public synchronized Database createNewDatabase() throws DatabaseCreationException { + try { + //connect to and create a 'new' database + String databaseName = DB_NAME_PREFIX + id; + Database db = new InternalDerbyDatabase(databaseName, createNewInternalDataSource(databaseName)); + + //if this database existed on disk from a previous session, clean it to be like new + removeAllNonSystemDatabaseTables(db.getConnection()); + + //keep track of our new database for this CIShell session + internalDatabases.add(db); + + id++; + return db; + } catch (Exception e) { + throw new DatabaseCreationException(e); + } } + public Database connectToExistingDatabase(String driver, String url) + throws DatabaseCreationException { + return connectToExistingDatabase(driver, url, null, null); + } + public Database connectToExistingDatabase( + String driver, String url, String username, String password) + throws DatabaseCreationException { + DataSource dataSource = + createNewDataSource(driver, url, username, password); + //TODO: change Database to support non-derby urls and whatnot + Database db = new ExternalDatabase(dataSource); + //(assuming we don't need to keep track of these databases, as we will not close them on shutdown) + return db; + } + + + + //***---UTILITIES---*** + + private DataSource createNewDataSource( + String driver, String url, String username, String password) + throws DatabaseCreationException { + try { + //Load the database driver + Class.forName(driver); + + ConnectionFactory connectionFactory = new DriverManagerConnectionFactory + (url, username, password); + GenericObjectPool connectionPool = new GenericObjectPool(); + KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null); + //(side-effects) + new PoolableConnectionFactory(connectionFactory, connectionPool, stmtPool, null, false, true); + //(creating the data source this way is probably overkill for our current purposes, + //(but I don't imagine it does much harm either). + DataSource dataSource = new PoolingDataSource(connectionPool); + return dataSource; + } catch (ClassNotFoundException e) { + throw new DatabaseCreationException + ("Database driver '" + driver + "' could not be found", e); + } + } + + private DataSource createNewInternalDataSource(String dbName) + throws DatabaseCreationException { + String newDatabaseConnectionURL = DERBY_PROTOCOL + + dbName + + DEFAULT_CREATE_CONNECTION_STRING; + return createNewDataSource(DERBY_DRIVER_NAME, newDatabaseConnectionURL, null, null); + } + private static final int SCHEMA_NAME_INDEX = 2; private static final int TABLE_NAME_INDEX = 3; private static final String NONSYSTEM_SCHEMA_NAME = "APP"; - private void removeAllNonSystemDatabaseTables() throws Exception { - - DataSource db = getDataSource(); - Connection dbConnection = db.getConnection(); + private void removeAllNonSystemDatabaseTables(Connection dbConnection) throws Exception { DatabaseMetaData dbMetadata = dbConnection.getMetaData(); ResultSet allTableNames = dbMetadata.getTables(null, null, null, null); @@ -124,45 +173,6 @@ removeTables.executeBatch(); } - - //TODO: It could be that we should give everyone different datasources instead of the same one - private PoolingDataSource getDataSource() throws DatabaseCreationException - { - if (this.poolingDataSource == null) { initializePoolingDataSource(); }; - return poolingDataSource; - } - //lazy-load the pooling data source (implicitly creates the initial database connection) - //TODO: Make it more clear where database connection is initially established - private void initializePoolingDataSource() throws DatabaseCreationException { - if (this.poolingDataSource != null) { - return; - } - - try { - //Load the database driver - Class.forName(DERBY_DRIVER_NAME); - - /* - * TODO:We can use this later to check acceptsUrl for better error reporting. - * Driver jdbcDriver = (Driver) Class.forName(driver).newInstance(); - */ - String newDatabaseConnectionURL = DERBY_PROTOCOL + - DEFAULT_DB_NAME + - DEFAULT_CREATE_CONNECTION_STRING; - - ConnectionFactory connectionFactory = new DriverManagerConnectionFactory - (newDatabaseConnectionURL, null, null); - GenericObjectPool connectionPool = new GenericObjectPool(); - KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null); - //(side-effects the connection-pool so it gets its connections from the connection factory (I think)) - new PoolableConnectionFactory(connectionFactory, connectionPool, stmtPool, null, false, true); - this.poolingDataSource = new PoolingDataSource(connectionPool); - } - catch (ClassNotFoundException e) { - throw new DatabaseCreationException - ("Database driver '" + DERBY_DRIVER_NAME + "' could not be found", e); - } - } } Added: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java (rev 0) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java 2009-12-17 20:09:00 UTC (rev 993) @@ -0,0 +1,30 @@ +package org.cishell.reference.service.database; + +import java.sql.Connection; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.cishell.service.database.Database; + +public class ExternalDatabase implements Database { + + private DataSource dataSource; + + public ExternalDatabase(DataSource dataSource) { + this.dataSource = dataSource; + } + + public Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } + + /* + * TODO: We could store the password from the beginning. + * Will want to discuss security implications here. + */ + public Connection getConnection(String username, String password) + throws SQLException { + return dataSource.getConnection(username, password); + } +} Added: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java (rev 0) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java 2009-12-17 20:09:00 UTC (rev 993) @@ -0,0 +1,34 @@ +package org.cishell.reference.service.database; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.cishell.service.database.Database; + +public class InternalDerbyDatabase implements Database { + + private String name; + private DataSource dataSource; + + public InternalDerbyDatabase(String name, DataSource dataSource) { + this.name = name; + this.dataSource = dataSource; + } + + + public Connection getConnection() throws SQLException { + return this.dataSource.getConnection(); + } + + public void shutdown() throws SQLException { + String shutdownDatabaseCommand = + DerbyDatabaseService.DERBY_PROTOCOL + + DerbyDatabaseService.DEFAULT_SHUTDOWN_CONNECTION_STRING; + DriverManager.getConnection(shutdownDatabaseCommand); + + + } +} Modified: trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF 2009-12-17 20:09:00 UTC (rev 993) @@ -5,3 +5,4 @@ Bundle-Version: 1.0.0 Bundle-RequiredExecutionEnvironment: J2SE-1.4 Export-Package: org.cishell.service.database +Import-Package: org.apache.commons.dbcp Added: trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java =================================================================== --- trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java (rev 0) +++ trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java 2009-12-17 20:09:00 UTC (rev 993) @@ -0,0 +1,10 @@ +package org.cishell.service.database; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.apache.commons.dbcp.ConnectionFactory; + +public interface Database { + public Connection getConnection() throws SQLException; +} \ No newline at end of file Modified: trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java =================================================================== --- trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java 2009-12-17 20:09:00 UTC (rev 993) @@ -1,5 +1,10 @@ package org.cishell.service.database; public interface DatabaseService { - public DataSourceWithID createDatabase() throws DatabaseCreationException; + public Database createNewDatabase() throws DatabaseCreationException; + public Database connectToExistingDatabase(String driver, String url) + throws DatabaseCreationException; + public Database connectToExistingDatabase( + String driver, String url, String username, String password) + throws DatabaseCreationException; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mwl...@us...> - 2010-01-04 17:29:16
|
Revision: 1003 http://cishell.svn.sourceforge.net/cishell/?rev=1003&view=rev Author: mwlinnem Date: 2010-01-04 17:29:08 +0000 (Mon, 04 Jan 2010) Log Message: ----------- Modified to incorporate database-related constants into this service (before they were duplicated in various other areas). Modified Paths: -------------- trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java Added Paths: ----------- trunk/core/org.cishell.reference.service.database/.checkstyle trunk/core/org.cishell.service.database/bin/ Removed Paths: ------------- trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java Added: trunk/core/org.cishell.reference.service.database/.checkstyle =================================================================== --- trunk/core/org.cishell.reference.service.database/.checkstyle (rev 0) +++ trunk/core/org.cishell.reference.service.database/.checkstyle 2010-01-04 17:29:08 UTC (rev 1003) @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<fileset-config file-format-version="1.2.0" simple-config="true"> + <fileset name="all" enabled="true" check-config-name="CNS Checks (Eclipse)" local="false"> + <file-match-pattern match-pattern="." include-pattern="true"/> + </fileset> +</fileset-config> Modified: trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF 2009-12-30 20:55:04 UTC (rev 1002) +++ trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF 2010-01-04 17:29:08 UTC (rev 1003) @@ -3,7 +3,6 @@ Bundle-Name: Database Plug-in Bundle-SymbolicName: org.cishell.reference.service.database Bundle-Version: 1.0.0 -Bundle-RequiredExecutionEnvironment: J2SE-1.4 Bundle-Activator: org.cishell.reference.service.database.DerbyDatabaseService X-AutoStart: true Import-Package: org.apache.commons.dbcp, @@ -20,3 +19,4 @@ org.osgi.service.log;version="1.3.0", org.osgi.util.tracker;version="1.3.3" Service-Component: OSGI-INF/component.xml +Bundle-RequiredExecutionEnvironment: J2SE-1.5 Modified: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2009-12-30 20:55:04 UTC (rev 1002) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2010-01-04 17:29:08 UTC (rev 1003) @@ -89,8 +89,10 @@ try { //connect to and create a 'new' database String databaseName = INTERNAL_DB_NAME_PREFIX + id; - InternalDerbyDatabase db = new InternalDerbyDatabase(createNewInternalDataSource(databaseName)); + InternalDerbyDatabase db = + new InternalDerbyDatabase(createNewInternalDataSource(databaseName)); + //if this database existed on disk from a previous session, clean it to be like new removeAllNonSystemDatabaseTables(db.getConnection()); @@ -115,7 +117,8 @@ throws DatabaseCreationException { DataSource dataSource = createNewDataSource(driver, url, username, password); - Database db = new ExternalDatabase(dataSource); + //TODO: See if we can get the default schema as a property somehow. + Database db = new ExternalDatabase(dataSource, "APP"); return db; } Modified: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java 2009-12-30 20:55:04 UTC (rev 1002) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java 2010-01-04 17:29:08 UTC (rev 1003) @@ -10,9 +10,11 @@ public class ExternalDatabase implements Database { private DataSource dataSource; + private String schemaName; - public ExternalDatabase(DataSource dataSource) { + public ExternalDatabase(DataSource dataSource, String schemaName) { this.dataSource = dataSource; + this.schemaName = schemaName; } public Connection getConnection() throws SQLException { @@ -27,4 +29,8 @@ throws SQLException { return dataSource.getConnection(username, password); } + + public String getApplicationSchemaName() { + return schemaName; + } } Modified: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java 2009-12-30 20:55:04 UTC (rev 1002) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java 2010-01-04 17:29:08 UTC (rev 1003) @@ -27,4 +27,10 @@ + DerbyDatabaseService.DEFAULT_SHUTDOWN_CONNECTION_STRING; DriverManager.getConnection(shutdownDatabaseCommand); } + + + //TODO: We might want to expose our different 'databases' as different schemas at some point instead. + public String getApplicationSchemaName() { + return "APP"; + } } Modified: trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF 2009-12-30 20:55:04 UTC (rev 1002) +++ trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF 2010-01-04 17:29:08 UTC (rev 1003) @@ -3,6 +3,6 @@ Bundle-Name: Database Plug-in Bundle-SymbolicName: org.cishell.service.database Bundle-Version: 1.0.0 -Bundle-RequiredExecutionEnvironment: J2SE-1.4 +Bundle-RequiredExecutionEnvironment: J2SE-1.5 Export-Package: org.cishell.service.database Import-Package: org.apache.commons.dbcp Deleted: trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java =================================================================== --- trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java 2009-12-30 20:55:04 UTC (rev 1002) +++ trunk/core/org.cishell.service.database/src/org/cishell/service/database/DataSourceWithID.java 2010-01-04 17:29:08 UTC (rev 1003) @@ -1,25 +0,0 @@ -package org.cishell.service.database; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - -public interface DataSourceWithID extends DataSource { - - public abstract int getID(); - - public abstract Connection getConnection() throws SQLException; - - public abstract Connection getConnection(String username, String password) throws SQLException; - - public abstract PrintWriter getLogWriter() throws SQLException; - - public abstract void setLogWriter(PrintWriter out) throws SQLException; - - public abstract int getLoginTimeout() throws SQLException; - - public abstract void setLoginTimeout(int seconds) throws SQLException; - -} \ No newline at end of file Modified: trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java =================================================================== --- trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java 2009-12-30 20:55:04 UTC (rev 1002) +++ trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java 2010-01-04 17:29:08 UTC (rev 1003) @@ -3,8 +3,18 @@ import java.sql.Connection; import java.sql.SQLException; -import org.apache.commons.dbcp.ConnectionFactory; + public interface Database { + public static final String DB_MIME_TYPE_PREFIX = "db:"; + public static final String GENERIC_DB_MIME_TYPE = "db:any"; + public Connection getConnection() throws SQLException; + + /** + * + * @return the name of the schema where the non-system tables we are interested in reside. + */ + public String getApplicationSchemaName(); + } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pat...@us...> - 2010-08-05 19:23:46
|
Revision: 1116 http://cishell.svn.sourceforge.net/cishell/?rev=1116&view=rev Author: pataphil Date: 2010-08-05 19:23:40 +0000 (Thu, 05 Aug 2010) Log Message: ----------- * Changed org.cishell.utilities.swt to org.cishell.utility.swt. Added Paths: ----------- trunk/core/org.cishell.utility.swt/ Removed Paths: ------------- trunk/core/org.cishell.utilities.swt/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pat...@us...> - 2010-08-23 18:07:54
|
Revision: 1128 http://cishell.svn.sourceforge.net/cishell/?rev=1128&view=rev Author: pataphil Date: 2010-08-23 18:07:46 +0000 (Mon, 23 Aug 2010) Log Message: ----------- * Revamped DataModel framework. * Reviewed by Chintan. Modified Paths: -------------- trunk/core/org.cishell.utility.datastructure/META-INF/MANIFEST.MF trunk/core/org.cishell.utility.swt/META-INF/MANIFEST.MF trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/ExpandableComponentWidget.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/ScrolledComponentFactory.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/datasynchronizer/CheckBoxDataSynchronizer.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/datasynchronizer/DropDownDataSynchronizer.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/datasynchronizer/SingleListSelectionDataSynchronizer.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/datasynchronizer/TextDataSynchronizer.java Added Paths: ----------- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/DataModel.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/ModelDataSynchronizer.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/AbstractDataModelArea.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/DataModelArea.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/DataModelAreaContainer.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ModelStructureException.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ModelValidationException.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/UniqueNameException.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelField.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelFieldContainer.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/BasicModelGroup.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/DataModelGroup.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/gui/ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/gui/AbstractGUIDataModel.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/WidgetConstructionException.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModel.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModelArea.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModelField.java Removed Paths: ------------- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utilities/ trunk/core/org.cishell.utility.swt/src/org/cishell/utilities/swt/model/ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModel.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModelField.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModelGroup.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/datasynchronizer/ModelDataSynchronizer.java Modified: trunk/core/org.cishell.utility.datastructure/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.utility.datastructure/META-INF/MANIFEST.MF 2010-08-23 18:06:40 UTC (rev 1127) +++ trunk/core/org.cishell.utility.datastructure/META-INF/MANIFEST.MF 2010-08-23 18:07:46 UTC (rev 1128) @@ -4,4 +4,10 @@ Bundle-SymbolicName: org.cishell.utility.datastructure Bundle-Version: 1.0.0 Bundle-RequiredExecutionEnvironment: J2SE-1.5 -Export-Package: org.cishell.utility.datastructure +Export-Package: org.cishell.utility.datastructure, + org.cishell.utility.datastructure.datamodel, + org.cishell.utility.datastructure.datamodel.area, + org.cishell.utility.datastructure.datamodel.exception, + org.cishell.utility.datastructure.datamodel.field, + org.cishell.utility.datastructure.datamodel.group, + org.cishell.utility.datastructure.datamodel.gui Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/DataModel.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/DataModel.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/DataModel.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,201 @@ +package org.cishell.utility.datastructure.datamodel; + +import java.util.Collection; +import java.util.Map; + +import org.cishell.utility.datastructure.datamodel.area.DataModelArea; +import org.cishell.utility.datastructure.datamodel.area.DataModelAreaContainer; +import org.cishell.utility.datastructure.datamodel.exception.ModelStructureException; +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; +import org.cishell.utility.datastructure.datamodel.group.DataModelGroup; + +/** + * DataModel is intended to organize and structure the manipulation of data elements + * (@link DataModelField) in a generic fashion. + * DataModel is inspired by GUIs--a GUI requiring user input (through various input fields) could + * be tied to a DataModel, which automatically contains values from the GUI. When the GUI is done + * (as in, the user finished), the DataModel could then be used for data retrieval in a + * GUI-agnostic fashion. + * Though of course implementation-specific, DataModel is designed to allow the + * addition/modification/deletion of user input fields without any knowledge of the particular + * (type of) GUI the DataModel is tied to. In other words, a DataModel could be purely data, + * AWT-/Swing-, or SWT-based, and input fields could still be interacted with on an + * abstract level. + * DataModels consist of areas {@link DataModelArea} and groups (@link DataModelGroup). + * Areas and groups both contain fields (@link DataModelField). + * Where as groups are purely organization structures (so one could get all fields within a group, + * say), areas are also tied to physical composite GUI structures so GUI-agnostic code can add + * fields to a given specific area. + * When adding fields, an area is not required. This implies that areas are not required for a + * valid model, and thus the ability to extend areas with sub-areas and/or fields is up to the + * GUI designer. + * A group is required when adding fields. DataModel itself actually provides no mechanism for + * retrieving fields directly. Rather, the recommended/somewhat-enforced method for field + * retrieval is via groups. + * Currently, there is no mechanism for abstractly expressing field component styles. + * DataModel is not thread-synchronized. + * Further usage details are described on a per-method basis. + */ +public interface DataModel extends DataModelAreaContainer { + public static final String DEFAULT_GROUP_NAME = "defaultGroup"; + + // Miscellaneous methods + + /** + * Set the parent GUI component. + * GUI-agnostic on the interface level. + * The GUI-specific implementations of this interface must type check parent for validity. + * This has to exist so fields can be added to GUIs without knowing about the GUI or how the + * GUI works. + * Parent components can be retrieved from specific fields or specific areas. + * + * @param currentParentComponent the current parent/containing GUI component to which this + * model should add subsequent fields to. + */ + public void setCurrentParentComponent(Object currentParentComponent) throws ClassCastException; + + // DataModelAreaContainer methods + + /// {@inheritDoc} + public Collection<String> getAreaNames(); + /// {@inheritDoc} + public Collection<DataModelArea> getAreas(); + /// {@inheritDoc} + public DataModelArea getArea(String name); + /// {@inheritDoc} + public DataModelArea createArea(String name) throws UniqueNameException; + /// {@inheritDoc} + public DataModelArea createArea(String name, Object componentForArea) + throws ClassCastException, ModelStructureException, UniqueNameException; + /// {@inheritDoc} + public void addArea(DataModelArea area) + throws ClassCastException, ModelStructureException, UniqueNameException; + /// {@inheritDoc} + public boolean areaDisposed(String name); + /// {@inheritDoc} + public boolean areaDisposed(DataModelArea area); + + // Group methods + + /// @return all of the group names in this DataModel. + public Collection<String> getGroupNames(); + /// @return all of the groups in this DataModel. + public Collection<DataModelGroup> getGroups(); + /** + * Get a group by specific name. + * + * @return the DataModelGroup with name if found. Otherwise, null. + */ + public DataModelGroup getGroup(String name); + /** + * Explicitly create a group with name. + * + * @param name the name of the new group. + * @return the created group. + * @throws UniqueNameException if a group with name has already been created. + */ + public DataModelGroup createGroup(String name) throws UniqueNameException; + + // Add Field methods + + /** + * Adds a checkbox field to the parent/containing GUI component of the specified area or the + * current parent/containing GUI component if no area is specified. + * Also creates the GUI-specific component. + * + * @see addField + * @param name the name of the new field. + * @param areaName the name of the area to add this field to. Not required. + * @param groupName the name of the group to add this field to. Not required, though a default + * will be used if not provided. + * @param defaultOn if true, the default value of this check box will be checked. + * @throws UniqueNameException if a field with name has already been added. + */ + public DataModelField<Boolean> addCheckBox( + String name, String areaName, String groupName, boolean defaultOn) + throws UniqueNameException; + /** + * Adds a single-selection drop down field to the parent/containing GUI component of the + * specified area or the current parent/containing GUI component if no area is specified. + * Also creates the GUI-specific component. + * + * @see addField + * @param name the name of the new field. + * @param areaName the name of the area to add this field to. Not required. + * @param groupName the name of the group to add this field to. Not required, though a default + * will be used if not provided. + * @param selectedIndex the element of unorderedOptionLabels to have selected by default. + * @param unorderedOptionLabels the literal items that get displayed as user-selectable + * options. Note: selectedIndex should fall within these bounds, and these should be exactly + * the keys into optionValuesByLabels. + * @param optionValuesByLabels the option label-to-value mapping used to tie user-selected + * options to actual values used by code later on. + * @throws UniqueNameException if a field with name has already been added. + */ + public<T> DataModelField<T> addDropDown( + String name, + String areaName, + String groupName, + int selectedIndex, + Collection<String> unorderedOptionLabels, + Map<String, T> optionValuesByLabels) throws UniqueNameException; + /** + * Adds a single-selection list field to the parent/containing GUI component of the specified + * area or the current parent/containing GUI component if no area is specified. + * Also creates the GUI-specific component. + * + * @see addField + * @param name the name of the new field. + * @param areaName the name of the area to add this field to. Not required. + * @param groupName the name of the group to add this field to. Not required, though a default + * will be used if not provided. + * @param selectedIndex the element of unorderedOptionLabels to have selected by default. + * @param unorderedOptionLabels the literal items that get displayed as user-selectable + * options. Note: selectedIndex should fall within these bounds, and these should be exactly + * the keys into optionValuesByLabels. + * @param optionValuesByLabels the option label-to-value mapping used to tie user-selected + * options to actual values used by code later on. + * @throws UniqueNameException if a field with name has already been added. + */ + public<T> DataModelField<T> addList( + String name, + String areaName, + String groupName, + int selectedIndex, + Collection<String> unorderedOptionLabels, + Map<String, T> optionValuesByLabels) throws UniqueNameException; + /** + * Adds a text field to the parent/containing GUI component of the specified area or the + * current parent/containing GUI component if no area is specified. + * + * @see addField + * @param name the name of the new field. + * @param areaName the name of the area to add this field to. Not required. + * @param groupName the name of the group to add this field to. Not required, though a default + * will be used if not provided. + * @param defaultValue the default value of this text field. + * @param isMultiLined if true, this text field will be multi-lined. Otherwise, it will be + * single-lined. + * @throws UniqueNameException if a field with name has already been added. + */ + public DataModelField<String> addText( + String name, + String areaName, + String groupName, + String defaultValue, + boolean isMultiLined) throws UniqueNameException; + /** + * Adds an already-created field to the area named areaName and group named groupName, both + * if specified. + * Note: It is up to the caller to have added field to the specified area's parent/containing + * GUI component, and the implementing class should verify this. + * + * @param areaName the name of the area to add this field to. Not required. + * @param groupName the name of the group to add this field to. Not required, though a default + * will be used if not provided. + * @throws UniqueNameException if a field with name has already been added. + */ + public<T> void addField(String areaName, String groupName, DataModelField<T> field) + throws UniqueNameException; +} \ No newline at end of file Copied: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/ModelDataSynchronizer.java (from rev 1118, trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/datasynchronizer/ModelDataSynchronizer.java) =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/ModelDataSynchronizer.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/ModelDataSynchronizer.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,12 @@ +package org.cishell.utility.datastructure.datamodel; + +/** + * + */ +public interface ModelDataSynchronizer<T> { + public int updateListenerCode(); + public T value(); + public T synchronizeFromGUI(); + public T synchronizeToGUI(T value); + public T reset(T defaultValue); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/AbstractDataModelArea.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/AbstractDataModelArea.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/AbstractDataModelArea.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,154 @@ +package org.cishell.utility.datastructure.datamodel.area; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.cishell.utility.datastructure.datamodel.exception.ModelStructureException; +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; + +public abstract class AbstractDataModelArea< + BaseGUIComponentType, GUIContainerComponentType extends BaseGUIComponentType> + implements DataModelArea { + private DataModelArea parentArea; + private GUIContainerComponentType parentComponent; + private String name; + + private Map<String, DataModelArea> areas = new HashMap<String, DataModelArea>(); + private Map<String, DataModelField<?>> fields = new HashMap<String, DataModelField<?>>(); + + public AbstractDataModelArea( + DataModelArea parentArea, GUIContainerComponentType parentComponent, String name) { + this.parentArea = parentArea; + this.parentComponent = parentComponent; + this.name = name; + } + + // Misceallaneous methods + + public DataModelArea getParentArea() { + return this.parentArea; + } + + public Object getParentComponent() { + return this.parentComponent; + } + + public GUIContainerComponentType getParentComponentWithType() { + return this.parentComponent; + } + + public String getName() { + return this.name; + } + + // DataModelAreaContainer methods + + public Collection<String> getAreaNames() { + return this.areas.keySet(); + } + + public Collection<DataModelArea> getAreas() { + return this.areas.values(); + } + + public DataModelArea getArea(String name) { + return this.areas.get(name); + } + + public DataModelArea createArea(String name) throws UniqueNameException { + if (getArea(name) != null) { + String exceptionMessage = String.format( + "The area '%s' already exists. All areas must have unique names.", name); + throw new UniqueNameException(exceptionMessage); + } else { + DataModelArea area = internalCreateArea(name); + this.areas.put(name, area); + + return area; + } + } + + public abstract DataModelArea createArea(String name, Object componentForArea) + throws ClassCastException, ModelStructureException, UniqueNameException; + + protected abstract DataModelArea internalCreateArea(String name); + + public void addArea(DataModelArea area) + throws ClassCastException, ModelStructureException, UniqueNameException { + String name = area.getName(); + + if (getArea(name) != null) { + String exceptionMessage = String.format( + "The area '%s' already exists. All areas must have unique names.", name); + throw new UniqueNameException(exceptionMessage); + } else if (area.getParentComponent() != getParentComponent()) { + String exceptionMessage = String.format( + "Tried to manually add area %s to area %s, but parent components do not match.", + name, + getName()); + throw new ModelStructureException(exceptionMessage); + } else { + this.areas.put(name, area); + } + } + + public boolean areaDisposed(String name) { + if (this.areas.containsKey(name)) { + this.areas.remove(name); + + return true; + } else { + return false; + } + } + + public boolean areaDisposed(DataModelArea area) { + return areaDisposed(area.getName()); + } + + // DataModelFieldContainer methods + + public Collection<String> getFieldNames() { + return this.fields.keySet(); + } + + public Collection<DataModelField<?>> getFields() { + return this.fields.values(); + } + + public DataModelField<?> getField(String fieldName) { + return this.fields.get(fieldName); + } + + public<T> void addField(DataModelField<T> field) throws UniqueNameException { + String fieldName = field.getName(); + + if (getField(fieldName) != null) { + String format = + "The field '%s' already exists in this area (%s). " + + "All fields must have unique names."; + String exceptionMessage = String.format( + format, fieldName, this.name); + throw new UniqueNameException(exceptionMessage); + } else { + this.fields.put(fieldName, field); + field.addToContainer(this); + } + } + + public boolean fieldDisposed(String fieldName) { + if (this.fields.containsKey(fieldName)) { + this.fields.remove(fieldName); + + return true; + } else { + return false; + } + } + + public<T> boolean fieldDisposed(DataModelField<T> field) { + return fieldDisposed(field.getName()); + } +} Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/DataModelArea.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/DataModelArea.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/DataModelArea.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,40 @@ +package org.cishell.utility.datastructure.datamodel.area; + +import java.util.Collection; + +import org.cishell.utility.datastructure.datamodel.exception.ModelStructureException; +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; +import org.cishell.utility.datastructure.datamodel.field.DataModelFieldContainer; + +/** + * DataModelArea corresponds to a physical area tied to a DataModel GUI. + * DataModelAreas can contain other DataModelAreas, as well as DataModelFields. + */ +public interface DataModelArea extends DataModelAreaContainer, DataModelFieldContainer { + // Miscellaneous methods + + public DataModelArea getParentArea(); + public Object getParentComponent(); + public String getName(); + + // DataModelAreaContainer methods + + public Collection<String> getAreaNames(); + public Collection<DataModelArea> getAreas(); + public DataModelArea getArea(String name); + public DataModelArea createArea(String name) throws UniqueNameException; + public DataModelArea createArea(String name, Object componentForArea) + throws ClassCastException, ModelStructureException, UniqueNameException; + public boolean areaDisposed(String name); + public boolean areaDisposed(DataModelArea area); + + // DataModelFieldContainer methods + + public Collection<String> getFieldNames(); + public Collection<DataModelField<?>> getFields(); + public DataModelField<?> getField(String fieldName); + public<T> void addField(DataModelField<T> field) throws UniqueNameException; + public boolean fieldDisposed(String fieldName); + public<T> boolean fieldDisposed(DataModelField<T> field); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/DataModelAreaContainer.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/DataModelAreaContainer.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/area/DataModelAreaContainer.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,28 @@ +package org.cishell.utility.datastructure.datamodel.area; + +import java.util.Collection; + +import org.cishell.utility.datastructure.datamodel.exception.ModelStructureException; +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; + +// TODO: addToContainer type stuff +public interface DataModelAreaContainer { + public Collection<String> getAreaNames(); + public Collection<DataModelArea> getAreas(); + public DataModelArea getArea(String name); + public DataModelArea createArea(String name) throws UniqueNameException; + /** + * @throws ClassCastException if componentForArea is not of the proper GUI container type. + * @throws ModelStructureException if componentForArea's parent is not this area's internal + * GUI container. + * @throws UniqueNameException if an area with name already exists. + */ + public DataModelArea createArea(String name, Object componentForArea) + throws ClassCastException, ModelStructureException, UniqueNameException; + public void addArea(DataModelArea area) + throws ClassCastException, ModelStructureException, UniqueNameException; + + //TODO: why is this returning boolean? + public boolean areaDisposed(String name); + public boolean areaDisposed(DataModelArea area); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ModelStructureException.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ModelStructureException.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ModelStructureException.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,21 @@ +package org.cishell.utility.datastructure.datamodel.exception; + +public class ModelStructureException extends Exception { + private static final long serialVersionUID = 1L; + + public ModelStructureException() { + super(); + } + + public ModelStructureException(String arg0) { + super(arg0); + } + + public ModelStructureException(Throwable arg0) { + super(arg0); + } + + public ModelStructureException(String arg0, Throwable arg1) { + super(arg0, arg1); + } +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ModelValidationException.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ModelValidationException.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/ModelValidationException.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,21 @@ +package org.cishell.utility.datastructure.datamodel.exception; + +public class ModelValidationException extends Exception { + private static final long serialVersionUID = 1L; + + public ModelValidationException() { + super(); + } + + public ModelValidationException(String arg0) { + super(arg0); + } + + public ModelValidationException(Throwable arg0) { + super(arg0); + } + + public ModelValidationException(String arg0, Throwable arg1) { + super(arg0, arg1); + } +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/UniqueNameException.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/UniqueNameException.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/exception/UniqueNameException.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,21 @@ +package org.cishell.utility.datastructure.datamodel.exception; + +public class UniqueNameException extends Exception { + private static final long serialVersionUID = 1L; + + public UniqueNameException() { + super(); + } + + public UniqueNameException(String arg0) { + super(arg0); + } + + public UniqueNameException(Throwable arg0) { + super(arg0); + } + + public UniqueNameException(String arg0, Throwable arg1) { + super(arg0, arg1); + } +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelField.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelField.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelField.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,29 @@ +package org.cishell.utility.datastructure.datamodel.field; + +import java.util.Collection; + +import org.cishell.utility.datastructure.datamodel.DataModel; + +/** + * DataModelFields are the meat of DataModels. + * They contain the actual data and internal behavior/user-interaction logic. + */ +public interface DataModelField<ValueType> { + public Collection<DataModelFieldContainer> getContainers(); + public boolean addToContainer(DataModelFieldContainer container); + + public String getName(); + public Object getParentComponent(); + public ValueType getDefaultValue(); + public ValueType getPreviousValue(); + public ValueType getValue(); + public ValueType setValue(ValueType value); + public ValueType reset(); + + public void addValidationRule( + FieldValidationRule<ValueType> validator, boolean validateNow, DataModel model); + public void addValidationAction(FieldValidationAction<ValueType> validationAction); + public void validate(DataModel model); + + public void dispose(); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelFieldContainer.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelFieldContainer.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelFieldContainer.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,14 @@ +package org.cishell.utility.datastructure.datamodel.field; + +import java.util.Collection; + +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; + +public interface DataModelFieldContainer { + public Collection<String> getFieldNames(); + public Collection<DataModelField<?>> getFields(); + public DataModelField<?> getField(String fieldName); + public<T> void addField(DataModelField<T> field) throws UniqueNameException; + public boolean fieldDisposed(String fieldName); + public<T> boolean fieldDisposed(DataModelField<T> field); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,12 @@ +package org.cishell.utility.datastructure.datamodel.field; + +import java.util.Collection; + +import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; + +public interface FieldValidationAction<ValueType> { + public void fieldDoesValidate(DataModelField<ValueType> field); + public void fieldDoesNotValidate( + DataModelField<ValueType> field, Collection<ModelValidationException> reasons); + public void fieldDisposed(DataModelField<ValueType> field); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,10 @@ +package org.cishell.utility.datastructure.datamodel.field; + +import org.cishell.utility.datastructure.datamodel.DataModel; +import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; + +public interface FieldValidationRule<ValueType> { + public void validateField(DataModelField<ValueType> field, DataModel model) + throws ModelValidationException; + public void fieldDisposed(DataModelField<ValueType> field); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/BasicModelGroup.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/BasicModelGroup.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/BasicModelGroup.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,68 @@ +package org.cishell.utility.datastructure.datamodel.group; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; + +public class BasicModelGroup implements DataModelGroup { + private String name; + private Map<String, DataModelField<?>> fields = new HashMap<String, DataModelField<?>>(); + + public BasicModelGroup(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public Collection<String> getFieldNames() { + return this.fields.keySet(); + } + + public Collection<DataModelField<?>> getFields() { + Collection<DataModelField<?>> fields = new ArrayList<DataModelField<?>>(); + fields.addAll(this.fields.values()); + + return fields; + } + + public DataModelField<?> getField(String name) { + return this.fields.get(name); + } + + public<T> void addField(DataModelField<T> field) + throws ClassCastException, UniqueNameException { + String fieldName = field.getName(); + + if (this.fields.containsKey(fieldName)) { + String format = + "The field '%s' already exists in this group (%s). " + + "All fields must have unique names."; + String exceptionMessage = String.format( + format, fieldName, this.name); + throw new UniqueNameException(exceptionMessage); + } + + this.fields.put(fieldName, field); + field.addToContainer(this); + } + + public boolean fieldDisposed(String fieldName) { + if (this.fields.containsKey(fieldName)) { + this.fields.remove(fieldName); + + return true; + } else { + return false; + } + } + + public<T> boolean fieldDisposed(DataModelField<T> field) { + return fieldDisposed(field.getName()); + } +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/DataModelGroup.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/DataModelGroup.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/group/DataModelGroup.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,24 @@ +package org.cishell.utility.datastructure.datamodel.group; + +import java.util.Collection; + +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; +import org.cishell.utility.datastructure.datamodel.field.DataModelFieldContainer; + +/** + * Model groups are organizational structures for related DataModelFields. + * They are not tied to the physical structure of a GUI. + * Anything that wishes to retrieve data from a DataModel can ask for ModelGroups. + */ +public interface DataModelGroup extends DataModelFieldContainer { + public String getName(); + + public Collection<String> getFieldNames(); + public Collection<DataModelField<?>> getFields(); + public DataModelField<?> getField(String fieldName); + public<T> void addField(DataModelField<T> field) + throws ClassCastException, UniqueNameException; + public boolean fieldDisposed(String fieldName); + public<T> boolean fieldDisposed(DataModelField<T> field); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/gui/AbstractGUIDataModel.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/gui/AbstractGUIDataModel.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/gui/AbstractGUIDataModel.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,158 @@ +package org.cishell.utility.datastructure.datamodel.gui; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.cishell.utility.datastructure.datamodel.DataModel; +import org.cishell.utility.datastructure.datamodel.area.DataModelArea; +import org.cishell.utility.datastructure.datamodel.exception.ModelStructureException; +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; +import org.cishell.utility.datastructure.datamodel.group.BasicModelGroup; +import org.cishell.utility.datastructure.datamodel.group.DataModelGroup; + +/// TODO: Document this. +/// TODO: Figure out a way to generically express styles for both widgets and areas. +public abstract class AbstractGUIDataModel< + BaseGUIComponentType, GUIContainerComponentType extends BaseGUIComponentType> + implements DataModel { + private Map<String, DataModelArea> areas = new HashMap<String, DataModelArea>(); + private Map<String, DataModelGroup> groups = new HashMap<String, DataModelGroup>(); + private GUIContainerComponentType currentParentComponent; + + public AbstractGUIDataModel() { + } + + // Miscellaneous methods + + @SuppressWarnings("unchecked") + public void setCurrentParentComponent(Object currentParentComponent) + throws ClassCastException { + this.currentParentComponent = (GUIContainerComponentType) currentParentComponent; + } + + public GUIContainerComponentType getCurrentParentComponent() { + return this.currentParentComponent; + } + + // DataModelAreaContainer methods (via DataModel) + + public Collection<String> getAreaNames() { + return this.areas.keySet(); + } + + public Collection<DataModelArea> getAreas() { + return this.areas.values(); + } + + public DataModelArea getArea(String name) { + return this.areas.get(name); + } + + public DataModelArea createArea(String name) throws UniqueNameException { + if (getArea(name) != null) { + String exceptionMessage = String.format( + "The area '%s' already exists. All areas must have unique names.", name); + throw new UniqueNameException(exceptionMessage); + } else { + DataModelArea area = createGUISpecificArea(name); + this.areas.put(name, area); + + return area; + } + } + + public abstract DataModelArea createArea(String name, Object componentForArea) + throws ClassCastException, ModelStructureException, UniqueNameException; + + protected abstract DataModelArea createGUISpecificArea(String name); + + public void addArea(DataModelArea area) + throws ClassCastException, ModelStructureException, UniqueNameException { + String name = area.getName(); + + if (getArea(name) != null) { + String exceptionMessage = String.format( + "The area '%s' already exists. All areas must have unique names.", name); + throw new UniqueNameException(exceptionMessage); + } else { + this.areas.put(name, area); + } + } + + public boolean areaDisposed(String name) { + if (this.areas.containsKey(name)) { + this.areas.remove(name); + + return true; + } else { + return false; + } + } + + public boolean areaDisposed(DataModelArea area) { + return areaDisposed(area.getName()); + } + + // Group methods + + public Collection<String> getGroupNames() { + return this.groups.keySet(); + } + + public Collection<DataModelGroup> getGroups() { + return this.groups.values(); + } + + public DataModelGroup getGroup(String name) { + return this.groups.get(name); + } + + public DataModelGroup createGroup(String name) throws UniqueNameException { + if (getGroup(name) != null) { + String exceptionMessage = String.format( + "The group '%s' already exists. All groups must have unique names.", name); + throw new UniqueNameException(exceptionMessage); + } else { + DataModelGroup group = new BasicModelGroup(name); + this.groups.put(name, group); + + return group; + } + } + + // Add Field methods + + public abstract DataModelField<Boolean> addCheckBox( + String name, + String areaName, + String groupName, + boolean defaultOn) throws UniqueNameException; + + public abstract<T> DataModelField<T> addDropDown( + String name, + String areaName, + String groupName, + int selectedIndex, + Collection<String> unorderedOptionLabels, + Map<String, T> optionValuesByLabels) throws UniqueNameException; + + public abstract<T> DataModelField<T> addList( + String name, + String areaName, + String groupName, + int selectedIndex, + Collection<String> unorderedOptionLabels, + Map<String, T> optionValuesByLabels) throws UniqueNameException; + + public abstract DataModelField<String> addText( + String name, + String areaName, + String groupName, + String defaultValue, + boolean isMultiLined) throws UniqueNameException; + + public abstract<T> void addField(String areaName, String groupName, DataModelField<T> field) + throws UniqueNameException; +} \ No newline at end of file Modified: trunk/core/org.cishell.utility.swt/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.utility.swt/META-INF/MANIFEST.MF 2010-08-23 18:06:40 UTC (rev 1127) +++ trunk/core/org.cishell.utility.swt/META-INF/MANIFEST.MF 2010-08-23 18:07:46 UTC (rev 1128) @@ -8,7 +8,13 @@ org.eclipse.core.runtime Import-Package: com.google.common.collect, org.cishell.utilities, - org.cishell.utility.datastructure + org.cishell.utility.datastructure, + org.cishell.utility.datastructure.datamodel, + org.cishell.utility.datastructure.datamodel.area, + org.cishell.utility.datastructure.datamodel.exception, + org.cishell.utility.datastructure.datamodel.field, + org.cishell.utility.datastructure.datamodel.group, + org.cishell.utility.datastructure.datamodel.gui Export-Package: org.cishell.utility.swt, org.cishell.utility.swt.model, org.cishell.utility.swt.model.datasynchronizer Modified: trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/ExpandableComponentWidget.java =================================================================== --- trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/ExpandableComponentWidget.java 2010-08-23 18:06:40 UTC (rev 1127) +++ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/ExpandableComponentWidget.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -65,7 +65,8 @@ return 1; } - public T addComponent(int style, Map<String, Object> arguments) { + public T addComponent(int style, Map<String, Object> arguments) + throws WidgetConstructionException { // TODO: Fix this terrible hack? if (this.components.size() == 0) { for (Label columnLabel : this.columnLabels) { @@ -75,7 +76,12 @@ final int componentCount = this.components.size(); T component = this.componentFactory.constructWidget( - this, this.scrolledAreaGrid, style, arguments, componentCount, this.uniqueComponentCount); + this, + this.scrolledAreaGrid, + style, + arguments, + componentCount, + this.uniqueComponentCount); this.uniqueComponentCount++; fixSize(); Modified: trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/ScrolledComponentFactory.java =================================================================== --- trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/ScrolledComponentFactory.java 2010-08-23 18:06:40 UTC (rev 1127) +++ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/ScrolledComponentFactory.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -9,7 +9,7 @@ int style, Map<String, Object> arguments, int index, - int uniqueIndex); + int uniqueIndex) throws WidgetConstructionException; public void reindexComponent(T component, int newIndex); } \ No newline at end of file Added: trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/WidgetConstructionException.java =================================================================== --- trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/WidgetConstructionException.java (rev 0) +++ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/WidgetConstructionException.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,21 @@ +package org.cishell.utility.swt; + +public class WidgetConstructionException extends Exception { + private static final long serialVersionUID = 1L; + + public WidgetConstructionException() { + super(); + } + + public WidgetConstructionException(String arg0) { + super(arg0); + } + + public WidgetConstructionException(Throwable arg0) { + super(arg0); + } + + public WidgetConstructionException(String arg0, Throwable arg1) { + super(arg0, arg1); + } +} \ No newline at end of file Deleted: trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModel.java =================================================================== --- trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModel.java 2010-08-23 18:06:40 UTC (rev 1127) +++ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModel.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -1,190 +0,0 @@ -package org.cishell.utility.swt.model; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import org.cishell.utility.swt.model.datasynchronizer.CheckBoxDataSynchronizer; -import org.cishell.utility.swt.model.datasynchronizer.DropDownDataSynchronizer; -import org.cishell.utility.swt.model.datasynchronizer.ModelDataSynchronizer; -import org.cishell.utility.swt.model.datasynchronizer.SingleListSelectionDataSynchronizer; -import org.cishell.utility.swt.model.datasynchronizer.TextDataSynchronizer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.List; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.Widget; - -public class GUIModel { - private Map<String, GUIModelGroup> groups = new HashMap<String, GUIModelGroup>(); - - public GUIModel() { - } - - public Collection<String> getGroupNames() { - return this.groups.keySet(); - } - - public Collection<GUIModelGroup> getGroups() { - return this.groups.values(); - } - - public GUIModelGroup getGroup(String name) { - if (!this.groups.containsKey(name)) { - GUIModelGroup newGroup = new GUIModelGroup(name); - this.groups.put(name, newGroup); - - return newGroup; - } else { - return this.groups.get(name); - } - } - - public GUIModelField<Boolean, Button, CheckBoxDataSynchronizer> addCheckBox( - String groupName, String name, boolean on, Composite parent, int style) { - Button checkBox = new Button(parent, style | SWT.CHECK); - CheckBoxDataSynchronizer dataSynchronizer = new CheckBoxDataSynchronizer(checkBox, on); - GUIModelField<Boolean, Button, CheckBoxDataSynchronizer> field = - new GUIModelField<Boolean, Button, CheckBoxDataSynchronizer>( - name, on, checkBox, dataSynchronizer); - addField(groupName, field); - - return field; - } - - public GUIModelField<String, Combo, DropDownDataSynchronizer> addDropDown( - String groupName, - String name, - int selectedIndex, - Collection<String> unorderedOptionLabels, - Map<String, String> optionValuesByLabels, - Composite parent, - int style) { - java.util.List<String> orderedOptionLabels = new ArrayList<String>(unorderedOptionLabels); - Combo dropDown = new Combo(parent, style | SWT.DROP_DOWN); - DropDownDataSynchronizer dataSynchronizer = new DropDownDataSynchronizer( - dropDown, selectedIndex, orderedOptionLabels, optionValuesByLabels); - GUIModelField<String, Combo, DropDownDataSynchronizer> field = - new GUIModelField<String, Combo, DropDownDataSynchronizer>( - name, - optionValuesByLabels.get(orderedOptionLabels.get(selectedIndex)), - dropDown, - dataSynchronizer); - addField(groupName, field); - - return field; - } - - // TODO: addMultiSelectionDropDown - - // TODO: Test this out. - // TODO: Make it so the build works with this stuff. -// public GUIModelField< -// org.joda.time.DateTime, org.eclipse.swt.widgets.DateTime, DateDataSynchronizer> -// addDate(String name, org.joda.time.DateTime date, Composite parent, int style) { -// org.eclipse.swt.widgets.DateTime dateSelector = -// new org.eclipse.swt.widgets.DateTime(parent, style | SWT.DATE); -// DateDataSynchronizer dataSynchronizer = new DateDataSynchronizer(dateSelector, date); -// GUIModelField< -// org.joda.time.DateTime, org.eclipse.swt.widgets.DateTime, DateDataSynchronizer> field = -// new GUIModelField< -// org.joda.time.DateTime, -// org.eclipse.swt.widgets.DateTime, -// DateDataSynchronizer>( -// name, date, dateSelector, dataSynchronizer); -// addField(field); -// -// return field; -// } - - // TODO: Test this out. -// public GUIModelField< -// org.joda.time.DateTime, org.eclipse.swt.widgets.DateTime, TimeDataSynchronizer> -// addTime(String name, org.joda.time.DateTime time, Composite parent, int style) { -// org.eclipse.swt.widgets.DateTime timeSelector = -// new org.eclipse.swt.widgets.DateTime(parent, style | SWT.TIME); -// TimeDataSynchronizer dataSynchronizer = new TimeDataSynchronizer(timeSelector, time); -// GUIModelField< -// org.joda.time.DateTime, org.eclipse.swt.widgets.DateTime, TimeDataSynchronizer> field = -// new GUIModelField< -// org.joda.time.DateTime, -// org.eclipse.swt.widgets.DateTime, -// TimeDataSynchronizer>( -// name, time, timeSelector, dataSynchronizer); -// addField(field); -// -// return field; -// } - - // TODO: addCalendar - - // TODO: Test this out. - public GUIModelField<String, List, SingleListSelectionDataSynchronizer> addList( - String groupName, - String name, - int selectedIndex, - Collection<String> unorderedOptionLabels, - Map<String, String> optionValuesByLabels, - Composite parent, - int style) { - java.util.List<String> orderedOptionLabels = new ArrayList<String>(unorderedOptionLabels); - List list = new List(parent, style | SWT.SINGLE); - SingleListSelectionDataSynchronizer dataSynchronizer = - new SingleListSelectionDataSynchronizer( - list, selectedIndex, orderedOptionLabels, optionValuesByLabels); - GUIModelField<String, List, SingleListSelectionDataSynchronizer> field = - new GUIModelField<String, List, SingleListSelectionDataSynchronizer>( - name, list.getItem(selectedIndex), list, dataSynchronizer); - addField(groupName, field); - - return field; - } - - // TODO: addMultiSelectionList - // TODO: addProgressBar - // TODO: addSash? - // TODO: addSlider - // TODO: addScale - // TODO: addSpinner - // TODO: addStyledText - - public GUIModelField<String, Text, TextDataSynchronizer> addText( - String groupName, - String name, - String value, - boolean isMultiLined, - Composite parent, - int style) { - if (isMultiLined) { - style = style | SWT.MULTI; - } else { - style = style | SWT.SINGLE; - } - - Text text = new Text(parent, style); - TextDataSynchronizer dataSynchronizer = new TextDataSynchronizer(text, value); - GUIModelField<String, Text, TextDataSynchronizer> field = - new GUIModelField<String, Text, TextDataSynchronizer>( - name, value, text, dataSynchronizer); - addField(groupName, field); - - return field; - } - - public<T> void addField( - String groupName, - GUIModelField<T, ? extends Widget, ? extends ModelDataSynchronizer<?>> field) { - GUIModelGroup group = getGroup(groupName); - group.addField(field); - } - - public<T> void removeField( - GUIModelField<T, ? extends Widget, ? extends ModelDataSynchronizer<?>> field) { - for (GUIModelGroup group : this.groups.values()) { - group.removeField(field); - } - } -} \ No newline at end of file Deleted: trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModelField.java =================================================================== --- trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModelField.java 2010-08-23 18:06:40 UTC (rev 1127) +++ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModelField.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -1,65 +0,0 @@ -package org.cishell.utility.swt.model; - -import org.cishell.utility.swt.model.datasynchronizer.ModelDataSynchronizer; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Widget; - -public class GUIModelField<T, U extends Widget, V extends ModelDataSynchronizer<T>> { - private String name; - private T defaultValue; - private T previousValue; - private T value; - private U widget; - private V dataSynchronizer; - - public GUIModelField( - String name, - T defaultValue, - U widget, - V dataSynchronizer) { - this.name = name; - this.defaultValue = defaultValue; - this.value = this.defaultValue; - this.widget = widget; - this.dataSynchronizer = dataSynchronizer; - - this.widget.addListener(this.dataSynchronizer.swtUpdateListenerCode(), new Listener() { - public void handleEvent(Event event) { - if (event.type == GUIModelField.this.dataSynchronizer.swtUpdateListenerCode()) { - GUIModelField.this.previousValue = GUIModelField.this.value; - GUIModelField.this.value = - GUIModelField.this.dataSynchronizer.synchronizeFromGUI(); - } - } - }); - } - - public String getName() { - return this.name; - } - - public T getPreviousValue() { - return this.previousValue; - } - - public T getValue() { - return this.value; - } - - public U getWidget() { - return this.widget; - } - - public V getDataSynchronizer() { - return this.dataSynchronizer; - } - - public void setValue(T value) { - this.value = this.dataSynchronizer.synchronizeToGUI(value); - } - - public void reset() { - this.value = this.dataSynchronizer.reset(this.defaultValue); - } -} \ No newline at end of file Deleted: trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModelGroup.java =================================================================== --- trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModelGroup.java 2010-08-23 18:06:40 UTC (rev 1127) +++ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModelGroup.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -1,57 +0,0 @@ -package org.cishell.utility.swt.model; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import org.cishell.utility.swt.model.datasynchronizer.ModelDataSynchronizer; -import org.eclipse.swt.widgets.Widget; - -public class GUIModelGroup { - private String name; - private Map<String, GUIModelField<?, ? extends Widget, ? extends ModelDataSynchronizer<?>>> - inputFieldsByName = new HashMap< - String, GUIModelField<?, ? extends Widget, ? extends ModelDataSynchronizer<?>>>(); - - public GUIModelGroup(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } - - public Collection<String> getFieldNames() { - return this.inputFieldsByName.keySet(); - } - - public Collection< - GUIModelField<?, ? extends Widget, ? extends ModelDataSynchronizer<?>>> getFields() { - return this.inputFieldsByName.values(); - } - - public GUIModelField< - ?, ? extends Widget, ? extends ModelDataSynchronizer<?>> getField(String name) { - return this.inputFieldsByName.get(name); - } - - public<T> void addField( - GUIModelField<T, ? extends Widget, ? extends ModelDataSynchronizer<?>> field) { - String fieldName = field.getName(); - - if (this.inputFieldsByName.containsKey(fieldName)) { - String exceptionMessage = - "A field with the name \"" + fieldName + "\" already exists. Unable to continue."; - throw new ModelFieldException(exceptionMessage); - } - - this.inputFieldsByName.put(fieldName, field); - } - - public<T> void removeField( - GUIModelField<T, ? extends Widget, ? extends ModelDataSynchronizer<?>> field) { - if (this.inputFieldsByName.containsValue(field)) { - this.inputFieldsByName.remove(field.getName()); - } - } -} \ No newline at end of file Copied: trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModel.java (from rev 1118, trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/GUIModel.java) =================================================================== --- trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModel.java (rev 0) +++ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModel.java 2010-08-23 18:07:46 UTC (rev 1128) @@ -0,0 +1,237 @@ +package org.cishell.utility.swt.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import org.cishell.utilities.StringUtilities; +import org.cishell.utility.datastructure.datamodel.area.DataModelArea; +import org.cishell.utility.datastructure.datamodel.exception.ModelStructureException; +import org.cishell.utility.datastructure.datamodel.exception.UniqueNameException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; +import org.cishell.utility.datastructure.datamodel.group.DataModelGroup; +import org.cishell.utility.datastructure.datamodel.gui.AbstractGUIDataModel; +import org.cishell.utility.swt.model.datasynchronizer.CheckBoxDataSynchronizer; +import org.cishell.utility.swt.model.datasynchronizer.DropDownDataSynchronizer; +import org.cishell.utility.swt.model.datasynchronizer.SingleListSelectionDataSynchronizer; +import org.cishell.utility.swt.model.datasynchronizer.TextDataSynchronizer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; + +public class SWTModel extends AbstractGUIDataModel<Widget, Composite> { + private int newAreaStyle; + + public SWTModel(int newAreaStyle) { + this.newAreaStyle = newAreaStyle; + } + + @Override + public DataModelArea createArea(String name, Object componentForArea) + throws ClassCastException, ModelStructureException, UniqueNameException { + if (getArea(name) != null) { + String exceptionMessage = String.format( + "The area '%s' already exists. All areas must have unique names.", name); + throw new UniqueNameException(exceptionMessage); + } else { + DataModelArea area = new SWTModelArea( + null, + null, + name, + (Composite) com... [truncated message content] |
From: <pat...@us...> - 2010-08-26 17:58:25
|
Revision: 1129 http://cishell.svn.sourceforge.net/cishell/?rev=1129&view=rev Author: pataphil Date: 2010-08-26 17:58:18 +0000 (Thu, 26 Aug 2010) Log Message: ----------- * Restructured how validation works. * Not reviewed. Modified Paths: -------------- trunk/core/org.cishell.utility.datastructure/META-INF/MANIFEST.MF trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelField.java trunk/core/org.cishell.utility.swt/META-INF/MANIFEST.MF trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModelField.java Added Paths: ----------- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/BasicFieldValidator.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/EmptyTextFieldValidationRule.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationAction.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationRule.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidator.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/UniqueValueValidationRule.java trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/field/ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/field/validation/ Removed Paths: ------------- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java trunk/core/org.cishell.utility.swt/src/org/cishell/utilities/swt/ Modified: trunk/core/org.cishell.utility.datastructure/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.utility.datastructure/META-INF/MANIFEST.MF 2010-08-23 18:07:46 UTC (rev 1128) +++ trunk/core/org.cishell.utility.datastructure/META-INF/MANIFEST.MF 2010-08-26 17:58:18 UTC (rev 1129) @@ -9,5 +9,8 @@ org.cishell.utility.datastructure.datamodel.area, org.cishell.utility.datastructure.datamodel.exception, org.cishell.utility.datastructure.datamodel.field, + org.cishell.utility.datastructure.datamodel.field.validation, org.cishell.utility.datastructure.datamodel.group, org.cishell.utility.datastructure.datamodel.gui +Import-Package: com.google.common.collect, + org.cishell.utilities Modified: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelField.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelField.java 2010-08-23 18:07:46 UTC (rev 1128) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/DataModelField.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -2,7 +2,8 @@ import java.util.Collection; -import org.cishell.utility.datastructure.datamodel.DataModel; +import org.cishell.utility.datastructure.datamodel.field.validation.FieldValidationAction; +import org.cishell.utility.datastructure.datamodel.field.validation.FieldValidator; /** * DataModelFields are the meat of DataModels. @@ -20,10 +21,15 @@ public ValueType setValue(ValueType value); public ValueType reset(); - public void addValidationRule( - FieldValidationRule<ValueType> validator, boolean validateNow, DataModel model); - public void addValidationAction(FieldValidationAction<ValueType> validationAction); - public void validate(DataModel model); + /// Add a validator to that should validate this field. + public void addValidator(FieldValidator<ValueType> validator); + /// Add validators that should be considered when performing validation actions. + public void addOtherValidators(Collection<FieldValidator<ValueType>> otherValidators); + /// Add an action to perform, given if everything validated or not. + public void addValidationAction(FieldValidationAction action); + /// Notify everything that has added this field that this field has been disposed. public void dispose(); + /// Has this field been disposed? + public boolean isDisposed(); } \ No newline at end of file Deleted: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java 2010-08-23 18:07:46 UTC (rev 1128) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -1,12 +0,0 @@ -package org.cishell.utility.datastructure.datamodel.field; - -import java.util.Collection; - -import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; - -public interface FieldValidationAction<ValueType> { - public void fieldDoesValidate(DataModelField<ValueType> field); - public void fieldDoesNotValidate( - DataModelField<ValueType> field, Collection<ModelValidationException> reasons); - public void fieldDisposed(DataModelField<ValueType> field); -} \ No newline at end of file Deleted: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java 2010-08-23 18:07:46 UTC (rev 1128) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -1,10 +0,0 @@ -package org.cishell.utility.datastructure.datamodel.field; - -import org.cishell.utility.datastructure.datamodel.DataModel; -import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; - -public interface FieldValidationRule<ValueType> { - public void validateField(DataModelField<ValueType> field, DataModel model) - throws ModelValidationException; - public void fieldDisposed(DataModelField<ValueType> field); -} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/BasicFieldValidator.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/BasicFieldValidator.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/BasicFieldValidator.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -0,0 +1,69 @@ +package org.cishell.utility.datastructure.datamodel.field.validation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; + +import org.cishell.utility.datastructure.datamodel.DataModel; +import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; + +public class BasicFieldValidator<ValueType> implements FieldValidator<ValueType> { + private String baseFieldName; + private Collection<DataModelField<ValueType>> fieldsToValidate = + new HashSet<DataModelField<ValueType>>(); + private Collection<FieldValidationRule<ValueType>> rules = + new HashSet<FieldValidationRule<ValueType>>(); + + public BasicFieldValidator(String baseFieldName) { + this.baseFieldName = baseFieldName; + } + + public void addFieldToValidate(DataModelField<ValueType> field) { + this.fieldsToValidate.add(field); + } + + public void addValidationRule(FieldValidationRule<ValueType> rule) { + this.rules.add(rule); + } + + public Collection<String> runValidation(DataModel model) { + Collection<String> errorMessages = new ArrayList<String>(); + + for (DataModelField<ValueType> field : this.fieldsToValidate) { + String errorHeader = String.format( + "(%s%s, %s): ", this.baseFieldName, field.getName(), field.getValue().toString()); + + for (FieldValidationRule<ValueType> rule : this.rules) { + try { + rule.validateField(field, model); + } catch (ModelValidationException e) { + String errorMessage = errorHeader + e.getMessage(); + errorMessages.add(errorMessage); + } + } + } + + return errorMessages; + } + + public void fieldUpdated(DataModelField<ValueType> field) { + for (FieldValidationRule<ValueType> rule : this.rules) { + rule.fieldUpdated(field); + } + } + + public void fieldsUpdated(Collection<DataModelField<ValueType>> fields) { + for (FieldValidationRule<ValueType> rule : this.rules) { + rule.fieldsUpdated(fields); + } + } + + public void fieldDisposed(DataModelField<ValueType> field) { + for (FieldValidationRule<ValueType> rule : this.rules) { + rule.fieldDisposed(field); + } + + this.fieldsToValidate.remove(field); + } +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/EmptyTextFieldValidationRule.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/EmptyTextFieldValidationRule.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/EmptyTextFieldValidationRule.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -0,0 +1,27 @@ +package org.cishell.utility.datastructure.datamodel.field.validation; + +import java.util.Collection; + +import org.cishell.utilities.StringUtilities; +import org.cishell.utility.datastructure.datamodel.DataModel; +import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; + +public class EmptyTextFieldValidationRule implements FieldValidationRule<String> { + public void validateField(DataModelField<String> field, DataModel model) + throws ModelValidationException { + if (StringUtilities.isNull_Empty_OrWhitespace(field.getValue())) { + String exceptionMessage = "Field may not be empty."; + throw new ModelValidationException(exceptionMessage); + } + } + + public void fieldUpdated(DataModelField<String> field) { + } + + public void fieldsUpdated(Collection<DataModelField<String>> fields) { + } + + public void fieldDisposed(DataModelField<String> field) { + } +} \ No newline at end of file Copied: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationAction.java (from rev 1128, trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationAction.java) =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationAction.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationAction.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -0,0 +1,8 @@ +package org.cishell.utility.datastructure.datamodel.field.validation; + +import java.util.Collection; + +public interface FieldValidationAction { + public void doesValidate(); + public void doesNotValidate(Collection<String> errorMessages); +} \ No newline at end of file Property changes on: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationAction.java ___________________________________________________________________ Added: svn:mergeinfo + Copied: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationRule.java (from rev 1128, trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/FieldValidationRule.java) =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationRule.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationRule.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -0,0 +1,16 @@ +package org.cishell.utility.datastructure.datamodel.field.validation; + +import java.util.Collection; + +import org.cishell.utility.datastructure.datamodel.DataModel; +import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; + +public interface FieldValidationRule<ValueType> { + public void validateField(DataModelField<ValueType> field, DataModel model) + throws ModelValidationException; + /// Update any internal states as necessary. + public void fieldUpdated(DataModelField<ValueType> field); + public void fieldsUpdated(Collection<DataModelField<ValueType>> fields); + public void fieldDisposed(DataModelField<ValueType> field); +} \ No newline at end of file Property changes on: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidationRule.java ___________________________________________________________________ Added: svn:mergeinfo + Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidator.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidator.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/FieldValidator.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -0,0 +1,26 @@ +package org.cishell.utility.datastructure.datamodel.field.validation; + +import java.util.Collection; + +import org.cishell.utility.datastructure.datamodel.DataModel; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; + +/** + * FieldValidators potentially validate multiple fields all in one batch. + * Fields may need multiple FieldValidators if they belong to multiple groupings of + * validation rules ({@link FieldValidationRule}). + */ +public interface FieldValidator<ValueType> { + /// Add a field to perform validation on. + public void addFieldToValidate(DataModelField<ValueType> field); + /// Add a validation rule that this validator should use for validation. + public void addValidationRule(FieldValidationRule<ValueType> rule); + /// Update any internal states as necessary. + public void fieldUpdated(DataModelField<ValueType> field); + /// Update any internal states as necessary. + public void fieldsUpdated(Collection<DataModelField<ValueType>> fields); + /// Perform validation on all fields added for validation. + public Collection<String> runValidation(DataModel model); + /// Called by the field when the field has been disposed. + public void fieldDisposed(DataModelField<ValueType> field); +} \ No newline at end of file Added: trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/UniqueValueValidationRule.java =================================================================== --- trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/UniqueValueValidationRule.java (rev 0) +++ trunk/core/org.cishell.utility.datastructure/src/org/cishell/utility/datastructure/datamodel/field/validation/UniqueValueValidationRule.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -0,0 +1,57 @@ +package org.cishell.utility.datastructure.datamodel.field.validation; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.cishell.utilities.MapUtilities; +import org.cishell.utilities.StringUtilities; +import org.cishell.utility.datastructure.datamodel.DataModel; +import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; +import org.cishell.utility.datastructure.datamodel.field.DataModelField; + +public class UniqueValueValidationRule<ValueType> implements FieldValidationRule<ValueType> { + private String baseFieldName; + private Map<String, ValueType> fieldValuesByNames = new HashMap<String, ValueType>(); +// private Multimap<ValueType, String> fieldNamesByValues = HashMultimap.create(); + + public UniqueValueValidationRule(String baseFieldName) { + this.baseFieldName = baseFieldName; + } + + public void validateField(DataModelField<ValueType> field, DataModel model) + throws ModelValidationException { + String fieldName = field.getName(); + ValueType fieldValue = field.getValue(); + Collection<String> fieldNameForFiltering = Arrays.asList(fieldName); + @SuppressWarnings("unchecked") + Collection<ValueType> fieldValueForFiltering = Arrays.asList(fieldValue); + + this.fieldValuesByNames.put(fieldName, fieldValue); + Collection<String> namesOfFieldsWithValue = MapUtilities.getValidKeysOfTypesInMap( + this.fieldValuesByNames, fieldValueForFiltering, fieldNameForFiltering); + + if (namesOfFieldsWithValue.size() > 0) { + String exceptionMessage = String.format( + "Field's value must be identical. Matches %sfields: [%s]", + this.baseFieldName, + StringUtilities.implodeItems(namesOfFieldsWithValue, ", ")); + throw new ModelValidationException(exceptionMessage); + } + } + + public void fieldUpdated(DataModelField<ValueType> field) { + this.fieldValuesByNames.put(field.getName(), field.getValue()); + } + + public void fieldsUpdated(Collection<DataModelField<ValueType>> fields) { + for (DataModelField<ValueType> field : fields) { + fieldUpdated(field); + } + } + + public void fieldDisposed(DataModelField<ValueType> field) { + this.fieldValuesByNames.remove(field.getName()); + } +} \ No newline at end of file Modified: trunk/core/org.cishell.utility.swt/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.utility.swt/META-INF/MANIFEST.MF 2010-08-23 18:07:46 UTC (rev 1128) +++ trunk/core/org.cishell.utility.swt/META-INF/MANIFEST.MF 2010-08-26 17:58:18 UTC (rev 1129) @@ -13,6 +13,7 @@ org.cishell.utility.datastructure.datamodel.area, org.cishell.utility.datastructure.datamodel.exception, org.cishell.utility.datastructure.datamodel.field, + org.cishell.utility.datastructure.datamodel.field.validation, org.cishell.utility.datastructure.datamodel.group, org.cishell.utility.datastructure.datamodel.gui Export-Package: org.cishell.utility.swt, Modified: trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModelField.java =================================================================== --- trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModelField.java 2010-08-23 18:07:46 UTC (rev 1128) +++ trunk/core/org.cishell.utility.swt/src/org/cishell/utility/swt/model/SWTModelField.java 2010-08-26 17:58:18 UTC (rev 1129) @@ -7,11 +7,10 @@ import org.cishell.utility.datastructure.datamodel.DataModel; import org.cishell.utility.datastructure.datamodel.ModelDataSynchronizer; -import org.cishell.utility.datastructure.datamodel.exception.ModelValidationException; import org.cishell.utility.datastructure.datamodel.field.DataModelField; import org.cishell.utility.datastructure.datamodel.field.DataModelFieldContainer; -import org.cishell.utility.datastructure.datamodel.field.FieldValidationAction; -import org.cishell.utility.datastructure.datamodel.field.FieldValidationRule; +import org.cishell.utility.datastructure.datamodel.field.validation.FieldValidationAction; +import org.cishell.utility.datastructure.datamodel.field.validation.FieldValidator; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; @@ -23,6 +22,7 @@ DataSynchronizerType extends ModelDataSynchronizer<ValueType>> implements DataModelField<ValueType> { private Set<DataModelFieldContainer> containers = new HashSet<DataModelFieldContainer>(); + private DataModel model; private String name; private Composite parentComponent; private ValueType defaultValue; @@ -30,18 +30,22 @@ private ValueType value; private BaseGUIComponentType widget; private DataSynchronizerType dataSynchronizer; - private Collection<FieldValidationRule<ValueType>> validators = - new ArrayList<FieldValidationRule<ValueType>>(); - private Collection<FieldValidationAction<ValueType>> validationActions = - new ArrayList<FieldValidationAction<ValueType>>(); + private Collection<FieldValidator<ValueType>> validators = + new ArrayList<FieldValidator<ValueType>>(); + private Collection<FieldValidator<ValueType>> otherValidators = + new ArrayList<FieldValidator<ValueType>>(); + private Collection<FieldValidationAction> validationActions = + new HashSet<FieldValidationAction>(); + private boolean isDisposed = false; public SWTModelField( - final DataModel model, + DataModel model, String name, Composite parentComponent, ValueType defaultValue, BaseGUIComponentType widget, DataSynchronizerType dataSynchronizer) { + this.model = model; this.name = name; this.parentComponent = parentComponent; this.defaultValue = defaultValue; @@ -55,7 +59,7 @@ SWTModelField.this.previousValue = SWTModelField.this.value; SWTModelField.this.value = SWTModelField.this.dataSynchronizer.synchronizeFromGUI(); - validate(model); + validate(); } } }); @@ -111,63 +115,74 @@ return this.value; } - public void addValidationRule( - FieldValidationRule<ValueType> validator, boolean validateNow, DataModel model) { + public void addValidator(FieldValidator<ValueType> validator) { + validator.addFieldToValidate(this); this.validators.add(validator); - - if (validateNow) { - validate(model); - } } - public void addValidationAction(FieldValidationAction<ValueType> validationAction) { - this.validationActions.add(validationAction); + public void addOtherValidators(Collection<FieldValidator<ValueType>> validators) { + this.otherValidators.addAll(validators); } - public void validate(DataModel model) { - Collection<ModelValidationException> reasonsInvalid = attemptValidation(model); - performValidationActions(model, reasonsInvalid); + public void addValidationAction(FieldValidationAction action) { + this.validationActions.add(action); } public void dispose() { + this.isDisposed = true; + for (DataModelFieldContainer container : this.containers) { container.fieldDisposed(this); } - for (FieldValidationRule<ValueType> validator : this.validators) { + for (FieldValidator<ValueType> validator : this.validators) { validator.fieldDisposed(this); } - for (FieldValidationAction<ValueType> validationAction : this.validationActions) { - validationAction.fieldDisposed(this); - } + validate(); } - private Collection<ModelValidationException> attemptValidation(DataModel model) { - Collection<ModelValidationException> reasonsInvalid = - new ArrayList<ModelValidationException>(); + public boolean isDisposed() { + return this.isDisposed; + } - for (FieldValidationRule<ValueType> validator : this.validators) { - try { - validator.validateField(this, model); - } catch (ModelValidationException e) { - reasonsInvalid.add(e); - } - } + public void validate() { + Collection<String> errorMessages = attemptValidation(model); + performValidationActions(this.model, errorMessages); + } - return reasonsInvalid; + private Collection<String> attemptValidation(DataModel model) { + Collection<String> errorMessages = attemptValidationOnValidators(this.validators, true); + errorMessages.addAll(attemptValidationOnValidators(this.otherValidators, false)); + + return errorMessages; } - private void performValidationActions( - DataModel model, Collection<ModelValidationException> reasonsInvalid) { - if (reasonsInvalid.size() == 0) { - for (FieldValidationAction<ValueType> validationAction : this.validationActions) { - validationAction.fieldDoesValidate(this); + private void performValidationActions(DataModel model, Collection<String> errorMessages) { + if (errorMessages.size() == 0) { + for (FieldValidationAction validationAction : this.validationActions) { + validationAction.doesValidate(); } } else { - for (FieldValidationAction<ValueType> validationAction : this.validationActions) { - validationAction.fieldDoesNotValidate(this, reasonsInvalid); + for (FieldValidationAction validationAction : this.validationActions) { + validationAction.doesNotValidate(errorMessages); } } } + + private Collection<String> attemptValidationOnValidators( + Collection<FieldValidator<ValueType>> validators, boolean update) { + Collection<String> errorMessages = new ArrayList<String>(); + + for (FieldValidator<ValueType> validator : validators) { + if (update && !this.isDisposed) { + validator.fieldUpdated(this); + } + + Collection<String> temporaryErrorMessage = validator.runValidation(model); + errorMessages.addAll(temporaryErrorMessage); + } + + return errorMessages; + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fu...@us...> - 2010-01-26 17:46:43
|
Revision: 1026 http://cishell.svn.sourceforge.net/cishell/?rev=1026&view=rev Author: fugu13 Date: 2010-01-26 17:46:36 +0000 (Tue, 26 Jan 2010) Log Message: ----------- Database Copy stuff. Reviewed by Patrick. Modified Paths: -------------- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java Modified: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2010-01-26 16:51:30 UTC (rev 1025) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2010-01-26 17:46:36 UTC (rev 1026) @@ -1,13 +1,13 @@ package org.cishell.reference.service.database; +import java.io.File; +import java.sql.CallableStatement; import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; +import java.util.UUID; import javax.sql.DataSource; @@ -20,179 +20,269 @@ import org.apache.commons.pool.impl.GenericObjectPool; import org.cishell.reference.service.database.utility.DatabaseCleaner; import org.cishell.service.database.Database; +import org.cishell.service.database.DatabaseCopyException; import org.cishell.service.database.DatabaseCreationException; import org.cishell.service.database.DatabaseService; +import org.cishell.utilities.DatabaseUtilities; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; +//TODO: rework exception handling everywhere to be failsafe. public class DerbyDatabaseService implements DatabaseService, BundleActivator { - + public static final String DERBY_DRIVER_NAME = "org.apache.derby.jdbc.EmbeddedDriver"; public static final String DERBY_PROTOCOL = "jdbc:derby:"; - + public static final String DEFAULT_CREATE_CONNECTION_STRING = ";create=true"; public static final String DEFAULT_SHUTDOWN_CONNECTION_STRING =";shutdown=true"; - + //where the database exists on the filesystem (relative to the application root directory) private static final String DATABASE_DIRECTORY = "database/"; - + //hold on to our service registration so we can unregister when this plugin stops. private ServiceRegistration databaseServiceRegistration; - + /* * internal databases are created when requested by outside services, * and are cleaned and shut down when this service is stopped. */ private List<InternalDerbyDatabase> internalDatabases = new ArrayList<InternalDerbyDatabase>(); - + public final void start(BundleContext context) throws Exception { - + /* * Tell Derby to look for an existing database or create a new database * in the default directory (within our application's directory) */ System.setProperty("derby.system.home", DATABASE_DIRECTORY); - + //Allow the database service to be found by other services/plugins databaseServiceRegistration = context.registerService( DatabaseService.class.getName(), this, new Hashtable()); } - + public final void stop(BundleContext context) { - //disallow the database service to be found by other services/plugins - this.databaseServiceRegistration.unregister(); - - //Clean out the internal databases and shut them down. - try { - for (InternalDerbyDatabase internalDatabase : internalDatabases) { - Connection internalDatabaseConnection = internalDatabase.getConnection(); - //DatabaseCleaner.cleanDatabase(internalDatabaseConnection, false); - internalDatabase.shutdown(); - } - } catch (Exception e) { - String message = - "An unexpected exception occurred while shutting down the internal database." - + "Aborting database shutdown process." - + "Database may not be left in a valid state, " - + "but we will try to make its state valid on next startup."; - throw new RuntimeException(message, e); + //disallow the database service to be found by other services/plugins + this.databaseServiceRegistration.unregister(); + + //Clean out the internal databases and shut them down. + try { + for (InternalDerbyDatabase internalDatabase : internalDatabases) { + Connection internalDatabaseConnection = internalDatabase.getConnection(); + //DatabaseCleaner.cleanDatabase(internalDatabaseConnection, false); + internalDatabase.shutdown(); } + } catch (Exception e) { + String message = + "An unexpected exception occurred while shutting down the internal database." + + "Aborting database shutdown process." + + "Database may not be left in a valid state, " + + "but we will try to make its state valid on next startup."; + throw new RuntimeException(message, e); + } } - + private static final String INTERNAL_DB_NAME_PREFIX = "cishell_database"; private static int id = 0; - - public synchronized Database createNewDatabase() throws DatabaseCreationException { - try { + + public Database createNewDatabase() throws DatabaseCreationException { //connect to and create a 'new' database - String databaseName = INTERNAL_DB_NAME_PREFIX + id; - InternalDerbyDatabase db = - new InternalDerbyDatabase(createNewInternalDataSource(databaseName)); - - - //if this database existed on disk from a previous session, clean it to be like new - DatabaseCleaner.cleanDatabase(db.getConnection(), false); - - //keep track of our new database for this CIShell session - internalDatabases.add(db); - - id++; - - return db; - } catch (Exception e) { - throw new DatabaseCreationException(e); - } + String databaseName = nextDatabaseIdentifier(); + DataSource internalDataSource = createNewInternalDataSource(databaseName); + //TODO: find a way to get the darn database name that isn't awful! + InternalDerbyDatabase internalDatabase = createNewInternalDatabase(internalDataSource); + internalDatabase.setName(databaseName); + return internalDatabase; } - + + + public Database connectToExistingDatabase(String driver, String url) - throws DatabaseCreationException { + throws DatabaseCreationException { return connectToExistingDatabase(driver, url, null, null); } - + public Database connectToExistingDatabase( String driver, String url, String username, String password) - throws DatabaseCreationException { + throws DatabaseCreationException { DataSource dataSource = createNewDataSource(driver, url, username, password); //TODO: See if we can get the default schema as a property somehow. Database db = new ExternalDatabase(dataSource, "APP"); return db; } + + + + public Database copyDatabase(Database originalDatabase) throws DatabaseCopyException { + /* Connection originalConnection = null; + Connection newConnection = null; + try { + Database newDatabase = createNewDatabase(); + originalConnection = originalDatabase.getConnection(); + try { + newConnection = newDatabase.getConnection(); + DatabaseTable[] tables = DatabaseTable.availableTables(originalConnection); + for(DatabaseTable table : tables) { + table.duplicateTable(originalConnection, newConnection); + } + for(DatabaseTable table : tables) { + table.transferPrimaryKey(originalConnection, newConnection); + table.pointForeignKeys(originalConnection, newConnection); + } + + + } catch(SQLException e) { + throw new DatabaseCopyException("There was a problem creating the new database: " + e.getMessage(), e); + } + } catch (DatabaseCreationException e) { + throw new DatabaseCopyException("Unable to create a new database to copy into: " + e.getMessage(), e); + } catch (SQLException e) { + throw new DatabaseCopyException("Unable to connect to the database being copied.", e); + } finally { + DatabaseUtilities.closeConnectionQuietly(originalConnection); + DatabaseUtilities.closeConnectionQuietly(newConnection); + } + + //TODO: copy views. Wait until we have the darn things. + /* + * TODO: make copy table work + * On the subject of copying tables . . . looks like that needs to be provided. Rough plan of attack: + * Make new database. For every table in the original (make sure system tables are excluded), make an identical table in the new one. + * For every table, copy all values into the new database. + * Put all constraints in place on the new database (especially: primary keys, foreign keys) + */ + + //Make a backup, then make a new database derived from the backup. + if(originalDatabase instanceof InternalDerbyDatabase) { + InternalDerbyDatabase database = (InternalDerbyDatabase) originalDatabase; + String originalName = database.getName(); + Connection connection = null; + try { + connection = database.getConnection(); + String backupLocation = createDatabaseBackup(connection, + originalName); + + InternalDerbyDatabase internalDatabase = createInternalDatabaseFromBackup(backupLocation); + return internalDatabase; + + + } catch (SQLException e) { + throw new DatabaseCopyException("A problem occurred while attempting to copy the database.", e); + } catch (DatabaseCreationException e) { + throw new DatabaseCopyException("A problem occurred while attempting to copy the database.", e); + } finally { + DatabaseUtilities.closeConnectionQuietly(connection); + } + + + + } else { + throw new DatabaseCopyException("Unable to copy external databases!"); + } + } + + private InternalDerbyDatabase createInternalDatabaseFromBackup( + String backupLocation) throws DatabaseCreationException { + String newName = nextDatabaseIdentifier(); + String newDatabaseConnectionURL = DERBY_PROTOCOL + newName + ";restoreFrom=" + backupLocation; + DataSource derivedDataSource = createNewDataSource(DERBY_DRIVER_NAME, + newDatabaseConnectionURL, null, null); + InternalDerbyDatabase internalDatabase = createNewInternalDatabase(derivedDataSource, false); + internalDatabase.setName(newName); + return internalDatabase; + } + + private String createDatabaseBackup(Connection connection, + String originalName) throws SQLException { + CallableStatement backupStatement = connection.prepareCall("CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE(?)"); + String tempDir = System.getProperty("java.io.tmpdir"); + backupStatement.setString(1, tempDir); + backupStatement.execute(); + String backupLocation = new File(new File(tempDir), originalName).getAbsolutePath(); + return backupLocation; + } + //***---UTILITIES---*** - + private DataSource createNewDataSource( String driver, String url, String username, String password) - throws DatabaseCreationException { + throws DatabaseCreationException { try { - //Load the database driver - Class.forName(driver); - - //create a new data source based on the database connection info provided. - ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( - url, username, password); - GenericObjectPool connectionPool = new GenericObjectPool(); + //Load the database driver + Class.forName(driver); + + //create a new data source based on the database connection info provided. + ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( + url, username, password); + GenericObjectPool connectionPool = new GenericObjectPool(); KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null); new PoolableConnectionFactory( connectionFactory, connectionPool, stmtPool, null, false, true); DataSource dataSource = new PoolingDataSource(connectionPool); - + //test the connection (this will throw an exception if the connection is faulty) dataSource.getConnection(); - + //return that data source. - return dataSource; - } catch (ClassNotFoundException e) { - throw new DatabaseCreationException( - "Database driver '" + driver + "' could not be found", e); - } catch (SQLException e) { - throw new DatabaseCreationException(e.getMessage(), e); - } + return dataSource; + } catch (ClassNotFoundException e) { + throw new DatabaseCreationException( + "Database driver '" + driver + "' could not be found", e); + } catch (SQLException e) { + throw new DatabaseCreationException(e.getMessage(), e); + } } - + private DataSource createNewInternalDataSource(String dbName) - throws DatabaseCreationException { + throws DatabaseCreationException { String newDatabaseConnectionURL = DERBY_PROTOCOL - + dbName - + DEFAULT_CREATE_CONNECTION_STRING; + + dbName + + DEFAULT_CREATE_CONNECTION_STRING; return createNewDataSource(DERBY_DRIVER_NAME, newDatabaseConnectionURL, null, null); } - private static final int SCHEMA_NAME_INDEX = 2; - private static final int TABLE_NAME_INDEX = 3; - private static final String NONSYSTEM_SCHEMA_NAME = "APP"; -// //(removes all non-system tables from the provided databases) -// private void removeAllNonSystemDatabaseTables(Connection dbConnection) throws SQLException { -// DatabaseMetaData dbMetadata = dbConnection.getMetaData(); -// ResultSet allTableNames = dbMetadata.getTables(null, null, null, null); -// -// Statement removeTables = dbConnection.createStatement(); -// -// while (allTableNames.next()) { -// if (!hasSystemSchema(allTableNames.getString(SCHEMA_NAME_INDEX))) { -// String dropTableQuery = formDropTableQuery(allTableNames.getString(TABLE_NAME_INDEX)); -// removeTables.addBatch(dropTableQuery); -// } -// } -// -// removeTables.executeBatch(); -// } - - private boolean hasSystemSchema(String tableSchemaName) { - return tableSchemaName.indexOf(NONSYSTEM_SCHEMA_NAME) == -1; + private InternalDerbyDatabase createNewInternalDatabase(DataSource internalDataSource) throws DatabaseCreationException { + return createNewInternalDatabase(internalDataSource, true); } - - private String formDropTableQuery(String tableName) { - String removeTableSQL = - "DROP TABLE " - + NONSYSTEM_SCHEMA_NAME + "." + tableName; - return removeTableSQL; + + private InternalDerbyDatabase createNewInternalDatabase(DataSource internalDataSource, boolean clean) + throws DatabaseCreationException { + InternalDerbyDatabase db = + new InternalDerbyDatabase(internalDataSource); + Connection cleaningConnection = null; + try { + //if this database existed on disk from a previous session, clean it to be like new + if(clean) { + cleaningConnection = db.getConnection(); + DatabaseCleaner.cleanDatabase(cleaningConnection, false); + } + + //keep track of our new database for this CIShell session + internalDatabases.add(db); + + + return db; + } catch (Exception e) { + DatabaseUtilities.closeConnectionQuietly(cleaningConnection); + throw new DatabaseCreationException(e); + } } + //only thing that needs to be synchronized; all other ops are non-conflicting once they have differing names + private synchronized String nextDatabaseIdentifier() { + //Random to deal with the multiple running CIShell instance problem. Note: this means databases will build up. This is not a big deal, as even a "large" database will only be a few megabytes. + String randomPart = UUID.randomUUID().toString(); + String identifier = INTERNAL_DB_NAME_PREFIX + randomPart + "_" + id; + id++; + return identifier; + } + } Modified: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java 2010-01-26 16:51:30 UTC (rev 1025) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java 2010-01-26 17:46:36 UTC (rev 1026) @@ -11,7 +11,8 @@ public class InternalDerbyDatabase implements Database { private DataSource dataSource; - + private String databaseName; + // TODO: Should this be public? public InternalDerbyDatabase(DataSource dataSource) { this.dataSource = dataSource; } @@ -33,4 +34,13 @@ public String getApplicationSchemaName() { return "APP"; } + + + protected void setName(String databaseName) { + this.databaseName = databaseName; + } + + protected String getName() { + return databaseName; + } } Modified: trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java =================================================================== --- trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java 2010-01-26 16:51:30 UTC (rev 1025) +++ trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java 2010-01-26 17:46:36 UTC (rev 1026) @@ -7,4 +7,5 @@ public Database connectToExistingDatabase( String driver, String url, String username, String password) throws DatabaseCreationException; + public Database copyDatabase(Database originalDatabase) throws DatabaseCopyException; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pat...@us...> - 2010-08-03 19:15:32
|
Revision: 1108 http://cishell.svn.sourceforge.net/cishell/?rev=1108&view=rev Author: pataphil Date: 2010-08-03 19:15:24 +0000 (Tue, 03 Aug 2010) Log Message: ----------- * Cleaned up and refactored a bit of code. * Introduced the notion of the Algorithm Invocation Service, though it's commented out. * Reviewed by Micah. Modified Paths: -------------- trunk/core/org.cishell.framework/src/org/cishell/app/service/scheduler/SchedulerService.java trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmCreationCanceledException.java trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmCreationFailedException.java trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmFactory.java trunk/core/org.cishell.framework/src/org/cishell/framework/data/BasicData.java trunk/core/org.cishell.framework/src/org/cishell/framework/data/Data.java trunk/core/org.cishell.reference/.settings/org.eclipse.jdt.core.prefs trunk/core/org.cishell.reference/META-INF/MANIFEST.MF trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/scheduler/SchedulerServiceImpl.java trunk/core/org.cishell.reference.services/src/org/cishell/reference/services/Activator.java Added Paths: ----------- trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/ trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java Modified: trunk/core/org.cishell.framework/src/org/cishell/app/service/scheduler/SchedulerService.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/app/service/scheduler/SchedulerService.java 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.framework/src/org/cishell/app/service/scheduler/SchedulerService.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -28,7 +28,6 @@ * service as it is not guaranteed to be available like the standard CIShell * services are. * - * @author Bruce Herr (bh...@bh...) */ public interface SchedulerService { /** @@ -37,10 +36,9 @@ * enough resources to fulfill the request. * * @param algorithm The algorithm to be run - * @param ref A reference to the Algorithm's associated service, may - * be <code>null</code> + * @param reference A reference to the Algorithm's associated service, may be <code>null</code> */ - public void runNow(Algorithm algorithm, ServiceReference ref); + public void runNow(Algorithm algorithm, ServiceReference reference); /** * Schedules an Algorithm to be run when convenient. This schedules an @@ -48,10 +46,9 @@ * Algorithms will be scheduled in this way. * * @param algorithm The Algorithm to be scheduled - * @param ref A reference to the Algorithm's associated service, may - * be <code>null</code> + * @param reference A reference to the Algorithm's associated service, may be <code>null</code> */ - public void schedule(Algorithm algorithm, ServiceReference ref); + public void schedule(Algorithm algorithm, ServiceReference reference); /** * Schedules an Algorithm to be run at a specific time. The Algorithm will @@ -60,11 +57,10 @@ * resources to fulfill the request. * * @param algorithm The Algorithm to be scheduled - * @param ref A reference to the Algorithm's associated service, may - * be <code>null</code> + * @param reference A reference to the Algorithm's associated service, may be <code>null</code> * @param time What time this Algorithm should be run */ - public void schedule(Algorithm algorithm, ServiceReference ref, Calendar time); + public void schedule(Algorithm algorithm, ServiceReference reference, Calendar time); /** * Reschedules an already scheduled Algorithm to be run at a different time. Modified: trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmCreationCanceledException.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmCreationCanceledException.java 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmCreationCanceledException.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -1,6 +1,5 @@ package org.cishell.framework.algorithm; -// TODO: Make this a regular Exception (not RuntimeException). public class AlgorithmCreationCanceledException extends RuntimeException { private static final long serialVersionUID = 9017277008277139930L; Modified: trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmCreationFailedException.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmCreationFailedException.java 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmCreationFailedException.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -1,6 +1,5 @@ package org.cishell.framework.algorithm; -// TODO: Make this a regular Exception (not RuntimeException). public class AlgorithmCreationFailedException extends RuntimeException { private static final long serialVersionUID = 9017277008277139930L; Modified: trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmFactory.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmFactory.java 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmFactory.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -32,7 +32,6 @@ * CIShell Specification 1.0</a> for documentation on the full requirements for * algorithm creation. * - * @author Bruce Herr (bh...@bh...) */ public interface AlgorithmFactory { @@ -47,7 +46,7 @@ * @param parameters A set of key-value pairs that were created based on * the associated input specification published to the * {@link MetaTypeService} - * @param context The context by which the Algorithm can gain access to + * @param ciShellContext The context by which the Algorithm can gain access to * standard CIShell services * @return An <code>Algorithm</code> primed for execution */ @@ -55,5 +54,5 @@ * the signature, and update the entire code base to conform to it. */ public Algorithm createAlgorithm( - Data[] data, Dictionary<String, Object> parameters, CIShellContext context); + Data[] data, Dictionary<String, Object> parameters, CIShellContext ciShellContext); } Modified: trunk/core/org.cishell.framework/src/org/cishell/framework/data/BasicData.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/framework/data/BasicData.java 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.framework/src/org/cishell/framework/data/BasicData.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -24,7 +24,7 @@ * @author Bruce Herr (bh...@bh...) */ public class BasicData implements Data { - private Dictionary properties; + private Dictionary<String, Object> properties; private Object data; private String format; @@ -35,7 +35,7 @@ * @param data The data being wrapped */ public BasicData(Object data, String format) { - this(new Hashtable(), data, format); + this(new Hashtable<String, Object>(), data, format); } /** @@ -44,7 +44,7 @@ * @param properties The metadata about the data * @param data The data being wrapped */ - public BasicData(Dictionary properties, Object data, String format) { + public BasicData(Dictionary<String, Object> properties, Object data, String format) { this.properties = properties; this.data = data; this.format = format; @@ -60,7 +60,7 @@ /** * @see org.cishell.framework.data.Data#getMetadata() */ - public Dictionary getMetadata() { + public Dictionary<String, Object> getMetadata() { return properties; } Modified: trunk/core/org.cishell.framework/src/org/cishell/framework/data/Data.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/framework/data/Data.java 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.framework/src/org/cishell/framework/data/Data.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -20,8 +20,7 @@ * A class that contains data, its format, and its metadata. This class is used * to pass data between algorithms and is what algorithms optionally create when * executed. - * - * @author Bruce Herr (bh...@bh...) + * */ public interface Data { /** @@ -30,7 +29,7 @@ * * @return The data's metadata */ - public Dictionary getMetadata(); + public Dictionary<String, Object> getMetadata(); /** * Returns the data stored in this Data object Added: trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java (rev 0) +++ trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -0,0 +1,126 @@ + +/* TODO: When we have time, we should talk about the design of the Algorithm Invocation Service (if + * we even use that name in the end). + * It's somewhat apparent that there is a use for this service, but exactly how it fits into + * CIShell and all of the tools remains to be fully clarified. + * This is all commented out for now because the design/use need discussion. + */ + +//package org.cishell.service.algorithminvocation; +// +//import java.util.Dictionary; +// +//import org.cishell.framework.CIShellContext; +//import org.cishell.framework.algorithm.Algorithm; +//import org.cishell.framework.algorithm.AlgorithmCanceledException; +//import org.cishell.framework.algorithm.AlgorithmCreationCanceledException; +//import org.cishell.framework.algorithm.AlgorithmCreationFailedException; +//import org.cishell.framework.algorithm.AlgorithmExecutionException; +//import org.cishell.framework.algorithm.AlgorithmFactory; +//import org.cishell.framework.data.Data; +// +///** +// * Provides the caller with various ways of creating algorithms, executing them, and +// * gathering/mutating parameters. +// * When creating an algorithm (from a factory), if the factory implements ParameterMutator, +// * mutateParameters() will be called on it. +// * All methods can optionally operate on a new thread, which is determined by shouldUseNewThread. +// */ +//public interface AlgorithmInvocationService { +// /** +// * Uses factory to create an algorithm, presenting the user with a GUI for parameters. +// */ +// public Algorithm createAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final CIShellContext ciShellContext, +// boolean shouldUseNewThread) +// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException; +// +// /** +// * Uses factory to create an algorithm, using parameters (instead of presenting the user with a +// * GUI for them). +// */ +// public Algorithm createAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final Dictionary<String, Object> parameters, +// final CIShellContext ciShellContext, +// boolean shouldUseNewThread) +// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException; +// +// /** +// * Invokes algorithm, returning the Data[] result of algorithm.execute(). +// * If logExceptionThrown is true, any exception thrown will be logged to the +// * default LogService. +// * If displayRuntimeException is true, the stack trace of any exception thrown will be +// * displayed in an error message box. +// */ +// public Data[] invokeAlgorithm( +// final Algorithm algorithm, +// final boolean logExceptionThrown, +// final boolean displayRuntimeException, +// boolean shouldUseNewThread) +// throws AlgorithmCanceledException, AlgorithmExecutionException; +// +// /** +// * Invokes algorithm, assuming sensible defaults for inline algorithm execution (that is, +// * not explicitly invoked from a menu/etc.), and return the Data[] result of +// * algorithm.execute(). +// * Most likely wraps invokeAlgorithm(). +// */ +// public Data[] simpleInvokeAlgorithm(final Algorithm algorithm, Thread thread) +// throws AlgorithmCanceledException, AlgorithmExecutionException; +// +// /** +// * Given factory, presents the user with a GUI for parameters to use for creating and executing +// * an algorithm. +// * Most likely wraps createAlgorithm() and invokeAlgorithm(). +// */ +// public Data[] createAndInvokeAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final CIShellContext ciShellContext, +// final boolean logExceptionThrown, +// final boolean displayRuntimeException, +// boolean shouldUseNewThread) throws +// AlgorithmCreationCanceledException, +// AlgorithmCreationFailedException, +// AlgorithmCanceledException, +// AlgorithmExecutionException; +// +// /** +// * Given factory, uses parameters to create and execute an algorithm. +// * Most likely wraps createAlgorithm() and invokeAlgorithm(). +// */ +// public Data[] createAndInvokeAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final Dictionary<String, Object> parameters, +// final CIShellContext ciShellContext, +// final boolean logExceptionThrown, +// final boolean displayRuntimeException, +// boolean shouldUseNewThread) throws +// AlgorithmCreationCanceledException, +// AlgorithmCreationFailedException, +// AlgorithmCanceledException, +// AlgorithmExecutionException; +// +// /** +// * Given factory, uses parameters to create and execute an algorithm. +// * Sensible defaults for inline algorithm execution (that is, not explicitly invoked from a +// * menu/etc.) are used. +// * Returns the Data[] result of algorithm.execute(). +// * Most likely wraps createAlgorithm() and simpleInvokeAlgorithm(). +// */ +// public Data[] simpleCreateAndInvokeAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final Dictionary<String, Object> parameters, +// CIShellContext ciShellContext, +// boolean shouldUseNewThread) throws +// AlgorithmCreationCanceledException, +// AlgorithmCreationFailedException, +// AlgorithmCanceledException, +// AlgorithmExecutionException; +//} \ No newline at end of file Modified: trunk/core/org.cishell.reference/.settings/org.eclipse.jdt.core.prefs =================================================================== --- trunk/core/org.cishell.reference/.settings/org.eclipse.jdt.core.prefs 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.reference/.settings/org.eclipse.jdt.core.prefs 2010-08-03 19:15:24 UTC (rev 1108) @@ -1,12 +1,12 @@ -#Mon Jul 27 15:45:33 EDT 2009 +#Wed Jul 21 20:42:37 EDT 2010 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning -org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning -org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 Modified: trunk/core/org.cishell.reference/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.reference/META-INF/MANIFEST.MF 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.reference/META-INF/MANIFEST.MF 2010-08-03 19:15:24 UTC (rev 1108) @@ -1,4 +1,3 @@ -Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: CIShell Reference Service Implementations Bundle-SymbolicName: org.cishell.reference @@ -14,9 +13,11 @@ org.osgi.service.log, org.osgi.service.metatype;version="1.1.0", org.osgi.service.prefs -Export-Package: org.cishell.reference.app.service.datamanager, +Export-Package: org.cishell.reference.app.service.algorithminvocation, + org.cishell.reference.app.service.datamanager, org.cishell.reference.app.service.scheduler, org.cishell.reference.service.conversion, org.cishell.reference.service.metatype Eclipse-LazyStart: true Require-Bundle: edu.uci.ics.jung +Bundle-RequiredExecutionEnvironment: J2SE-1.5 Added: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java (rev 0) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -0,0 +1,85 @@ +//package org.cishell.reference.app.service.algorithminvocation; +// +//import java.util.Dictionary; +//import java.util.Hashtable; +// +//import org.cishell.framework.CIShellContext; +//import org.cishell.framework.algorithm.Algorithm; +//import org.cishell.framework.algorithm.AlgorithmCreationCanceledException; +//import org.cishell.framework.algorithm.AlgorithmCreationFailedException; +//import org.cishell.framework.algorithm.AlgorithmFactory; +//import org.cishell.framework.data.Data; +//import org.cishell.service.algorithminvocation.AlgorithmInvocationService; +//import org.osgi.service.log.LogService; +// +//public class AlgorithmInvocationServiceImpl implements AlgorithmInvocationService { +// private LogService logger; +// +// public AlgorithmInvocationServiceImpl(LogService logger) { +// this.logger = logger; +// } +// +// @SuppressWarnings("unchecked") +// public Algorithm createAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final CIShellContext ciShellContext, +// boolean shouldUseNewThread) +// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException { +// /* TODO: Refactor org.cishell.utilities into several plugins so there are no +// * circular dependencies! +// */ +// +// final AlgorithmCreationCanceledException[] canceledException = +// new AlgorithmCreationCanceledException[1]; +// final AlgorithmCreationFailedException[] failedException = +// new AlgorithmCreationFailedException[1]; +// final Algorithm[] algorithm = new Algorithm[1]; +// +// Runnable operator = new Runnable() { +// public void run() { +// /* TODO: Refactor algorithm creation code out of +// * org.cishell.reference.gui.menumanager, and call it here. +// */ +// +// try { +// // TODO: readFromMetadataFile +// Dictionary<String, Object> parameters = new Hashtable<String, Object>(); +// // TODO: mutateParameters +// Dictionary<String, Object> mutatedParameters = parameters; +// // TODO: Invoke GUI builder service, getting user-entered parameters. +// Dictionary<String, Object> userEnteredParameters = mutatedParameters; +// +// algorithm[0] = +// factory.createAlgorithm(data, userEnteredParameters, ciShellContext); +// } catch (AlgorithmCreationCanceledException e) { +// canceledException[0] = e; +// } catch (AlgorithmCreationFailedException e) { +// failedException[0] = e; +// } +// } +// }; +// +// if (shouldUseNewThread) { +// new Thread(operator).start(); +// } else { +// operator.run(); +// } +// +// return algorithm[0]; +// } +// +// public Algorithm createAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final Dictionary<String, Object> parameters, +// final CIShellContext ciShellContext, +// boolean shouldUseNewThread) +// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException { +// final AlgorithmCreationCanceledException[] canceledException = +// new AlgorithmCreationCanceledException[1]; +// final AlgorithmCreationFailedException[] failedException = +// new AlgorithmCreationFailedException[1]; +// +// } +//} \ No newline at end of file Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/scheduler/SchedulerServiceImpl.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/scheduler/SchedulerServiceImpl.java 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/scheduler/SchedulerServiceImpl.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -30,7 +30,7 @@ import org.cishell.app.service.scheduler.SchedulerService; import org.cishell.framework.algorithm.Algorithm; import org.cishell.framework.data.Data; -import org.cishell.reference.app.service.scheduler.AlgorithmTask.STATE; +import org.cishell.reference.app.service.scheduler.AlgorithmTask.AlgorithmState; import org.osgi.framework.ServiceReference; /** @@ -74,156 +74,150 @@ * algorithm, consider using Quartz http://www.opensymphony.com/quartz/ </li> * </ul> * - * @author Shashikant Penumarthy - * @author Bruce Herr (bh...@bh...) */ -// May 8, 2006 7:05:32 PM Shashikant Penumarthy: Initial Implementation -// July 19, 2006 10:30:00 AM Bruce Herr: Ported to new CIShell public class SchedulerServiceImpl implements SchedulerService { /** * This timer runs the algorithm scheduling task. */ - private Timer _schedulerTimer; + private Timer schedulerTimer; /** * The task which schedules algorithms to run on the _algRunningTimer. */ - private AlgSchedulerTask _algSchedulerTask; + private AlgorithmSchedulerTask algorithmSchedulerTask; /** * Convenience object for informing all the schedulers. */ - private SchedulerListenerInformer _schedulerListenerInformer; + private SchedulerListenerInformer schedulerListenerInformer; + + private boolean isShutDown = true; public SchedulerServiceImpl() { - _initialize(); + initialize(); } - public SchedulerServiceImpl(int maxSimultaneousAlgsLimit) { + public SchedulerServiceImpl(int maxSimultaneousAlgorithm) { this(); - _algSchedulerTask.setMaxSimultaneousAlgs(maxSimultaneousAlgsLimit); - _isShutDown = false; + this.algorithmSchedulerTask.setMaxSimultaneousAlgorithms(maxSimultaneousAlgorithm); + this.isShutDown = false; } - public synchronized final void setMaxSimultaneousAlgs(int max) { - _algSchedulerTask.setMaxSimultaneousAlgs(max); + public synchronized final void setMaxSimultaneousAlgorithms(int max) { + this.algorithmSchedulerTask.setMaxSimultaneousAlgorithms(max); } - private final void _initialize() { - _schedulerTimer = new Timer(true); - _schedulerListenerInformer = new SchedulerListenerInformer(); - _algSchedulerTask = new AlgSchedulerTask(_schedulerListenerInformer); - _schedulerTimer.schedule(_algSchedulerTask, 0L, 500L); + private final void initialize() { + this.schedulerTimer = new Timer(true); + this.schedulerListenerInformer = new SchedulerListenerInformer(); + this.algorithmSchedulerTask = new AlgorithmSchedulerTask(this.schedulerListenerInformer); + this.schedulerTimer.schedule(this.algorithmSchedulerTask, 0L, 500L); } public synchronized final void shutDown() { - _algSchedulerTask.cancel(); - _schedulerTimer.cancel(); - _isShutDown = true; + this.algorithmSchedulerTask.cancel(); + this.schedulerTimer.cancel(); + this.isShutDown = true; } public final boolean isEmpty() { - return _algSchedulerTask.isEmpty(); + return this.algorithmSchedulerTask.isEmpty(); } public final boolean isRunning() { - return _algSchedulerTask.isRunning(); + return this.algorithmSchedulerTask.isRunning(); } public final int numRunning() { - return _algSchedulerTask.numRunning(); + return this.algorithmSchedulerTask.numRunning(); } - private boolean _isShutDown = true; - public final boolean isShutDown() { - return _isShutDown; + return this.isShutDown; } public boolean reschedule(Algorithm algorithm, Calendar newTime) { - // Shaky method. Ideally this is done at a higher level. But still, here - // goes... - ServiceReference ref = _algSchedulerTask.getServiceReference(algorithm); - boolean status = false; + // Shaky method. Ideally this is done at a higher level. But still, here goes... + ServiceReference reference = this.algorithmSchedulerTask.getServiceReference(algorithm); + boolean canReschedule = false; + try { - STATE algState = _algSchedulerTask.getAlgorithmState(algorithm); + AlgorithmState algorithmState = + this.algorithmSchedulerTask.getAlgorithmState(algorithm); - // Cannot reschedule running algs - if (algState.equals(STATE.RUNNING)) { - status = false; + // Cannot reschedule running algorithms. + if (algorithmState.equals(AlgorithmState.RUNNING)) { + canReschedule = false; + } else if (algorithmState.equals(AlgorithmState.STOPPED)) { + this.algorithmSchedulerTask.purgeFinished(); + this.algorithmSchedulerTask.schedule(algorithm, reference, newTime); + canReschedule = true; + } else if (algorithmState.equals(AlgorithmState.NEW)) { + this.algorithmSchedulerTask.cancel(algorithm); + this.algorithmSchedulerTask.schedule(algorithm, reference, newTime); + } else { + throw new IllegalStateException("Encountered an invalid state: " + algorithmState); } - else if (algState.equals(STATE.STOPPED)) { - _algSchedulerTask.purgeFinished(); - _algSchedulerTask.schedule(algorithm, ref, newTime); - status = true; - } - else if (algState.equals(STATE.NEW)) { - _algSchedulerTask.cancel(algorithm); - _algSchedulerTask.schedule(algorithm, ref, newTime); - } - else { - throw new IllegalStateException( - "Encountered an invalid state: " + algState); - } - } catch (NoSuchElementException nsee) { - _algSchedulerTask.schedule(algorithm, ref, newTime); - status = true; + } catch (NoSuchElementException e) { + this.algorithmSchedulerTask.schedule(algorithm, reference, newTime); + canReschedule = true; } - return status; + return canReschedule; } - public void runNow(Algorithm algorithm, ServiceReference ref) { + public void runNow(Algorithm algorithm, ServiceReference reference) { // There is currently no difference between this one and - // schedule(Algorithm, ref). - schedule(algorithm, ref); + // schedule(Algorithm, reference). + schedule(algorithm, reference); } - public void schedule(Algorithm algorithm, ServiceReference ref) { - schedule(algorithm, ref, Calendar.getInstance()); + public void schedule(Algorithm algorithm, ServiceReference reference) { + schedule(algorithm, reference, Calendar.getInstance()); } - public void schedule(Algorithm algorithm, ServiceReference ref, Calendar time) { - _algSchedulerTask.schedule(algorithm, ref, time); + public void schedule(Algorithm algorithm, ServiceReference reference, Calendar time) { + this.algorithmSchedulerTask.schedule(algorithm, reference, time); } public boolean unschedule(Algorithm algorithm) { - return _algSchedulerTask.cancel(algorithm); + return this.algorithmSchedulerTask.cancel(algorithm); } public void addSchedulerListener(SchedulerListener listener) { - _schedulerListenerInformer.addSchedulerListener(listener); + this.schedulerListenerInformer.addSchedulerListener(listener); } public void removeSchedulerListener(SchedulerListener listener) { - _schedulerListenerInformer.removeSchedulerListener(listener); + this.schedulerListenerInformer.removeSchedulerListener(listener); } public synchronized void clearSchedule() { - _algSchedulerTask.cancel(); - _schedulerTimer.cancel(); + this.algorithmSchedulerTask.cancel(); + this.schedulerTimer.cancel(); - _schedulerTimer = new Timer(true); - _algSchedulerTask = new AlgSchedulerTask(_schedulerListenerInformer); - _schedulerTimer.schedule(_algSchedulerTask, 0L, 500L); + this.schedulerTimer = new Timer(true); + this.algorithmSchedulerTask = new AlgorithmSchedulerTask(this.schedulerListenerInformer); + // TODO: Make constants for these magic numbers. + this.schedulerTimer.schedule(this.algorithmSchedulerTask, 0L, 500L); - _schedulerListenerInformer.schedulerCleared(); + this.schedulerListenerInformer.schedulerCleared(); } public Algorithm[] getScheduledAlgorithms() { - return _algSchedulerTask.getScheduledAlgorithms(); + return this.algorithmSchedulerTask.getScheduledAlgorithms(); } public Calendar getScheduledTime(Algorithm algorithm) { - return _algSchedulerTask.getScheduledTime(algorithm); + return this.algorithmSchedulerTask.getScheduledTime(algorithm); } public ServiceReference getServiceReference(Algorithm algorithm) { - return _algSchedulerTask.getServiceReference(algorithm); + return this.algorithmSchedulerTask.getServiceReference(algorithm); } public void setRunning(boolean isRunning) { - _algSchedulerTask.setRunning(isRunning); - _schedulerListenerInformer.schedulerRunStateChanged(isRunning); + this.algorithmSchedulerTask.setRunning(isRunning); + this.schedulerListenerInformer.schedulerRunStateChanged(isRunning); } } @@ -238,133 +232,124 @@ * @author Team IVC */ class SchedulerListenerInformer implements SchedulerListener { + private List<SchedulerListener> schedulerListeners; - private List _schedulerListeners; - public SchedulerListenerInformer() { - _schedulerListeners = new ArrayList(); + this.schedulerListeners = new ArrayList<SchedulerListener>(); } public void addSchedulerListener(SchedulerListener listener) { - _schedulerListeners.add(listener); + this.schedulerListeners.add(listener); } public void removeSchedulerListener(SchedulerListener listener) { - _schedulerListeners.remove(listener); + this.schedulerListeners.remove(listener); } public void algorithmScheduled(Algorithm algorithm, Calendar time) { - for (Iterator iter = _schedulerListeners.iterator() ; iter.hasNext() ; ) { - SchedulerListener sl = (SchedulerListener) iter.next() ; - sl.algorithmScheduled(algorithm, time); + for (SchedulerListener schedulerListener : this.schedulerListeners) { + schedulerListener.algorithmScheduled(algorithm, time); } } public synchronized void algorithmStarted(Algorithm algorithm) { - for (Iterator iter = _schedulerListeners.iterator() ; iter.hasNext() ; ) { - SchedulerListener sl = (SchedulerListener) iter.next() ; - sl.algorithmStarted(algorithm); + for (SchedulerListener schedulerListener : this.schedulerListeners) { + schedulerListener.algorithmStarted(algorithm); } } public void algorithmError(Algorithm algorithm, Throwable error) { - for (Iterator iter = _schedulerListeners.iterator() ; iter.hasNext() ; ) { - SchedulerListener sl = (SchedulerListener) iter.next() ; - sl.algorithmError(algorithm, error); + for (SchedulerListener schedulerListener : this.schedulerListeners) { + schedulerListener.algorithmError(algorithm, error); } } public void algorithmFinished(Algorithm algorithm, Data[] createdDM) { - for (Iterator iter = _schedulerListeners.iterator() ; iter.hasNext() ; ) { - SchedulerListener sl = (SchedulerListener) iter.next() ; - sl.algorithmFinished(algorithm, createdDM); + for (SchedulerListener schedulerListener : this.schedulerListeners) { + schedulerListener.algorithmFinished(algorithm, createdDM); } } public void algorithmRescheduled(Algorithm algorithm, Calendar time) { - for (Iterator iter = _schedulerListeners.iterator() ; iter.hasNext() ; ) { - SchedulerListener sl = (SchedulerListener) iter.next() ; - sl.algorithmRescheduled(algorithm, time); + for (SchedulerListener schedulerListener : this.schedulerListeners) { + schedulerListener.algorithmRescheduled(algorithm, time); } } public void algorithmUnscheduled(Algorithm algorithm) { - for (Iterator iter = _schedulerListeners.iterator() ; iter.hasNext() ; ) { - SchedulerListener sl = (SchedulerListener) iter.next() ; - sl.algorithmUnscheduled(algorithm); + for (SchedulerListener schedulerListener : this.schedulerListeners) { + schedulerListener.algorithmUnscheduled(algorithm); } } public void schedulerCleared() { - for (Iterator iter = _schedulerListeners.iterator() ; iter.hasNext() ; ) { - SchedulerListener sl = (SchedulerListener) iter.next() ; - sl.schedulerCleared(); + for (SchedulerListener schedulerListener : this.schedulerListeners) { + schedulerListener.schedulerCleared(); } } public void schedulerRunStateChanged(boolean isRunning) { - for (Iterator iter = _schedulerListeners.iterator() ; iter.hasNext() ; ) { - SchedulerListener sl = (SchedulerListener) iter.next() ; - sl.schedulerRunStateChanged(isRunning); + for (SchedulerListener schedulerListener : this.schedulerListeners) { + schedulerListener.schedulerRunStateChanged(isRunning); } } } -class AlgSchedulerTask extends TimerTask implements SchedulerListener { +class AlgorithmSchedulerTask extends TimerTask implements SchedulerListener { + public static final int AS_MANY_SIMULTANEOUS_ALGORITHMS_AS_NEEDED = -1; + private Map<Algorithm, AlgorithmTask> tasksByAlgorithms; + private Map<Algorithm, ServiceReference> serviceReferencesByAlgorithms; + private volatile boolean isRunning = true; + private volatile int runningTaskCount = 0; + private SchedulerListener schedulerListener; + private int maxSimultaneousAlgorithms = AS_MANY_SIMULTANEOUS_ALGORITHMS_AS_NEEDED; - private Map _algMap; - private Map _algServiceMap; - private volatile boolean _running = true; - - // Default allow as many as needed - private int _maxSimultaneousAlgs = -1; - /** * Maximum number of algorithms allowed to run simultaneously. This value * can be changed at runtime without any problems. Negative values are * interpreted to mean 'no limit'. * * @param max - * The maximum number of algorithms that can be simultaneously - * run. + * The maximum number of algorithms that can be simultaneously run. */ - public synchronized final void setMaxSimultaneousAlgs(final int max) { - if (max < -1) - this._maxSimultaneousAlgs = -1; - else - this._maxSimultaneousAlgs = max; + public synchronized final void setMaxSimultaneousAlgorithms(final int max) { + if (max < -1) { + this.maxSimultaneousAlgorithms = AS_MANY_SIMULTANEOUS_ALGORITHMS_AS_NEEDED; + } else { + this.maxSimultaneousAlgorithms = max; + } } public synchronized Algorithm[] getScheduledAlgorithms() { - return (Algorithm[]) _algMap.keySet().toArray(new Algorithm[0]); + return this.tasksByAlgorithms.keySet().toArray(new Algorithm[0]); } public synchronized final boolean isEmpty() { - return _algMap.size() == 0; + return this.tasksByAlgorithms.size() == 0; } public synchronized final int numRunning() { - return _numRunning; + return this.runningTaskCount; } - private SchedulerListener _schedulerListener; - - public AlgSchedulerTask(SchedulerListener listener) { - _algMap = Collections.synchronizedMap(new HashMap()); - _algServiceMap = new HashMap(); - setSchedulerListener(listener); + public AlgorithmSchedulerTask(SchedulerListener listener) { + this.tasksByAlgorithms = + Collections.synchronizedMap(new HashMap<Algorithm, AlgorithmTask>()); + this.serviceReferencesByAlgorithms = new HashMap<Algorithm, ServiceReference>(); + this.setSchedulerListener(listener); } public synchronized final void setSchedulerListener(SchedulerListener listener) { - _schedulerListener = listener; + this.schedulerListener = listener; } public final ServiceReference getServiceReference(Algorithm algorithm) { - return (ServiceReference) _algServiceMap.get(algorithm); + return this.serviceReferencesByAlgorithms.get(algorithm); } public synchronized final Calendar getScheduledTime(Algorithm algorithm) { - AlgorithmTask task = (AlgorithmTask)_algMap.get(algorithm); + AlgorithmTask task = this.tasksByAlgorithms.get(algorithm); + if (task != null) { return task.getScheduledTime(); } else { @@ -372,10 +357,13 @@ } } - public synchronized final boolean cancel(Algorithm alg) { - AlgorithmTask task = (AlgorithmTask) this._algMap.get(alg); - if (task == null) + public synchronized final boolean cancel(Algorithm algorithm) { + AlgorithmTask task = this.tasksByAlgorithms.get(algorithm); + + if (task == null) { return false; + } + // The algorithm will run till the end and // then stop so there's no real way to cancel running algorithms. // Clients should always check the state of an algorithm before trying @@ -384,23 +372,23 @@ } public synchronized final void schedule(Algorithm alg, ServiceReference ref, Calendar time) { - AlgorithmTask task = (AlgorithmTask) this._algMap.get(alg); + AlgorithmTask task = this.tasksByAlgorithms.get(alg); // If alg already exists, do some checks... if (task != null) { - STATE state = task.getState(); + AlgorithmState state = task.getState(); // If its still running, we can't schedule it again. - if (state.equals(STATE.RUNNING)) { + if (state.equals(AlgorithmState.RUNNING)) { throw new RuntimeException( "Cannot schedule running algorithm. Check state of algorithm first."); } // If its new or waiting to run, we refuse to schedule it to force // user to explicitly // cancel and reschedule. - else if (state.equals(STATE.NEW)) { + else if (state.equals(AlgorithmState.NEW)) { throw new RuntimeException( "Algorithm is already scheduled to run. Cancel existing schedule first."); } - else if (state.equals(STATE.STOPPED)) { + else if (state.equals(AlgorithmState.STOPPED)) { // If it was stopped but not cleaned up yet, clean it up purgeFinished(); } @@ -414,21 +402,21 @@ } public synchronized final int getMaxSimultaneousAlgs() { - return this._maxSimultaneousAlgs; + return this.maxSimultaneousAlgorithms; } public synchronized final void registerAlgorithmTask(Algorithm algorithm, AlgorithmTask algorithmTask) { - this._algServiceMap.put(algorithm, algorithmTask.getServiceReference()); - this._algMap.put(algorithm, algorithmTask); + this.serviceReferencesByAlgorithms.put(algorithm, algorithmTask.getServiceReference()); + this.tasksByAlgorithms.put(algorithm, algorithmTask); } /** - * @param alg + * @param algorithm * The algorithm whose state we want to query. * @return State of the specified algorithm. */ - public synchronized final STATE getAlgorithmState(Algorithm alg) { - AlgorithmTask task = (AlgorithmTask) this._algMap.get(alg); + public synchronized final AlgorithmState getAlgorithmState(Algorithm algorithm) { + AlgorithmTask task = this.tasksByAlgorithms.get(algorithm); if (task == null) throw new NoSuchElementException("Algorithm doesn't exist."); return task.getState(); @@ -439,92 +427,95 @@ */ public synchronized final void purgeFinished() { synchronized (this) { - Iterator iter = this._algMap - .entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = (Map.Entry) iter.next(); - AlgorithmTask task = (AlgorithmTask) entry.getValue(); - if (task.getState() == STATE.STOPPED) { - iter.remove(); - _algServiceMap.remove(entry.getKey()); + Iterator<Map.Entry<Algorithm, AlgorithmTask>> entries = + this.tasksByAlgorithms.entrySet().iterator(); + + while (entries.hasNext()) { + Map.Entry<Algorithm, AlgorithmTask> entry = entries.next(); + AlgorithmTask task = entry.getValue(); + + if (task.getState() == AlgorithmState.STOPPED) { + entries.remove(); + this.serviceReferencesByAlgorithms.remove(entry.getKey()); } } } } - private synchronized final boolean _limitReached() { - return (_maxSimultaneousAlgs != -1) - && (_numRunning >= _maxSimultaneousAlgs); + private synchronized final boolean limitReached() { + return + (this.maxSimultaneousAlgorithms != AS_MANY_SIMULTANEOUS_ALGORITHMS_AS_NEEDED) && + (this.runningTaskCount >= this.maxSimultaneousAlgorithms); } public void setRunning(boolean isRunning) { - _running = isRunning; + this.isRunning = isRunning; } public boolean isRunning() { - return _running; + return this.isRunning; } public void run() { - if (_running) { + if (this.isRunning) { synchronized (this) { // If we are running the max allowable, wait until next turn. Date now = Calendar.getInstance().getTime(); // Iterate through algorithms. - Collection tasks = this._algMap.values(); - for (Iterator iter = tasks.iterator() ; iter.hasNext() ;) { - AlgorithmTask task = (AlgorithmTask) iter.next() ; - if (_limitReached()) + Collection<AlgorithmTask> tasks = this.tasksByAlgorithms.values(); + + for (AlgorithmTask task : tasks) { + if (limitReached()) { return; - if ((task.getState() == STATE.NEW) + } + + if ((task.getState() == AlgorithmState.NEW) && now.compareTo(task.getScheduledTime().getTime()) >= 0) { - // Run immediately + // Run immediately. task.start(); } } } } } - - private volatile int _numRunning = 0; public synchronized void algorithmScheduled(Algorithm algorithm, Calendar time) { - _schedulerListener.algorithmScheduled(algorithm, time); + this.schedulerListener.algorithmScheduled(algorithm, time); } public synchronized void algorithmStarted(Algorithm algorithm) { - _numRunning++; - _schedulerListener.algorithmStarted(algorithm); + this.runningTaskCount++; + this.schedulerListener.algorithmStarted(algorithm); } public synchronized void algorithmError(Algorithm algorithm, Throwable error) { - _numRunning--; - _schedulerListener.algorithmError(algorithm, error); + this.runningTaskCount--; + this.schedulerListener.algorithmError(algorithm, error); purgeFinished(); } public synchronized void algorithmFinished(Algorithm algorithm, Data[] createdDM) { - _numRunning--; - _schedulerListener.algorithmFinished(algorithm, createdDM); + this.runningTaskCount--; + this.schedulerListener.algorithmFinished(algorithm, createdDM); purgeFinished(); } public synchronized void algorithmRescheduled(Algorithm algorithm, Calendar time) { - _schedulerListener.algorithmRescheduled(algorithm, time); + this.schedulerListener.algorithmRescheduled(algorithm, time); } public synchronized void algorithmUnscheduled(Algorithm algorithm) { - _schedulerListener.algorithmUnscheduled(algorithm); + this.schedulerListener.algorithmUnscheduled(algorithm); } public synchronized void schedulerCleared() { - _schedulerListener.schedulerCleared(); + this.schedulerListener.schedulerCleared(); } public synchronized void schedulerRunStateChanged(boolean isRunning) { - _schedulerListener.schedulerRunStateChanged(isRunning); + this.schedulerListener.schedulerRunStateChanged(isRunning); } } @@ -542,147 +533,196 @@ // May 8, 2006 7:19:00 PM Shashikant Penumarthy: Initial implementation. //July 19, 2006 10:45:00 AM Bruce Herr: Ported to new CIShell class AlgorithmTask implements Runnable { - /** * The states in which algorithm tasks can exist. * * @author Team IVC */ - static final class STATE { - private String _name ; - public STATE(String name) { - this._name = name ; - } - public final boolean equals(Object object) { - if (! (object instanceof STATE)) - return false ; - STATE state = (STATE) object ; - return state._name.compareTo(_name) == 0; - } - /** New algorithms are in this state. */ - public static final STATE NEW = new STATE("NEW") ; - /** Running algorithms are in this state. */ - public static final STATE RUNNING = new STATE("RUNNING") ; - /** Algorithms either cancelled or finished are in this state. */ - public static final STATE STOPPED = new STATE("STOPPED") ; - /** Algorithm had an error while executing */ - public static final STATE ERROR = new STATE("ERROR"); - } + private volatile boolean isCanceled = false; + private final Algorithm algorithm; - private volatile boolean _noRun = false; + /* NOTE: TimerTask keeps its own schedule variable which can be retrieved using + * scheduledExecutionTime() method. We don't use that here. + */ + private final Calendar scheduledTime; + private final ServiceReference serviceReference; + private volatile AlgorithmState state; + // Execution status of the algorithm (i.e.) return value. + private Data[] result; + + // The exception thrown, if an algorithm had one while executing. + private Exception exceptionThrown; + + // Deliberately allow only one listener. Its not the algorithms job to do all the informing. + private SchedulerListener schedulerListener; + public synchronized final boolean cancel() { - if (_noRun) + if (this.isCanceled) { return true; - if (_state.equals(STATE.RUNNING)) + } + + if (this.state.equals(AlgorithmState.RUNNING)) { return false; - _state = STATE.STOPPED; - _noRun = true; - return _noRun; + } + + this.state = AlgorithmState.STOPPED; + this.isCanceled = true; + + return this.isCanceled; } public synchronized final void start() { - if (_noRun) + if (this.isCanceled) { return; - _setState(STATE.RUNNING); + } + + setState(AlgorithmState.RUNNING); new Thread(this).start(); } - private final Algorithm _alg; + public AlgorithmTask( + Algorithm algorithm, + ServiceReference serviceReference, + Calendar scheduledTime, + AlgorithmSchedulerTask algorithmSchedulerTask) { + this.algorithm = algorithm; + this.serviceReference = serviceReference; + this.scheduledTime = scheduledTime; + this.schedulerListener = algorithmSchedulerTask; - // NOTE: TimerTask keeps its own schedule variable which can be retrieved - // using scheduledExecutionTime() method. We don't use that here. - private final Calendar _scheduledTime; - - private final ServiceReference _ref; - - private volatile STATE _state; - - /** - * Execution status of the algorithm (i.e.) return value. - */ - private Data[] _result; - - /** - * The error, if an algorithm had one while executing - */ - private Exception _error; - - /** - * Deliberately allow only one listener. Its not the algorithms job to do - * all the informing. - */ - private SchedulerListener _schedulerListener; - - public AlgorithmTask(Algorithm alg, ServiceReference ref, Calendar scheduledTime, - //SchedulerListener listener) { - AlgSchedulerTask algSchedulerTask) { - _alg = alg; - _ref = ref; - _scheduledTime = scheduledTime; - _schedulerListener = algSchedulerTask; - algSchedulerTask.registerAlgorithmTask(alg, this); - _init(); + algorithmSchedulerTask.registerAlgorithmTask(algorithm, this); + init(); } public synchronized final Calendar getScheduledTime() { - // Do a defensive copy cuz we don't want clients changing - // the time using this reference! + /* Do a defensive copy because we don't want clients changing the time using + * this reference! + */ Calendar calendar = Calendar.getInstance(); - calendar.setTime(this._scheduledTime.getTime()); + calendar.setTime(this.scheduledTime.getTime()); + return calendar; } public synchronized final ServiceReference getServiceReference() { - return _ref; + return this.serviceReference; } - private final void _init() { - _result = null; - _setState(STATE.NEW); + private final void init() { + this.result = null; + setState(AlgorithmState.NEW); } public synchronized final Data[] getResult() { - return _result; + return this.result; } - private synchronized final void _setState(STATE state) { - this._state = state; - // Inform listeners - if (_schedulerListener != null) { - if (this._state.equals(STATE.NEW)) { - _schedulerListener.algorithmScheduled(_alg, _scheduledTime); - } - else if (this._state.equals(STATE.RUNNING)) { - _schedulerListener.algorithmStarted(_alg); - } - else if (this._state.equals(STATE.STOPPED)) { - _noRun = true; - _schedulerListener.algorithmFinished(_alg, getResult()); - } - else if (this._state.equals(STATE.ERROR)) { - _noRun = true; - _schedulerListener.algorithmError(_alg, _error); - } - else { - throw new IllegalStateException( - "Encountered illegal algorithm state: " + _state); - } + private synchronized final void setState(AlgorithmState state) { + this.state = state; + // Inform listeners. + if (this.schedulerListener != null) { + this.state.performAction( + algorithm, + this.schedulerListener, + this.scheduledTime, + getResult(), + this.exceptionThrown); + this.isCanceled = this.state.isCanceledNow(); } } - public synchronized final STATE getState() { - return this._state; + public synchronized final AlgorithmState getState() { + return this.state; } public void run() { try { - _result = _alg.execute(); + this.result = this.algorithm.execute(); } catch (Exception e) { - _error = e; - _setState(STATE.ERROR); + this.exceptionThrown = e; + setState(AlgorithmState.ERROR); } finally { - _setState(STATE.STOPPED); + setState(AlgorithmState.STOPPED); } } + + static class AlgorithmState { + /** New algorithms are in this state. */ + public static final AlgorithmState NEW = new AlgorithmState("NEW", false) { + public void performAction( + Algorithm algorithm, + SchedulerListener schedulerListener, + Calendar scheduledTime, + Data[] result, + Exception exceptionThrown) { + schedulerListener.algorithmScheduled(algorithm, scheduledTime); + } + }; + + /** Running algorithms are in this state. */ + public static final AlgorithmState RUNNING = new AlgorithmState("RUNNING", false) { + public void performAction( + Algorithm algorithm, + SchedulerListener schedulerListener, + Calendar scheduledTime, + Data[] result, + Exception exceptionThrown) { + schedulerListener.algorithmStarted(algorithm); + } + }; + /** Algorithms either cancelled or finished are in this state. */ + public static final AlgorithmState STOPPED = new AlgorithmState("STOPPED", true) { + public void performAction( + Algorithm algorithm, + SchedulerListener schedulerListener, + Calendar scheduledTime, + Data[] result, + Exception exceptionThrown) { + schedulerListener.algorithmFinished(algorithm, result); + } + }; + /** Algorithm had an exceptionThrown while executing */ + public static final AlgorithmState ERROR = new AlgorithmState("ERROR", true) { + public void performAction( + Algorithm algorithm, + SchedulerListener schedulerListener, + Calendar scheduledTime, + Data[] result, + Exception exceptionThrown) { + schedulerListener.algorithmError(algorithm, exceptionThrown); + } + }; + + private String name; + private boolean isCanceled; + + public AlgorithmState(String name, boolean isCanceled) { + this.name = name; + this.isCanceled = isCanceled; + } + + public final boolean equals(Object object) { + if (!(object instanceof AlgorithmState)) { + return false; + } + + AlgorithmState state = (AlgorithmState) object; + + return state.name.compareTo(name) == 0; + } + + public void performAction( + Algorithm algorithm, + SchedulerListener schedulerListener, + Calendar scheduledTime, + Data[] result, + Exception exceptionThrown) { + throw new IllegalStateException("Encountered illegal algorithm state: " + this); + } + + public boolean isCanceledNow() { + return this.isCanceled; + } + } } Modified: trunk/core/org.cishell.reference.services/src/org/cishell/reference/services/Activator.java =================================================================== --- trunk/core/org.cishell.reference.services/src/org/cishell/reference/services/Activator.java 2010-08-03 18:35:25 UTC (rev 1107) +++ trunk/core/org.cishell.reference.services/src/org/cishell/reference/services/Activator.java 2010-08-03 19:15:24 UTC (rev 1108) @@ -15,36 +15,46 @@ import org.osgi.framework.ServiceRegistration; public class Activator implements BundleActivator { - private ServiceRegistration conversionReg; - private ServiceRegistration schedulerReg; - private ServiceRegistration dataManagerReg; + private ServiceRegistration conversionRegistration; + private ServiceRegistration schedulerRegistration; + private ServiceRegistration dataManagerRegistration; +// private ServiceRegistration algorithmInvokerRegistration; /** * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */ - public void start(BundleContext bContext) throws Exception { - CIShellContext ciContext = new LocalCIShellContext(bContext); + public void start(BundleContext bundleContext) throws Exception { + CIShellContext ciShellContext = new LocalCIShellContext(bundleContext); - DataConversionService conversionService = - new DataConversionServiceImpl(bContext, ciContext); - conversionReg = bContext.registerService( - DataConversionService.class.getName(), conversionService, new Hashtable()); + DataConversionService conversionService = + new DataConversionServiceImpl(bundleContext, ciShellContext); + this.conversionRegistration = bundleContext.registerService( + DataConversionService.class.getName(), + conversionService, + new Hashtable<String, Object>()); SchedulerService scheduler = new SchedulerServiceImpl(); - schedulerReg = bContext.registerService( - SchedulerService.class.getName(), scheduler, new Hashtable()); + this.schedulerRegistration = bundleContext.registerService( + SchedulerService.class.getName(), scheduler, new Hashtable<String, Object>()); DataManagerService dataManager = new DataManagerServiceImpl(); - dataManagerReg = bContext.registerService( - DataManagerService.class.getName(), dataManager, new Hashtable()); + this.dataManagerRegistration = bundleContext.registerService( + DataManagerService.class.getName(), dataManager, new Hashtable<String, Object>()); + +// AlgorithmInvocationService algorithmInvoker = new AlgorithmInvocationServiceImpl(); +// this.algorithmInvokerRegistration = bundleContext.registerService( +// AlgorithmInvocationService.class.getName(), +// algorithmInvoker, +// new Hashtable<String, Object>()); } /** * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ - public vo... [truncated message content] |
From: <pat...@us...> - 2010-08-05 19:44:52
|
Revision: 1118 http://cishell.svn.sourceforge.net/cishell/?rev=1118&view=rev Author: pataphil Date: 2010-08-05 19:44:46 +0000 (Thu, 05 Aug 2010) Log Message: ----------- * Changed org.cishell.utilities.datastructure to org.cishell.utility.datastructure. Added Paths: ----------- trunk/core/org.cishell.utility.datastructure/ Removed Paths: ------------- trunk/core/org.cishell.utilities.datastructure/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pat...@us...> - 2011-02-11 13:26:24
|
Revision: 1203 http://cishell.svn.sourceforge.net/cishell/?rev=1203&view=rev Author: pataphil Date: 2011-02-11 13:26:16 +0000 (Fri, 11 Feb 2011) Log Message: ----------- * Added loadFileOfType methods to FileLoaderService and implementation. * Removed AlgorithmFactory2 * Potential redesign of AlgorithmInvocationService? Modified Paths: -------------- trunk/core/org.cishell.framework/META-INF/MANIFEST.MF trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoaderService.java trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java trunk/core/org.cishell.reference/META-INF/MANIFEST.MF trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/datamanager/DataManagerServiceImpl.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileLoaderServiceImpl.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/PrettyLabeler.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/ValidatorSelectorRunnable.java Added Paths: ----------- trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/FakeAlgorithmInvocationService.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/FakeAlgorithmInvocationServiceImpl.java Removed Paths: ------------- trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmFactory2.java Modified: trunk/core/org.cishell.framework/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.framework/META-INF/MANIFEST.MF 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.framework/META-INF/MANIFEST.MF 2011-02-11 13:26:16 UTC (rev 1203) @@ -17,6 +17,7 @@ org.cishell.framework.algorithm;version="1.0.0", org.cishell.framework.data;version="1.0.0", org.cishell.framework.userprefs;version="1.0.0", + org.cishell.service.algorithminvocation, org.cishell.service.conversion;version="1.0.0", org.cishell.service.guibuilder;version="1.0.0" Bundle-ActivationPolicy: lazy Modified: trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoaderService.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoaderService.java 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoaderService.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -3,6 +3,7 @@ import java.io.File; import org.cishell.framework.CIShellContext; +import org.cishell.framework.algorithm.AlgorithmFactory; import org.cishell.framework.algorithm.ProgressMonitor; import org.cishell.framework.data.Data; import org.osgi.framework.BundleContext; @@ -29,4 +30,19 @@ LogService logger, ProgressMonitor progressMonitor, File file) throws FileLoadException; + public Data[] loadFileOfType( + BundleContext bundleContext, + CIShellContext ciShellContext, + LogService logger, + ProgressMonitor progressMonitor, + File file, + String fileExtension, + String mimeType) throws FileLoadException; + public Data[] loadFileOfType( + BundleContext bundleContext, + CIShellContext ciShellContext, + LogService logger, + ProgressMonitor progressMonitor, + File file, + AlgorithmFactory validator) throws FileLoadException; } \ No newline at end of file Deleted: trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmFactory2.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmFactory2.java 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.framework/src/org/cishell/framework/algorithm/AlgorithmFactory2.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -1,7 +0,0 @@ -package org.cishell.framework.algorithm; - -import org.osgi.framework.ServiceReference; - -public interface AlgorithmFactory2 { - public void setServiceReference(ServiceReference serviceReference); -} \ No newline at end of file Modified: trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -1,126 +1,20 @@ +package org.cishell.service.algorithminvocation; -/* TODO: When we have time, we should talk about the design of the Algorithm Invocation Service (if - * we even use that name in the end). - * It's somewhat apparent that there is a use for this service, but exactly how it fits into - * CIShell and all of the tools remains to be fully clarified. - * This is all commented out for now because the design/use need discussion. - */ +import java.util.Dictionary; -//package org.cishell.service.algorithminvocation; -// -//import java.util.Dictionary; -// -//import org.cishell.framework.CIShellContext; -//import org.cishell.framework.algorithm.Algorithm; -//import org.cishell.framework.algorithm.AlgorithmCanceledException; -//import org.cishell.framework.algorithm.AlgorithmCreationCanceledException; -//import org.cishell.framework.algorithm.AlgorithmCreationFailedException; -//import org.cishell.framework.algorithm.AlgorithmExecutionException; -//import org.cishell.framework.algorithm.AlgorithmFactory; -//import org.cishell.framework.data.Data; -// -///** -// * Provides the caller with various ways of creating algorithms, executing them, and -// * gathering/mutating parameters. -// * When creating an algorithm (from a factory), if the factory implements ParameterMutator, -// * mutateParameters() will be called on it. -// * All methods can optionally operate on a new thread, which is determined by shouldUseNewThread. -// */ -//public interface AlgorithmInvocationService { -// /** -// * Uses factory to create an algorithm, presenting the user with a GUI for parameters. -// */ -// public Algorithm createAlgorithm( -// final AlgorithmFactory factory, -// final Data[] data, -// final CIShellContext ciShellContext, -// boolean shouldUseNewThread) -// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException; -// -// /** -// * Uses factory to create an algorithm, using parameters (instead of presenting the user with a -// * GUI for them). -// */ -// public Algorithm createAlgorithm( -// final AlgorithmFactory factory, -// final Data[] data, -// final Dictionary<String, Object> parameters, -// final CIShellContext ciShellContext, -// boolean shouldUseNewThread) -// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException; -// -// /** -// * Invokes algorithm, returning the Data[] result of algorithm.execute(). -// * If logExceptionThrown is true, any exception thrown will be logged to the -// * default LogService. -// * If displayRuntimeException is true, the stack trace of any exception thrown will be -// * displayed in an error message box. -// */ -// public Data[] invokeAlgorithm( -// final Algorithm algorithm, -// final boolean logExceptionThrown, -// final boolean displayRuntimeException, -// boolean shouldUseNewThread) -// throws AlgorithmCanceledException, AlgorithmExecutionException; -// -// /** -// * Invokes algorithm, assuming sensible defaults for inline algorithm execution (that is, -// * not explicitly invoked from a menu/etc.), and return the Data[] result of -// * algorithm.execute(). -// * Most likely wraps invokeAlgorithm(). -// */ -// public Data[] simpleInvokeAlgorithm(final Algorithm algorithm, Thread thread) -// throws AlgorithmCanceledException, AlgorithmExecutionException; -// -// /** -// * Given factory, presents the user with a GUI for parameters to use for creating and executing -// * an algorithm. -// * Most likely wraps createAlgorithm() and invokeAlgorithm(). -// */ -// public Data[] createAndInvokeAlgorithm( -// final AlgorithmFactory factory, -// final Data[] data, -// final CIShellContext ciShellContext, -// final boolean logExceptionThrown, -// final boolean displayRuntimeException, -// boolean shouldUseNewThread) throws -// AlgorithmCreationCanceledException, -// AlgorithmCreationFailedException, -// AlgorithmCanceledException, -// AlgorithmExecutionException; -// -// /** -// * Given factory, uses parameters to create and execute an algorithm. -// * Most likely wraps createAlgorithm() and invokeAlgorithm(). -// */ -// public Data[] createAndInvokeAlgorithm( -// final AlgorithmFactory factory, -// final Data[] data, -// final Dictionary<String, Object> parameters, -// final CIShellContext ciShellContext, -// final boolean logExceptionThrown, -// final boolean displayRuntimeException, -// boolean shouldUseNewThread) throws -// AlgorithmCreationCanceledException, -// AlgorithmCreationFailedException, -// AlgorithmCanceledException, -// AlgorithmExecutionException; -// -// /** -// * Given factory, uses parameters to create and execute an algorithm. -// * Sensible defaults for inline algorithm execution (that is, not explicitly invoked from a -// * menu/etc.) are used. -// * Returns the Data[] result of algorithm.execute(). -// * Most likely wraps createAlgorithm() and simpleInvokeAlgorithm(). -// */ -// public Data[] simpleCreateAndInvokeAlgorithm( -// final AlgorithmFactory factory, -// final Data[] data, -// final Dictionary<String, Object> parameters, -// CIShellContext ciShellContext, -// boolean shouldUseNewThread) throws -// AlgorithmCreationCanceledException, -// AlgorithmCreationFailedException, -// AlgorithmCanceledException, -// AlgorithmExecutionException; -//} \ No newline at end of file +import org.cishell.framework.CIShellContext; +import org.cishell.framework.algorithm.AlgorithmExecutionException; +import org.cishell.framework.data.Data; +import org.osgi.framework.ServiceReference; + +public interface AlgorithmInvocationService { + public Data[] runAlgorithm(String pid, Data[] inputData) throws AlgorithmExecutionException; + public Data[] wrapAlgorithm( + String pid, + CIShellContext callerCIShellContext, + Data[] inputData, + Dictionary<String, Object> parameters) throws AlgorithmExecutionException; + + public ServiceReference createUniqueServiceReference(ServiceReference actualServiceReference); + public CIShellContext createUniqueCIShellContext(ServiceReference uniqueServiceReference); +} \ No newline at end of file Copied: trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/FakeAlgorithmInvocationService.java (from rev 1194, trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/AlgorithmInvocationService.java) =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/FakeAlgorithmInvocationService.java (rev 0) +++ trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/FakeAlgorithmInvocationService.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -0,0 +1,126 @@ + +/* TODO: When we have time, we should talk about the design of the Algorithm Invocation Service (if + * we even use that name in the end). + * It's somewhat apparent that there is a use for this service, but exactly how it fits into + * CIShell and all of the tools remains to be fully clarified. + * This is all commented out for now because the design/use need discussion. + */ + +package org.cishell.service.algorithminvocation; + +import java.util.Dictionary; + +import org.cishell.framework.CIShellContext; +import org.cishell.framework.algorithm.Algorithm; +import org.cishell.framework.algorithm.AlgorithmCanceledException; +import org.cishell.framework.algorithm.AlgorithmCreationCanceledException; +import org.cishell.framework.algorithm.AlgorithmCreationFailedException; +import org.cishell.framework.algorithm.AlgorithmExecutionException; +import org.cishell.framework.algorithm.AlgorithmFactory; +import org.cishell.framework.data.Data; + +/** + * Provides the caller with various ways of creating algorithms, executing them, and + * gathering/mutating parameters. + * When creating an algorithm (from a factory), if the factory implements ParameterMutator, + * mutateParameters() will be called on it. + * All methods can optionally operate on a new thread, which is determined by shouldUseNewThread. + */ +public interface FakeAlgorithmInvocationService { + /** + * Uses factory to create an algorithm, presenting the user with a GUI for parameters. + */ + public Algorithm createAlgorithm( + final AlgorithmFactory factory, + final Data[] data, + final CIShellContext ciShellContext, + boolean shouldUseNewThread) + throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException; + + /** + * Uses factory to create an algorithm, using parameters (instead of presenting the user with a + * GUI for them). + */ + public Algorithm createAlgorithm( + final AlgorithmFactory factory, + final Data[] data, + final Dictionary<String, Object> parameters, + final CIShellContext ciShellContext, + boolean shouldUseNewThread) + throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException; + + /** + * Invokes algorithm, returning the Data[] result of algorithm.execute(). + * If logExceptionThrown is true, any exception thrown will be logged to the + * default LogService. + * If displayRuntimeException is true, the stack trace of any exception thrown will be + * displayed in an error message box. + */ + public Data[] invokeAlgorithm( + final Algorithm algorithm, + final boolean logExceptionThrown, + final boolean displayRuntimeException, + boolean shouldUseNewThread) + throws AlgorithmCanceledException, AlgorithmExecutionException; + + /** + * Invokes algorithm, assuming sensible defaults for inline algorithm execution (that is, + * not explicitly invoked from a menu/etc.), and return the Data[] result of + * algorithm.execute(). + * Most likely wraps invokeAlgorithm(). + */ + public Data[] simpleInvokeAlgorithm(final Algorithm algorithm, Thread thread) + throws AlgorithmCanceledException, AlgorithmExecutionException; + + /** + * Given factory, presents the user with a GUI for parameters to use for creating and executing + * an algorithm. + * Most likely wraps createAlgorithm() and invokeAlgorithm(). + */ + public Data[] createAndInvokeAlgorithm( + final AlgorithmFactory factory, + final Data[] data, + final CIShellContext ciShellContext, + final boolean logExceptionThrown, + final boolean displayRuntimeException, + boolean shouldUseNewThread) throws + AlgorithmCreationCanceledException, + AlgorithmCreationFailedException, + AlgorithmCanceledException, + AlgorithmExecutionException; + + /** + * Given factory, uses parameters to create and execute an algorithm. + * Most likely wraps createAlgorithm() and invokeAlgorithm(). + */ + public Data[] createAndInvokeAlgorithm( + final AlgorithmFactory factory, + final Data[] data, + final Dictionary<String, Object> parameters, + final CIShellContext ciShellContext, + final boolean logExceptionThrown, + final boolean displayRuntimeException, + boolean shouldUseNewThread) throws + AlgorithmCreationCanceledException, + AlgorithmCreationFailedException, + AlgorithmCanceledException, + AlgorithmExecutionException; + + /** + * Given factory, uses parameters to create and execute an algorithm. + * Sensible defaults for inline algorithm execution (that is, not explicitly invoked from a + * menu/etc.) are used. + * Returns the Data[] result of algorithm.execute(). + * Most likely wraps createAlgorithm() and simpleInvokeAlgorithm(). + */ + public Data[] simpleCreateAndInvokeAlgorithm( + final AlgorithmFactory factory, + final Data[] data, + final Dictionary<String, Object> parameters, + CIShellContext ciShellContext, + boolean shouldUseNewThread) throws + AlgorithmCreationCanceledException, + AlgorithmCreationFailedException, + AlgorithmCanceledException, + AlgorithmExecutionException; +} \ No newline at end of file Property changes on: trunk/core/org.cishell.framework/src/org/cishell/service/algorithminvocation/FakeAlgorithmInvocationService.java ___________________________________________________________________ Added: svn:mergeinfo + Modified: trunk/core/org.cishell.reference/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.reference/META-INF/MANIFEST.MF 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.reference/META-INF/MANIFEST.MF 2011-02-11 13:26:16 UTC (rev 1203) @@ -9,6 +9,7 @@ org.cishell.framework.algorithm;version="1.0.0", org.cishell.framework.data;version="1.0.0", org.cishell.reference.gui.common, + org.cishell.service.algorithminvocation, org.cishell.service.conversion;version="1.0.0", org.cishell.service.guibuilder;version="1.0.0", org.osgi.framework, Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -1,85 +1,35 @@ -//package org.cishell.reference.app.service.algorithminvocation; -// -//import java.util.Dictionary; -//import java.util.Hashtable; -// -//import org.cishell.framework.CIShellContext; -//import org.cishell.framework.algorithm.Algorithm; -//import org.cishell.framework.algorithm.AlgorithmCreationCanceledException; -//import org.cishell.framework.algorithm.AlgorithmCreationFailedException; -//import org.cishell.framework.algorithm.AlgorithmFactory; -//import org.cishell.framework.data.Data; -//import org.cishell.service.algorithminvocation.AlgorithmInvocationService; -//import org.osgi.service.log.LogService; -// -//public class AlgorithmInvocationServiceImpl implements AlgorithmInvocationService { -// private LogService logger; -// -// public AlgorithmInvocationServiceImpl(LogService logger) { -// this.logger = logger; -// } -// -// @SuppressWarnings("unchecked") -// public Algorithm createAlgorithm( -// final AlgorithmFactory factory, -// final Data[] data, -// final CIShellContext ciShellContext, -// boolean shouldUseNewThread) -// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException { -// /* TODO: Refactor org.cishell.utilities into several plugins so there are no -// * circular dependencies! -// */ -// -// final AlgorithmCreationCanceledException[] canceledException = -// new AlgorithmCreationCanceledException[1]; -// final AlgorithmCreationFailedException[] failedException = -// new AlgorithmCreationFailedException[1]; -// final Algorithm[] algorithm = new Algorithm[1]; -// -// Runnable operator = new Runnable() { -// public void run() { -// /* TODO: Refactor algorithm creation code out of -// * org.cishell.reference.gui.menumanager, and call it here. -// */ -// -// try { -// // TODO: readFromMetadataFile -// Dictionary<String, Object> parameters = new Hashtable<String, Object>(); -// // TODO: mutateParameters -// Dictionary<String, Object> mutatedParameters = parameters; -// // TODO: Invoke GUI builder service, getting user-entered parameters. -// Dictionary<String, Object> userEnteredParameters = mutatedParameters; -// -// algorithm[0] = -// factory.createAlgorithm(data, userEnteredParameters, ciShellContext); -// } catch (AlgorithmCreationCanceledException e) { -// canceledException[0] = e; -// } catch (AlgorithmCreationFailedException e) { -// failedException[0] = e; -// } -// } -// }; -// -// if (shouldUseNewThread) { -// new Thread(operator).start(); -// } else { -// operator.run(); -// } -// -// return algorithm[0]; -// } -// -// public Algorithm createAlgorithm( -// final AlgorithmFactory factory, -// final Data[] data, -// final Dictionary<String, Object> parameters, -// final CIShellContext ciShellContext, -// boolean shouldUseNewThread) -// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException { -// final AlgorithmCreationCanceledException[] canceledException = -// new AlgorithmCreationCanceledException[1]; -// final AlgorithmCreationFailedException[] failedException = -// new AlgorithmCreationFailedException[1]; -// -// } -//} \ No newline at end of file +package org.cishell.reference.app.service.algorithminvocation; + +import java.util.Dictionary; + +import org.cishell.framework.CIShellContext; +import org.cishell.framework.algorithm.AlgorithmExecutionException; +import org.cishell.framework.data.Data; +import org.cishell.service.algorithminvocation.AlgorithmInvocationService; +import org.osgi.framework.ServiceReference; + +public class AlgorithmInvocationServiceImpl implements AlgorithmInvocationService { + public Data[] runAlgorithm(String pid, Data[] inputData) throws AlgorithmExecutionException { + // TODO: AlgorithmWrapper, etc. + return null; + } + + public Data[] wrapAlgorithm( + String pid, + CIShellContext callerCIShellContext, + Data[] inputData, + Dictionary<String, Object> parameters) throws AlgorithmExecutionException { + // TODO: Get the algorithm, call it, etc. + return null; + } + + public ServiceReference createUniqueServiceReference(ServiceReference actualServiceReference) { + // TODO + return null; + } + + public CIShellContext createUniqueCIShellContext(ServiceReference uniqueServiceReference) { + // TODO: + return null; + } +} \ No newline at end of file Copied: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/FakeAlgorithmInvocationServiceImpl.java (from rev 1191, trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/AlgorithmInvocationServiceImpl.java) =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/FakeAlgorithmInvocationServiceImpl.java (rev 0) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/FakeAlgorithmInvocationServiceImpl.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -0,0 +1,86 @@ +package org.cishell.reference.app.service.algorithminvocation; +//package org.cishell.reference.app.service.algorithminvocation; +// +//import java.util.Dictionary; +//import java.util.Hashtable; +// +//import org.cishell.framework.CIShellContext; +//import org.cishell.framework.algorithm.Algorithm; +//import org.cishell.framework.algorithm.AlgorithmCreationCanceledException; +//import org.cishell.framework.algorithm.AlgorithmCreationFailedException; +//import org.cishell.framework.algorithm.AlgorithmFactory; +//import org.cishell.framework.data.Data; +//import org.cishell.service.algorithminvocation.FakeAlgorithmInvocationService; +//import org.osgi.service.log.LogService; +// +//public class AlgorithmInvocationServiceImpl implements FakeAlgorithmInvocationService { +// private LogService logger; +// +// public AlgorithmInvocationServiceImpl(LogService logger) { +// this.logger = logger; +// } +// +// @SuppressWarnings("unchecked") +// public Algorithm createAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final CIShellContext ciShellContext, +// boolean shouldUseNewThread) +// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException { +// /* TODO: Refactor org.cishell.utilities into several plugins so there are no +// * circular dependencies! +// */ +// +// final AlgorithmCreationCanceledException[] canceledException = +// new AlgorithmCreationCanceledException[1]; +// final AlgorithmCreationFailedException[] failedException = +// new AlgorithmCreationFailedException[1]; +// final Algorithm[] algorithm = new Algorithm[1]; +// +// Runnable operator = new Runnable() { +// public void run() { +// /* TODO: Refactor algorithm creation code out of +// * org.cishell.reference.gui.menumanager, and call it here. +// */ +// +// try { +// // TODO: readFromMetadataFile +// Dictionary<String, Object> parameters = new Hashtable<String, Object>(); +// // TODO: mutateParameters +// Dictionary<String, Object> mutatedParameters = parameters; +// // TODO: Invoke GUI builder service, getting user-entered parameters. +// Dictionary<String, Object> userEnteredParameters = mutatedParameters; +// +// algorithm[0] = +// factory.createAlgorithm(data, userEnteredParameters, ciShellContext); +// } catch (AlgorithmCreationCanceledException e) { +// canceledException[0] = e; +// } catch (AlgorithmCreationFailedException e) { +// failedException[0] = e; +// } +// } +// }; +// +// if (shouldUseNewThread) { +// new Thread(operator).start(); +// } else { +// operator.run(); +// } +// +// return algorithm[0]; +// } +// +// public Algorithm createAlgorithm( +// final AlgorithmFactory factory, +// final Data[] data, +// final Dictionary<String, Object> parameters, +// final CIShellContext ciShellContext, +// boolean shouldUseNewThread) +// throws AlgorithmCreationCanceledException, AlgorithmCreationFailedException { +// final AlgorithmCreationCanceledException[] canceledException = +// new AlgorithmCreationCanceledException[1]; +// final AlgorithmCreationFailedException[] failedException = +// new AlgorithmCreationFailedException[1]; +// +// } +//} \ No newline at end of file Property changes on: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/algorithminvocation/FakeAlgorithmInvocationServiceImpl.java ___________________________________________________________________ Added: svn:mergeinfo + Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/datamanager/DataManagerServiceImpl.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/datamanager/DataManagerServiceImpl.java 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/datamanager/DataManagerServiceImpl.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -16,7 +16,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -27,85 +26,76 @@ public class DataManagerServiceImpl implements DataManagerService { - private Map modelToLabelMap; - private Map labelToModelMap; - private Map labelToNumOccurrences; - private Set models; - private Set selectedModels; - - private Set listeners; - - /** - * Creates a new BasicModelManager Object. - */ - public DataManagerServiceImpl() { - modelToLabelMap = new HashMap(); - labelToModelMap = new HashMap(); - labelToNumOccurrences = new HashMap(); - models = new HashSet(); - listeners = new HashSet(); - } + private Map<Data, String> datumToLabel = new HashMap<Data, String>(); + private Map<String, Data> labelToDatum = new HashMap<String, Data>(); + private Map<String, Integer> labelToOccurrenceCount = new HashMap<String, Integer>(); + private Set<Data> data = new HashSet<Data>(); + private Set<Data> selectedData = new HashSet<Data>(); + private Set<DataManagerListener> listeners = new HashSet<DataManagerListener>(); - /** - * @see edu.iu.iv.core.ModelManager#addData(java.lang.Object) - */ - public void addData(Data model) { - if(model == null){ + public void addData(Data datum) { + if (datum == null) { return; } - String label = (String)model.getMetadata().get(DataProperty.LABEL); - String type = (String)model.getMetadata().get(DataProperty.TYPE); + + String label = (String) datum.getMetadata().get(DataProperty.LABEL); + String type = (String) datum.getMetadata().get(DataProperty.TYPE); - if(type == null){ + if (type == null) { type = DataProperty.OTHER_TYPE; - model.getMetadata().put(DataProperty.TYPE, type); + datum.getMetadata().put(DataProperty.TYPE, type); } - //generate label if needed - if(label == null || label.equals("")){ - StackTraceElement[] stack = new Throwable().getStackTrace(); - - if (stack.length > 2) { - String className = stack[2].getClassName(); - int lastDot = className.lastIndexOf("."); - - if (className.length() > lastDot) { - lastDot++; - className = className.substring(lastDot); - - if (className.endsWith("Algorithm")) { - className = className.substring(0,className.lastIndexOf("Algorithm")); - } - - if (className.endsWith("Factory")) { - className = className.substring(0,className.lastIndexOf("Factory")); - } - } - label = className; - } else { - label = "Unknown"; - } - - label = label + "." + type; + // Generate label if needed. + if ((label == null) || "".equals(label)) { + label = generateDefaultLabel(type); } - addModel(model, label); - - for (Iterator iter=listeners.iterator(); iter.hasNext();) { - ((DataManagerListener) iter.next()).dataAdded(model, label); + addModel(datum, label); + + for (DataManagerListener listener : this.listeners) { + listener.dataAdded(datum, label); } } - private void addModel(Data model, String label) { + private void addModel(Data datum, String label) { label = findUniqueLabel(label); - model.getMetadata().put(DataProperty.LABEL, label); - //set the model to be unsaved initially - model.getMetadata().put(DataProperty.MODIFIED, new Boolean(true)); + datum.getMetadata().put(DataProperty.LABEL, label); + // Set the model to be unsaved initially. + datum.getMetadata().put(DataProperty.MODIFIED, new Boolean(true)); - modelToLabelMap.put(model, label); - labelToModelMap.put(label, model); - models.add(model); + this.datumToLabel.put(datum, label); + this.labelToDatum.put(label, datum); + this.data.add(datum); } + + private String generateDefaultLabel(String dataType) { + String label; + StackTraceElement[] stack = new Throwable().getStackTrace(); + + if (stack.length > 2) { + String className = stack[2].getClassName(); + int lastDot = className.lastIndexOf("."); + + if (className.length() > lastDot) { + lastDot++; + className = className.substring(lastDot); + + if (className.endsWith("Algorithm")) { + className = className.substring(0,className.lastIndexOf("Algorithm")); + } + + if (className.endsWith("Factory")) { + className = className.substring(0,className.lastIndexOf("Factory")); + } + } + label = className; + } else { + label = "Unknown"; + } + + return String.format("%s.%s", label, dataType); + } /** * Ensures that the label is unique by comparing it to the labels @@ -117,16 +107,17 @@ */ private String findUniqueLabel(String label) { - Integer numOccurences = (Integer) labelToNumOccurrences.get(label); + Integer occurenceCount = this.labelToOccurrenceCount.get(label); - if (numOccurences == null) { + if (occurenceCount == null) { //the label is unique - labelToNumOccurrences.put(label, new Integer(1)); + this.labelToOccurrenceCount.put(label, new Integer(1)); + return label; } else { - //the label is not unique - int numOccurrencesVal = numOccurences.intValue(); + // The label is not unique. + int numOccurrencesVal = occurenceCount.intValue(); int newNumOccurrencesVal = numOccurrencesVal + 1; @@ -146,8 +137,7 @@ /* * remember how many occurrences of the original label we have. */ - labelToNumOccurrences.put(label, - new Integer(newNumOccurrencesVal)); + this.labelToOccurrenceCount.put(label, new Integer(newNumOccurrencesVal)); /* * also, remember that we now have a new label which might be @@ -159,7 +149,7 @@ * of whatever.xml). Maybe not the best way to do this, but * it makes sense. */ - labelToNumOccurrences.put(newLabel, new Integer(1)); + this.labelToOccurrenceCount.put(newLabel, new Integer(1)); return newLabel; } @@ -206,69 +196,65 @@ } - public void removeData(Data model) { - String label = getLabel(model); + public void removeData(Data datum) { + String label = getLabel(datum); - labelToModelMap.remove(label); - modelToLabelMap.remove(model); - labelToNumOccurrences.remove(label); - models.remove(model); - - for (Iterator iter=listeners.iterator(); iter.hasNext();) { - ((DataManagerListener) iter.next()).dataRemoved(model); + this.labelToDatum.remove(label); + this.datumToLabel.remove(datum); + this.labelToOccurrenceCount.remove(label); + this.data.remove(datum); + + for (DataManagerListener listener : this.listeners) { + listener.dataRemoved(datum); } } public Data[] getSelectedData() { - if (selectedModels == null) { - selectedModels = new HashSet(); - } - - return (Data[]) selectedModels.toArray(new Data[]{}); + return this.selectedData.toArray(new Data[0]); } - public void setSelectedData(Data[] inModels) { - selectedModels = new HashSet(Arrays.asList(inModels)); + public void setSelectedData(Data[] data) { + this.selectedData.clear(); + this.selectedData.addAll(Arrays.asList(data)); - for (int i=0; i < inModels.length; i++) { - if (!this.models.contains(inModels[i])) { - addData(inModels[i]); + for (int ii = 0; ii < data.length; ii++) { + if (!this.data.contains(data[ii])) { + addData(data[ii]); } } - - for (Iterator iter=listeners.iterator(); iter.hasNext();) { - ((DataManagerListener) iter.next()).dataSelected(inModels); + + for (DataManagerListener listener : this.listeners) { + listener.dataSelected(data); } } - private Data getModelForLabel(String label){ - return (Data)labelToModelMap.get(label); + private Data getModelForLabel(String label) { + return this.labelToDatum.get(label); } - public String getLabel(Data model){ - return (String)modelToLabelMap.get(model); + public String getLabel(Data datum) { + return this.datumToLabel.get(datum); } - public synchronized void setLabel(Data model, String label) { - label = findUniqueLabel(label); - - modelToLabelMap.put(model, label); - labelToModelMap.put(label, model); - - for (Iterator iter=listeners.iterator(); iter.hasNext();) { - ((DataManagerListener) iter.next()).dataLabelChanged(model, label); + public synchronized void setLabel(Data datum, String label) { + String uniqueLabel = findUniqueLabel(label); + this.datumToLabel.put(datum, uniqueLabel); + this.labelToDatum.put(uniqueLabel, datum); + + for (DataManagerListener listener : this.listeners) { + listener.dataLabelChanged(datum, label); } } public Data[] getAllData() { - return (Data[]) models.toArray(new Data[]{}); + return this.data.toArray(new Data[0]); } public void addDataManagerListener(DataManagerListener listener) { - listeners.add(listener); + this.listeners.add(listener); } public void removeDataManagerListener(DataManagerListener listener) { - listeners.remove(listener); + this.listeners.remove(listener); } } Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileLoaderServiceImpl.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileLoaderServiceImpl.java 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileLoaderServiceImpl.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -20,6 +20,8 @@ import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.osgi.framework.BundleContext; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedService; import org.osgi.service.log.LogService; @@ -89,6 +91,62 @@ bundleContext, ciShellContext, logger, progressMonitor, new File[] { file }); } + public Data[] loadFileOfType( + BundleContext bundleContext, + CIShellContext ciShellContext, + LogService logger, + ProgressMonitor progressMonitor, + File file, + String fileExtension, + String mimeType) throws FileLoadException { + try { + String format = + "(& " + + "(type=validator)" + + "(| (in_data=file-ext:%1$s) (also_validates=%1$s))" + + "(out_data=%2$s))"; + String validatorsQuery = String.format(format, fileExtension, mimeType); + ServiceReference[] supportingValidators = bundleContext.getAllServiceReferences( + AlgorithmFactory.class.getName(), validatorsQuery); + + if (supportingValidators == null) { + throw new FileLoadException(String.format( + "The file %s cannot be loaded as type %s.", file.getName(), mimeType)); + } else { + AlgorithmFactory validator = + (AlgorithmFactory) bundleContext.getService(supportingValidators[0]); + + return loadFileOfType( + bundleContext, ciShellContext, logger, progressMonitor, file, validator); + } + } catch (InvalidSyntaxException e) { + e.printStackTrace(); + + throw new FileLoadException(e.getMessage(), e); + } + } + + public Data[] loadFileOfType( + BundleContext bundleContext, + CIShellContext ciShellContext, + LogService logger, + ProgressMonitor progressMonitor, + File file, + AlgorithmFactory validator) throws FileLoadException { + try { + Data[] loadedFileData = loadFileInternal( + bundleContext, ciShellContext, logger, progressMonitor, file, validator); + + for (FileLoadListener listener : this.listeners) { + listener.fileLoaded(file); + } + + return loadedFileData; + } catch (AlgorithmExecutionException e) { + throw new FileLoadException(e.getMessage(), e); + } + } + public void updated(Dictionary preferences) throws ConfigurationException { if (preferences != null) { this.preferences = preferences; @@ -123,15 +181,26 @@ for (File file : files) { try { - Data[] validatedFileData = validateFile( + AlgorithmFactory validator = + getValidatorFromUser(bundleContext, window, display, file); + +// Data[] validatedFileData = validateFile( +// bundleContext, +// ciShellContext, +// logger, +// progressMonitor, +// window, +// display, +// file, +// validator); +// Data[] labeledFileData = labelFileData(file, validatedFileData); + Data[] labeledFileData = loadFileInternal( bundleContext, ciShellContext, logger, progressMonitor, - window, - display, - file); - Data[] labeledFileData = labelFileData(file, validatedFileData); + file, + validator); for (Data data : labeledFileData) { finalLabeledFileData.add(data); @@ -152,6 +221,29 @@ } } + private Data[] loadFileInternal( + BundleContext bundleContext, + CIShellContext ciShellContext, + LogService logger, + ProgressMonitor progressMonitor, + File file, + AlgorithmFactory validator) throws AlgorithmExecutionException, FileLoadException { + IWorkbenchWindow window = getFirstWorkbenchWindow(); + Display display = PlatformUI.getWorkbench().getDisplay(); + Data[] validatedFileData = validateFile( + bundleContext, + ciShellContext, + logger, + progressMonitor, + window, + display, + file, + validator); + Data[] labeledFileData = labelFileData(file, validatedFileData); + + return labeledFileData; + } + private IWorkbenchWindow getFirstWorkbenchWindow() throws FileLoadException { final IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); @@ -182,15 +274,18 @@ ProgressMonitor progressMonitor, IWorkbenchWindow window, Display display, - File file) throws AlgorithmExecutionException { - AlgorithmFactory validator = null; - validator = getValidatorFromUser(bundleContext, window, display, file); - + File file, + AlgorithmFactory validator) throws AlgorithmExecutionException { if ((file == null) || (validator == null)) { String logMessage = "File loading canceled"; logger.log(LogService.LOG_WARNING, logMessage); } else { try { + System.err.println("file: " + file); + System.err.println("validator: " + validator); + System.err.println("progressMonitor: " + progressMonitor); + System.err.println("ciShellContext: " + ciShellContext); + System.err.println("logger: " + logger); return FileValidator.validateFile( file, validator, progressMonitor, ciShellContext, logger); } catch (AlgorithmExecutionException e) { Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/PrettyLabeler.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/PrettyLabeler.java 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/PrettyLabeler.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -73,11 +73,17 @@ for (Data datum : data) { Dictionary<String, Object> labeledDatumMetadata = datum.getMetadata(); - Data dataParent = getParent(labeledDatumMetadata); - if (!possibleParents.contains(dataParent)) { - labeledDatumMetadata.put(DataProperty.LABEL, prefix + absoluteFile.getName()); + Object labelObject = labeledDatumMetadata.get(DataProperty.LABEL); + + if ((labelObject == null) || ("".equals(labelObject.toString()))) { + Data dataParent = getParent(labeledDatumMetadata); + + if (!possibleParents.contains(dataParent)) { + labeledDatumMetadata.put(DataProperty.LABEL, prefix + absoluteFile.getName()); + } + + possibleParents.add(datum); } - possibleParents.add(datum); } return data; Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/ValidatorSelectorRunnable.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/ValidatorSelectorRunnable.java 2011-02-09 18:22:52 UTC (rev 1202) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/ValidatorSelectorRunnable.java 2011-02-11 13:26:16 UTC (rev 1203) @@ -13,38 +13,40 @@ private BundleContext bundleContext; private File file; - private AlgorithmFactory validator; + private AlgorithmFactory chosenValidator; public ValidatorSelectorRunnable( IWorkbenchWindow window, BundleContext bundleContext, File file) { this.window = window; this.bundleContext = bundleContext; this.file = file; + } public AlgorithmFactory getValidator() { - return this.validator; + return this.chosenValidator; } public void run() { String fileExtension = getFileExtension(this.file.getAbsolutePath()).toLowerCase().substring(1); - ServiceReference[] supportingValidators = getSupportingValidators(fileExtension); + ServiceReference[] supportingValidators = + getSupportingValidators(this.bundleContext, fileExtension); // If there are no supporting validators... if (supportingValidators.length == 0) { // Let the user choose from all the validators available. - ServiceReference[] allValidators = getAllValidators(); + ServiceReference[] allValidators = getAllValidators(this.bundleContext); FileFormatSelector validatorSelector = new FileFormatSelector( "Load", window.getShell(), this.bundleContext, allValidators, this.file); validatorSelector.open(); - this.validator = validatorSelector.getValidator(); + this.chosenValidator = validatorSelector.getValidator(); } else if (supportingValidators.length == 1) { ServiceReference onlyPossibleValidator = supportingValidators[0]; - this.validator = + this.chosenValidator = (AlgorithmFactory)this.bundleContext.getService(onlyPossibleValidator); } @@ -52,49 +54,50 @@ FileFormatSelector validatorSelector = new FileFormatSelector( "Load", window.getShell(), this.bundleContext, supportingValidators, this.file); validatorSelector.open(); - this.validator = validatorSelector.getValidator(); + this.chosenValidator = validatorSelector.getValidator(); } } - private ServiceReference[] getSupportingValidators(String fileExtension) { + public static ServiceReference[] getAllValidators(BundleContext bundleContext) { try { - String validatorsQuery = - "(& (type=validator)" + - "(|" + - "(in_data=file-ext:" + fileExtension + ")" + - "(also_validates=" + fileExtension + ")" + - "))"; - - ServiceReference[] supportingValidators = this.bundleContext.getAllServiceReferences( + String validatorsQuery = "(&(type=validator)(in_data=file-ext:*))"; + ServiceReference[] allValidators = bundleContext.getAllServiceReferences( AlgorithmFactory.class.getName(), validatorsQuery); - if (supportingValidators == null) { + if (allValidators == null) { return new ServiceReference[0]; } else { - return supportingValidators; + return allValidators; } } catch (InvalidSyntaxException e) { e.printStackTrace(); - return new ServiceReference[]{}; + return new ServiceReference[0]; } } - private ServiceReference[] getAllValidators() { + public static ServiceReference[] getSupportingValidators( + BundleContext bundleContext, String fileExtension) { try { - String validatorsQuery = "(&(type=validator)(in_data=file-ext:*))"; - ServiceReference[] allValidators = this.bundleContext.getAllServiceReferences( + String validatorsQuery = + "(& (type=validator)" + + "(|" + + "(in_data=file-ext:" + fileExtension + ")" + + "(also_validates=" + fileExtension + ")" + + "))"; + + ServiceReference[] supportingValidators = bundleContext.getAllServiceReferences( AlgorithmFactory.class.getName(), validatorsQuery); - if (allValidators == null) { + if (supportingValidators == null) { return new ServiceReference[0]; } else { - return allValidators; + return supportingValidators; } } catch (InvalidSyntaxException e) { e.printStackTrace(); - return new ServiceReference[0]; + return new ServiceReference[]{}; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pat...@us...> - 2011-03-01 20:10:37
|
Revision: 1231 http://cishell.svn.sourceforge.net/cishell/?rev=1231&view=rev Author: pataphil Date: 2011-03-01 20:10:28 +0000 (Tue, 01 Mar 2011) Log Message: ----------- * Implemented the FileLoaderService and the FileSaverService. * Reviewed by Joseph. Modified Paths: -------------- trunk/core/org.cishell.framework/META-INF/MANIFEST.MF trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoadException.java trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoaderService.java trunk/core/org.cishell.reference/META-INF/MANIFEST.MF trunk/core/org.cishell.reference/OSGI-INF/fileloader.properties trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileFormatSelector.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileLoaderServiceImpl.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileSelectorRunnable.java Added Paths: ----------- trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/ trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/AbstractFileSaverService.java trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaveException.java trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaveListener.java trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaverService.java trunk/core/org.cishell.reference/OSGI-INF/filesaver.properties trunk/core/org.cishell.reference/OSGI-INF/filesaver.xml trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/DataFormatChooser.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/FileSaverServiceImpl.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/SaveAsController.java trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/persistence/ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/persistence/AbstractDialog.java Removed Paths: ------------- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/AbstractDialog.java Modified: trunk/core/org.cishell.framework/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.framework/META-INF/MANIFEST.MF 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.framework/META-INF/MANIFEST.MF 2011-03-01 20:10:28 UTC (rev 1231) @@ -11,6 +11,7 @@ org.osgi.service.prefs Export-Package: org.cishell.app.service.datamanager;version="1.0.0", org.cishell.app.service.fileloader, + org.cishell.app.service.filesaver, org.cishell.app.service.scheduler;version="1.0.0", org.cishell.framework;version="1.0.0", org.cishell.framework.algorithm;version="1.0.0", Modified: trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoadException.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoadException.java 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoadException.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -14,8 +14,4 @@ public FileLoadException(String message) { super(message); } - - public FileLoadException() { - this("Algorithm canceled by user."); - } } Modified: trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoaderService.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoaderService.java 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.framework/src/org/cishell/app/service/fileloader/FileLoaderService.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -13,11 +13,15 @@ public void registerListener(FileLoadListener listener); public void unregisterListener(FileLoadListener listener); + /* TODO make abstract default class, template method pattern, blah blah */ + public File[] getFilesToLoadFromUser( + boolean selectSingleFile, String[] filterExtensions) throws FileLoadException; public Data[] loadFilesFromUserSelection( BundleContext bundleContext, CIShellContext ciShellContext, LogService logger, - ProgressMonitor progressMonitor) throws FileLoadException; + ProgressMonitor progressMonitor, + boolean selectSingleFile) throws FileLoadException; public Data[] loadFiles( BundleContext bundleContext, CIShellContext ciShellContext, Added: trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/AbstractFileSaverService.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/AbstractFileSaverService.java (rev 0) +++ trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/AbstractFileSaverService.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,80 @@ +package org.cishell.app.service.filesaver; + +import java.io.File; +import java.util.Collection; + +import org.cishell.framework.data.Data; +import org.cishell.service.conversion.ConversionException; +import org.cishell.service.conversion.Converter; + +public abstract class AbstractFileSaverService implements FileSaverService { + private Collection<FileSaveListener> listeners; + + public void registerListener(FileSaveListener listener) { + this.listeners.add(listener); + } + + public void unregisterListener(FileSaveListener listener) { + this.listeners.remove(listener); + } + + public File promptForTargetFile() throws FileSaveException { + return promptForTargetFile(""); + } + + public File promptForTargetFile(Data datum) throws FileSaveException { + return promptForTargetFile((File) datum.getData()); + } + + public File promptForTargetFile(File outputFile) throws FileSaveException { + return promptForTargetFile(outputFile.getAbsolutePath()); // TODO getName? + } + + public File save(Data sourceDatum) throws FileSaveException { + return save((File) sourceDatum.getData()); + } + + public File save(File sourceFile) throws FileSaveException { + File targetFile = promptForTargetFile(sourceFile); + saveTo(sourceFile, targetFile); + + return targetFile; + } + + public Data save(Data sourceDatum, String targetMimeType) + throws FileSaveException { + Converter converter = promptForConverter(sourceDatum, targetMimeType); + + if (converter != null) { + return save(converter, sourceDatum); + } else { + // TODO: CanceledException? + return null; + } + } + + // TODO: What to actually return here? Maybe Pair<Data, File> (LOL)? + public Data save(Converter converter, Data sourceDatum) + throws FileSaveException { + File targetFile = promptForTargetFile(sourceDatum); + + if (targetFile != null) { + return save(converter, sourceDatum, targetFile); + } else { + // TODO: CanceledException? + return null; + } + } + + public Data save( + Converter converter, Data sourceDatum, File targetFile) throws FileSaveException { + try { + Data convertedDatum = converter.convert(sourceDatum); + saveTo((File) convertedDatum.getData(), targetFile); + + return convertedDatum; + } catch (ConversionException e) { + throw new FileSaveException(e.getMessage(), e); + } + } +} \ No newline at end of file Added: trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaveException.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaveException.java (rev 0) +++ trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaveException.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,17 @@ +package org.cishell.app.service.filesaver; + +public class FileSaveException extends Exception { + private static final long serialVersionUID = 1L; + + public FileSaveException(String message, Throwable exception) { + super(message, exception); + } + + public FileSaveException(Throwable exception) { + super(exception); + } + + public FileSaveException(String message) { + super(message); + } +} Added: trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaveListener.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaveListener.java (rev 0) +++ trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaveListener.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,7 @@ +package org.cishell.app.service.filesaver; + +import java.io.File; + +public interface FileSaveListener { + void fileSaved(File file); +} \ No newline at end of file Added: trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaverService.java =================================================================== --- trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaverService.java (rev 0) +++ trunk/core/org.cishell.framework/src/org/cishell/app/service/filesaver/FileSaverService.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,40 @@ +package org.cishell.app.service.filesaver; + +import java.io.File; + +import org.cishell.framework.data.Data; +import org.cishell.service.conversion.Converter; + +/* TODO Push down methods with an obvious implementation in terms of the "atomic" methods + * (choose converter, choose file, perform save) into an abstract class that implements this. + * Then FileSaverServiceImpl extends the abstract class. + */ +public interface FileSaverService { + public void registerListener(FileSaveListener listener); + public void unregisterListener(FileSaveListener listener); + + public Converter promptForConverter(final Data outDatum, String targetMimeType) + throws FileSaveException; + + public File promptForTargetFile() throws FileSaveException; + public File promptForTargetFile(Data datum) throws FileSaveException; + public File promptForTargetFile(File outputFile) throws FileSaveException; + public File promptForTargetFile(String fileName) throws FileSaveException; + + /* TODO I'm seriously tempted to recommend that all methods beyond this point be called + * "save" or "saveToFile" or something, and just have a bit of very concise Javadoc that + * explains what may be prompted for? Alternatively, ask another dev about doing the null + * arguments idea. + */ + // TODO (NEW): Just Javadoc these really well? + public File save(Data sourceDatum) throws FileSaveException; + public File save(File sourceFile) throws FileSaveException; + public void saveTo(File sourceFile, File targetFile) throws FileSaveException; + + // TODO: What to actually return here? the File object for the one on disk + /* TODO sourceDatum always first, targetType/File last */ + public Data save(Data sourceDatum, String targetMimeType) throws FileSaveException; + public Data save(Converter converter, Data sourceDatum) throws FileSaveException; + public Data save( + Converter converter, Data sourceDatum, File targetFile) throws FileSaveException; +} \ No newline at end of file Modified: trunk/core/org.cishell.reference/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.reference/META-INF/MANIFEST.MF 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.reference/META-INF/MANIFEST.MF 2011-03-01 20:10:28 UTC (rev 1231) @@ -2,8 +2,11 @@ Bundle-Name: CIShell Reference Service Implementations Bundle-SymbolicName: org.cishell.reference Bundle-Version: 1.0.0 -Import-Package: org.cishell.app.service.datamanager, +Import-Package: com.google.common.base, + com.google.common.collect, + org.cishell.app.service.datamanager, org.cishell.app.service.fileloader, + org.cishell.app.service.filesaver, org.cishell.app.service.scheduler;version="1.0.0", org.cishell.framework;version="1.0.0", org.cishell.framework.algorithm;version="1.0.0", @@ -13,12 +16,15 @@ org.cishell.service.guibuilder;version="1.0.0", org.osgi.framework, org.osgi.service.cm;version="1.2.0", + org.osgi.service.component;version="1.0.0", org.osgi.service.log, org.osgi.service.metatype;version="1.1.0", org.osgi.service.prefs Export-Package: org.cishell.reference.app.service.algorithminvocation, org.cishell.reference.app.service.datamanager, org.cishell.reference.app.service.fileloader, + org.cishell.reference.app.service.filesaver, + org.cishell.reference.app.service.persistence, org.cishell.reference.app.service.scheduler, org.cishell.reference.service.conversion, org.cishell.reference.service.metatype @@ -27,6 +33,6 @@ org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.update.ui -Service-Component: OSGI-INF/fileloader.xml +Service-Component: OSGI-INF/fileloader.xml, OSGI-INF/filesaver.xml Bundle-RequiredExecutionEnvironment: J2SE-1.5 X-AutoStart: true Modified: trunk/core/org.cishell.reference/OSGI-INF/fileloader.properties =================================================================== --- trunk/core/org.cishell.reference/OSGI-INF/fileloader.properties 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.reference/OSGI-INF/fileloader.properties 2011-03-01 20:10:28 UTC (rev 1231) @@ -4,7 +4,7 @@ #description=This allows users to select files from the file system and load them to Data Model window. #in_data=null #out_data=java.lang.Object -service.pid=org.cishell.reference.app.service.fileloader.FileLoadServiceImpl +service.pid=org.cishell.reference.app.service.fileloader.FileLoaderServiceImpl remoteable=true prefs_published=local receive_prefs=true Added: trunk/core/org.cishell.reference/OSGI-INF/filesaver.properties =================================================================== --- trunk/core/org.cishell.reference/OSGI-INF/filesaver.properties (rev 0) +++ trunk/core/org.cishell.reference/OSGI-INF/filesaver.properties 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,11 @@ +#menu_path=File/start +#label=Load... +#shortcut=ctrl+alt+o +#description=This allows users to select files from the file system and load them to Data Model window. +#in_data=null +#out_data=java.lang.Object +service.pid=org.cishell.reference.app.service.filesaver.FileSaverServiceImpl +remoteable=true +prefs_published=local +receive_prefs=true +#documentation_url=http://wiki.slis.indiana.edu:8080/display/ALGDOC/Data+Formats \ No newline at end of file Added: trunk/core/org.cishell.reference/OSGI-INF/filesaver.xml =================================================================== --- trunk/core/org.cishell.reference/OSGI-INF/filesaver.xml (rev 0) +++ trunk/core/org.cishell.reference/OSGI-INF/filesaver.xml 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component name="org.cishell.reference.app.service.filesaver.FileSaverServiceImpl.component" immediate="true"> + <implementation class="org.cishell.reference.app.service.filesaver.FileSaverServiceImpl"/> + <reference name="DCS" interface="org.cishell.service.conversion.DataConversionService"/> + <reference name="GBS" interface="org.cishell.service.guibuilder.GUIBuilderService"/> + <reference name="LOG" interface="org.osgi.service.log.LogService"/> + + <service> + <provide interface="org.cishell.app.service.filesaver.FileSaverService"/> + </service> +</component> \ No newline at end of file Deleted: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/AbstractDialog.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/AbstractDialog.java 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/AbstractDialog.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -1,490 +0,0 @@ -/* - * InfoVis CyberInfrastructure: A Data-Code-Compute Resource for Research - * and Education in Information Visualization (http://iv.slis.indiana.edu/). - * - * Created on Feb 22, 2005 at Indiana University. - */ -package org.cishell.reference.app.service.fileloader; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.ShellAdapter; -import org.eclipse.swt.events.ShellEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Dialog; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - - -/** - * This class provides a DialogBox structure that can be extended to create Dialogs for CIShell. - * This framework will enforce consistency in the look and feel of Dialogs in CIShell by providing a - * standard layout of description, content, and buttons[, along with a choice of icon images - * defined as constants in this class]. An optional details section allows the Dialog designer - * to provide additional information when the details button is pressed. - * - * @author Team IVC - */ -public abstract class AbstractDialog extends Dialog { - private static final int DETAILS_HEIGHT = 75; - - public static Image INFORMATION; - public static Image WARNING; - public static Image ERROR; - public static Image QUESTION; - public static Image WORKING; - - static { - Runnable runner = new Runnable() { - public void run() { - INFORMATION = Display.getDefault().getSystemImage(SWT.ICON_INFORMATION); - WARNING = Display.getDefault().getSystemImage(SWT.ICON_WARNING); - ERROR = Display.getDefault().getSystemImage(SWT.ICON_ERROR); - QUESTION = Display.getDefault().getSystemImage(SWT.ICON_QUESTION); - WORKING = Display.getDefault().getSystemImage(SWT.ICON_WORKING); - }}; - - if (Display.getDefault().getThread() == Thread.currentThread()) { - runner.run(); - } else { - Display.getDefault().asyncExec(runner); - } - } - - - private String description = ""; - private String detailsString = ""; - private Text detailsText; - private Shell shell; - private Image image; - private boolean success; - private Composite header; - private Composite content; - private Composite buttons; - private Shell parent; - - /** - * Creates a new AbstractDialog object. - * - * @param parent the parent Shell of this AbstractDialog - * @param title the title to put in the title bar of this AbstractDialog - * @param image the Image to display to the left of the description specified - * for this AbstractDialog. This will usually be one of: - * <ul> - * <li>AbstractDialog.WARNING</li> - * <li>AbstractDialog.INFORMATION</li> - * <li>AbstractDialog.ERROR</li> - * <li>AbstractDialog.WORKING</li> - * <li>AbstractDialog.QUESTION</li> - * </ul> - */ - public AbstractDialog(Shell parent, String title, Image image) { - super(parent, 0); - setText(title); - this.image = image; - this.parent = parent; - init(); - } - - /** - * Closes this AbstractDialog. - * - * @param success true if the dialog was successful, false if it - * was cancelled by the user (or closed prematurely) - */ - public void close(boolean success){ - shell.dispose(); - this.success = success; - } - - /** - * Returns the shell used by this AbstractDialog - * - * @return the shell used by this AbstractDialog - */ - public Shell getShell(){ - return shell; - } - - /** - * Initializes this AbstractDialog. This consists of resetting all of the - * customizable components like the content area, details pane, buttons, - * and description label, and readying the dialog to be refilled with - * new content. - */ - public void init(){ - if(shell != null) - shell.dispose(); - - shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.RESIZE); - - if (parent != null) - shell.setImage(parent.getImage()); - - shell.setText(getText()); - GridLayout layout = new GridLayout(); - layout.numColumns = 1; - shell.setLayout(layout); - } - - /** - * Opens this AbstractDialog. - * - * @return true if this AbstractDialog was closed by clicking the 'x' in the upper right - * corner of the window, signifying a cancellation, false if the dialog is exited otherwise. - */ - public boolean open() { - if (shell.getDisplay().getThread() == Thread.currentThread()) { - doOpen(); - } else { - shell.getDisplay().syncExec(new Runnable() { - public void run() { - doOpen(); - }}); - } - - Display display = getParent().getDisplay(); - - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - - return success; - } - - protected void doOpen() { - success = true; - - setupHeader(); - setupContent(); - setupButtons(); - - shell.pack(); - setLocation(); - shell.open(); - shell.addShellListener(new ShellAdapter(){ - public void shellClosed(ShellEvent e) { - success = false; - } - }); - } - - /* - * centers the dialog on its parents shell - */ - private void setLocation(){ - Point parentLocation = parent.getLocation(); - int parentWidth = parent.getSize().x; - int parentHeight = parent.getSize().y; - int shellWidth = shell.getSize().x; - int shellHeight = shell.getSize().y; - - int x = parentLocation.x + (parentWidth - shellWidth)/2; - int y = parentLocation.y + (parentHeight - shellHeight)/2; - shell.setLocation(x, y); - } - - /** - * Sets the Description of this AbstractDialog. This is the textField that is displayed in the - * top section of the Dialog window, giving information about the question that is being - * asked or the information that is being given. - * - * @param description the description for this AbstractDialog to use - */ - public void setDescription(String description) { - this.description = description; - } - - /** - * Sets the details textField of this AbstractDialog. This is the textField that is displayed in the lower - * section of the Dialog window when the user presses the "Details >>" button. If this String - * is null or the empty string, the details button will be disabled. - * - * @param details DOCUMENT ME! - */ - public void setDetails(String details) { - this.detailsString = details; - } - - /** - * Creates the Buttons to use in this AbstractDialog based on the given parent. These are - * the buttons that show up at the bottom of the dialog for user input, such as a - * "Yes/No" group or "Continue/Cancel" or something like that. This does not encompass all - * Buttons created in the dialog (such as those created in the content section), just those - * to display at the bottom of the dialog. - * - * @param parent the parent to be used to create the Buttons for this AbstractDialog - */ - public abstract void createDialogButtons(Composite parent); - - /** - * Creates the content section of this AbstractDialog based on the given parent. - * This section is where all of the "guts" of the AbstractDialog go, specifying the controls - * that are needed to interact with the user and provide whatever questions or information - * are needed. - * - * @param parent the parent to be used to create the Buttosn for this AbstractDialog - * - * @return the Composite that is created to display the content of this AbstractDialog - */ - public abstract Composite createContent(Composite parent); - - /* - * Sets up the header section of the dialog. This section contains the image for the - * type of dialog it is, as well as the description label - */ - private void setupHeader() { - header = new Composite(shell, SWT.NONE); - header.setLayoutData(new GridData(GridData.FILL_BOTH)); - GridLayout layout = new GridLayout(); - layout.numColumns = 2; - header.setLayout(layout); - - Label canvas = new Label(header, SWT.NONE); - if (image != null) { - canvas.setImage(image); - } - GridData canvasData = new GridData(); - canvasData.heightHint = image.getBounds().height; - canvas.setLayoutData(canvasData); - - Label desc = new Label(header, SWT.WRAP); - - if ((description != null) && !description.equals("")) { - desc.setText(description); - } - } - - /* - * sets up the content section of the dialog, this calls the abstract method to - * create the content that must be implemented by all subclasses - */ - private void setupContent() { - content = createContent(shell); - - if (content != null) { - content.setLayoutData(new GridData(GridData.FILL_BOTH)); - } - } - - /* - * sets up the button section in the bottom of the dialog. These buttons - * are created in the abstract method createDialogButtons(parent). In addition to - * any created buttons, a "Details >>" button is added to allow the user to see any - * details that are available in the current Dialog. - */ - private void setupButtons() { - buttons = new Composite(shell, SWT.NONE); - buttons.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END)); - - //there are two sections, all the user stuff to the left, and - //then the details button on the far right - //User Buttons Section - createDialogButtons(buttons); - Control[] controls = buttons.getChildren(); - GridLayout buttonsLayout = new GridLayout(); - buttonsLayout.numColumns = controls.length + 1; - buttonsLayout.makeColumnsEqualWidth = true; - buttons.setLayout(buttonsLayout); - - //setup the grid data for each button for standard look - for (int i = 0; i < controls.length; i++) { - controls[i].setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - } - - //Details Button section - final Button details = new Button(buttons, SWT.PUSH); - details.setText("Details >>"); - details.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - details.addSelectionListener(new SelectionAdapter() { - public synchronized void widgetSelected(SelectionEvent e) { - GridData data = (GridData) detailsText.getLayoutData(); - - if (detailsText.getVisible()) { - detailsText.setText(""); - details.setText("Details >>"); - data.heightHint = 0; - data.grabExcessHorizontalSpace = false; - data.grabExcessVerticalSpace = false; - } else { - detailsText.setText(detailsString); - details.setText("Details <<"); - data.heightHint = DETAILS_HEIGHT; - data.grabExcessHorizontalSpace = true; - data.grabExcessVerticalSpace = true; - } - - detailsText.setLayoutData(data); - detailsText.setVisible(!detailsText.getVisible()); - - shell.setSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT)); - shell.layout(); - } - }); - - setupDetails(); - details.setEnabled(detailsString != null && !detailsString.equals("")); - } - - /* - * creates the details textField box when the "Details >>" button is toggled - */ - private void setupDetails() { - detailsText = new Text(shell, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL); - detailsText.setEditable(false); - detailsText.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)); - - GridData data = new GridData(GridData.FILL_BOTH | - GridData.GRAB_VERTICAL | GridData.GRAB_HORIZONTAL); - data.widthHint = 400; - - detailsText.setLayoutData(data); - detailsText.setVisible(false); - } - - /** - * Open a standard error dialog with OK button - * - * @param parent the parent Shell of this dialog - * @param title the textField to display in the title bar of this dialog - * @param message the message to give in the dialog's body - * @param details the textField to put in the details pane to be visible when the - * "Details >>" button is pressed (can be null or empty, resulting - * in the "Details >>" button not being enabled) - * @return true if the dialog was exited by pressing the OK button, false - * if it was cancelled by pressing the 'x' in the title bar - */ - public static boolean openError(Shell parent, String title, String message, String details){ - return openOKDialog(parent, ERROR, title, message, details); - } - - /** - * Open a standard information dialog with OK button - * - * @param parent the parent Shell of this dialog - * @param title the textField to display in the title bar of this dialog - * @param message the message to give in the dialog's body - * @param details the textField to put in the details pane to be visible when the - * "Details >>" button is pressed (can be null or empty, resulting - * in the "Details >>" button not being enabled) * @return true if the dialog was exited by pressing the OK button, false - * if it was cancelled by pressing the 'x' in the title bar - */ - public static boolean openInformation(Shell parent, String title, String message, String details){ - return openOKDialog(parent, INFORMATION, title, message, details); - } - - /** - * Open a standard warning dialog with OK button - * - * @param parent the parent Shell of this dialog - * @param title the textField to display in the title bar of this dialog - * @param message the message to give in the dialog's body - * @param details the textField to put in the details pane to be visible when the - * "Details >>" button is pressed (can be null or empty, resulting - * in the "Details >>" button not being enabled) * @return true if the dialog was exited by pressing the OK button, false - * if it was cancelled by pressing the 'x' in the title bar - */ - public static boolean openWarning(Shell parent, String title, String message, String details){ - return openOKDialog(parent, WARNING, title, message, details); - } - - /** - * Open a standard question dialog with Yes/No buttons - * - * @param parent the parent Shell of this dialog - * @param title the textField to display in the title bar of this dialog - * @param message the message to give in the dialog's body - * @param details the textField to put in the details pane to be visible when the - * "Details >>" button is pressed (can be null or empty, resulting - * in the "Details >>" button not being enabled) * @return true if the dialog was exited by pressing the OK button, false - * if it was cancelled by pressing the 'x' in the title bar or pressing the - * No button - */ - public static boolean openQuestion(Shell parent, String title, String message, String details){ - return openConfirmDenyDialog(parent, QUESTION, title, message, details, "Yes", "No"); - } - - /** - * Open a standard confirmation dialog with OK/Cancel buttons - * - * @param parent the parent Shell of this dialog - * @param title the textField to display in the title bar of this dialog - * @param message the message to give in the dialog's body - * @param details the textField to put in the details pane to be visible when the - * "Details >>" button is pressed (can be null or empty, resulting - * in the "Details >>" button not being enabled) * @return true if the dialog was exited by pressing the OK button, false - * if it was cancelled by pressing the 'x' in the title bar or pressing - * the Cancel button - */ - public static boolean openConfirm(Shell parent, String title, String message, String details){ - return openConfirmDenyDialog(parent, QUESTION, title, message, details, "OK", "Cancel"); - } - - /* - * helper to create OK dialogs: error, warning, information - */ - private static boolean openOKDialog(Shell parent, Image image, String title, String message, String details){ - AbstractDialog okDialog = new AbstractDialog(parent, title, image){ - public void createDialogButtons(Composite parent) { - Button ok = new Button(parent, SWT.PUSH); - ok.setText("OK"); - ok.addSelectionListener(new SelectionAdapter(){ - public void widgetSelected(SelectionEvent e) { - close(true); - } - }); - } - - public Composite createContent(Composite parent) { - return null; - } - }; - okDialog.setDescription(message); - okDialog.setDetails(details); - return okDialog.open(); - } - - /* - * helper to create confirm/deny dialogs: question, confirmation - */ - private static boolean openConfirmDenyDialog(Shell parent, Image image, String title, String message, String details, final String confirmLabel, final String denyLabel){ - AbstractDialog dialog = new AbstractDialog(parent, title, image){ - public void createDialogButtons(Composite parent) { - Button confirm = new Button(parent, SWT.PUSH); - if(confirmLabel != null) - confirm.setText(confirmLabel); - confirm.addSelectionListener(new SelectionAdapter(){ - public void widgetSelected(SelectionEvent e) { - close(true); - } - }); - Button deny = new Button(parent, SWT.PUSH); - if(denyLabel != null) - deny.setText(denyLabel); - deny.addSelectionListener(new SelectionAdapter(){ - public void widgetSelected(SelectionEvent e) { - close(false); - } - }); - } - - public Composite createContent(Composite parent) { - return null; - } - }; - dialog.setDescription(message); - dialog.setDetails(details); - return dialog.open(); - } -} Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileFormatSelector.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileFormatSelector.java 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileFormatSelector.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -3,6 +3,7 @@ import java.io.File; import org.cishell.framework.algorithm.AlgorithmFactory; +import org.cishell.reference.app.service.persistence.AbstractDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileLoaderServiceImpl.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileLoaderServiceImpl.java 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileLoaderServiceImpl.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -43,18 +43,25 @@ } } + public File[] getFilesToLoadFromUser(boolean selectSingleFile, String[] filterExtensions) + throws FileLoadException { + IWorkbenchWindow window = getFirstWorkbenchWindow(); + Display display = PlatformUI.getWorkbench().getDisplay(); + + return getFilesToLoadFromUserInternal(window, display, selectSingleFile, filterExtensions); + } + public Data[] loadFilesFromUserSelection( BundleContext bundleContext, CIShellContext ciShellContext, LogService logger, - ProgressMonitor progressMonitor) throws FileLoadException { + ProgressMonitor progressMonitor, + boolean selectSingleFile) throws FileLoadException { if ("".equals(defaultLoadDirectory)) { defaultLoadDirectory = determineDefaultLoadDirectory(); } - IWorkbenchWindow window = getFirstWorkbenchWindow(); - Display display = PlatformUI.getWorkbench().getDisplay(); - File[] files = getFilesToLoadFromUser(window, display); + File[] files = getFilesToLoadFromUser(selectSingleFile, null); if (files != null) { return loadFiles(bundleContext, ciShellContext, logger, progressMonitor, files); @@ -255,8 +262,13 @@ } } - private File[] getFilesToLoadFromUser(IWorkbenchWindow window, Display display) { - FileSelectorRunnable fileSelector = new FileSelectorRunnable(window); + private File[] getFilesToLoadFromUserInternal( + IWorkbenchWindow window, + Display display, + boolean selectSingleFile, + String[] filterExtensions) { + FileSelectorRunnable fileSelector = + new FileSelectorRunnable(window, selectSingleFile, filterExtensions); if (Thread.currentThread() != display.getThread()) { display.syncExec(fileSelector); Modified: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileSelectorRunnable.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileSelectorRunnable.java 2011-03-01 20:09:46 UTC (rev 1230) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/fileloader/FileSelectorRunnable.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -8,11 +8,15 @@ public final class FileSelectorRunnable implements Runnable { private IWorkbenchWindow window; - + private boolean selectSingleFile; + private String[] filterExtensions; private File[] files; - public FileSelectorRunnable(IWorkbenchWindow window) { + public FileSelectorRunnable( + IWorkbenchWindow window, boolean selectSingleFile, String[] filterExtensions) { this.window = window; + this.selectSingleFile = selectSingleFile; + this.filterExtensions = filterExtensions; } public File[] getFiles() { @@ -35,7 +39,6 @@ fileDialog.open(); String path = fileDialog.getFilterPath(); String[] fileNames = fileDialog.getFileNames(); - // TODO: Ask Angela about the order here, i.e. should they be sorted alphabetically? if ((fileNames == null) || (fileNames.length == 0)) { return new File[0]; @@ -54,10 +57,24 @@ private FileDialog createFileDialog() { File currentDirectory = new File(FileLoaderServiceImpl.defaultLoadDirectory); String absolutePath = currentDirectory.getAbsolutePath(); - FileDialog fileDialog = new FileDialog(this.window.getShell(), SWT.OPEN | SWT.MULTI); + FileDialog fileDialog = + new FileDialog(this.window.getShell(), SWT.OPEN | determineSWTFileSelectFlag()); fileDialog.setFilterPath(absolutePath); + + if ((this.filterExtensions != null) && (this.filterExtensions.length > 0)) { + fileDialog.setFilterExtensions(this.filterExtensions); + } + fileDialog.setText("Select Files"); return fileDialog; } + + private int determineSWTFileSelectFlag() { + if (this.selectSingleFile) { + return SWT.SINGLE; + } else { + return SWT.MULTI; + } + } } \ No newline at end of file Added: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/DataFormatChooser.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/DataFormatChooser.java (rev 0) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/DataFormatChooser.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,338 @@ +package org.cishell.reference.app.service.filesaver; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import org.cishell.framework.algorithm.AlgorithmProperty; +import org.cishell.framework.data.Data; +import org.cishell.reference.app.service.persistence.AbstractDialog; +import org.cishell.service.conversion.Converter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Shell; +import org.osgi.framework.ServiceReference; + +/* TODO Kill dead methods */ +public class DataFormatChooser extends AbstractDialog implements AlgorithmProperty { +// public static final Image QUESTION_ICON = +// Display.getCurrent().getSystemImage(SWT.ICON_QUESTION); + + protected Data data; + protected Converter[] converters; + private List converterListComponent; + private StyledText detailPane; + private Converter chosenConverter; + + public DataFormatChooser(Data data, Shell parent, Converter[] converters, String title) { + super(parent, title, AbstractDialog.QUESTION); + this.data = data; + this.converters = alphabetizeConverters(filterConverters(converters)); + } + + public Converter getChosenConverter() { + return this.chosenConverter; + } + + private Composite initializeGUI(Composite parent) { + Composite content = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + content.setLayout(layout); + + Group converterGroup = new Group(content, SWT.NONE); + converterGroup.setText("Pick the Output Data Type"); + converterGroup.setLayout(new FillLayout()); + GridData persisterData = new GridData(GridData.FILL_BOTH); + persisterData.widthHint = 200; + converterGroup.setLayoutData(persisterData); + + converterListComponent = + new List(converterGroup, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE); + initializeConverterListComponent(); + converterListComponent.addMouseListener(new MouseAdapter() { + public void mouseDoubleClick(MouseEvent mouseEvent) { + List list = (List)mouseEvent.getSource(); + int selection = list.getSelectionIndex(); + + if (selection != -1) { + selectionMade(selection); + } + } + }); + converterListComponent.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent selectionEvent) { + List list = (List)selectionEvent.getSource(); + int selection = list.getSelectionIndex(); + + if (selection != -1) { + updateDetailPane(converters[selection]); + } + } + }); + + Group detailsGroup = new Group(content, SWT.NONE); + detailsGroup.setText("Details"); + detailsGroup.setLayout(new FillLayout()); + GridData detailsData = new GridData(GridData.FILL_BOTH); + detailsData.widthHint = 200; + detailsGroup.setLayoutData(detailsData); + + detailPane = initializeDetailPane(detailsGroup); + + // Select the first item by default. + converterListComponent.setSelection(0); + updateDetailPane(converters[0]); + + return content; + } + + /** + * Initialize the Listbox of Persisters using the stored Persister array + */ + private void initializeConverterListComponent() { + for (int ii = 0; ii < converters.length; ii++) { + if (converters[ii] != null) { + Dictionary converterProperties = converters[ii].getProperties(); + + // Get the name of the persister from the property map. + String outData = null; + + ServiceReference[] serviceReferences = converters[ii].getConverterChain(); + + if ((serviceReferences != null) && (serviceReferences.length > 0)) { + outData = (String)serviceReferences[serviceReferences.length - 1].getProperty( + AlgorithmProperty.LABEL); + } + + if (outData == null) { + outData = (String)converterProperties.get(AlgorithmProperty.LABEL); + } + + /* + * If someone was sloppy enough to not provide a name, then use the name of the + * class instead. + */ + if ((outData == null) || (outData.length() == 0)) { + outData = converters[ii].getClass().getName(); + } + + converterListComponent.add(outData); + } + } + } + + private StyledText initializeDetailPane(Group detailsGroup) { + StyledText detailPane = new StyledText(detailsGroup, SWT.H_SCROLL | SWT.V_SCROLL); + detailPane.setEditable(false); + detailPane.getCaret().setVisible(false); + + return detailPane; + } + + private void updateDetailPane(Converter converter) { + Dictionary converterProperties = converter.getProperties(); + Enumeration converterPropertiesKeys = converterProperties.keys(); + + detailPane.setText(""); + + while (converterPropertiesKeys.hasMoreElements()) { + Object key = converterPropertiesKeys.nextElement(); + Object value = converterProperties.get(key); + + StyleRange styleRange = new StyleRange(); + styleRange.start = detailPane.getText().length(); + detailPane.append(key + ":\n"); + styleRange.length = key.toString().length() + 1; + styleRange.fontStyle = SWT.BOLD; + detailPane.setStyleRange(styleRange); + + detailPane.append(value + "\n"); + } + } + + private Converter[] filterConverters(Converter[] allConverters) { + Map lastInDataToConverter = new HashMap(); + + for (int ii = 0; ii < allConverters.length; ii++) { + Converter converter = allConverters[ii]; + String lastInputData = getLastConverterInData(converter); + + if (lastInDataToConverter.containsKey(lastInputData)) { + Converter alreadyStoredConverter = + (Converter)lastInDataToConverter.get(lastInputData); + Converter chosenConverter = + returnPreferredConverter(converter, alreadyStoredConverter); + lastInDataToConverter.put(lastInputData, chosenConverter); + } else { + lastInDataToConverter.put(lastInputData, converter); + } + } + + return (Converter[]) lastInDataToConverter.values().toArray(new Converter[0]); + } + + private String getLastConverterInData(Converter converter) { + ServiceReference[] convChain = converter.getConverterChain(); + + if (convChain.length >= 1) { + ServiceReference lastConverter = convChain[convChain.length - 1]; + String lastInData = (String) lastConverter.getProperty("in_data"); + + return lastInData; + } else { + return ""; + } + } + + private Converter returnPreferredConverter(Converter converter1, Converter converter2) { + Dictionary converter1Properties = converter1.getProperties(); + String converter1Lossiness = (String)converter1Properties.get(CONVERSION); + int converter1Quality = determineQuality(converter1Lossiness); + + Dictionary converter2Properties = converter2.getProperties(); + String converter2Lossiness = (String)converter2Properties.get(CONVERSION); + int converter2Quality = determineQuality(converter2Lossiness); + + if (converter1Quality > converter2Quality) { + return converter1; + } else if (converter2Quality > converter1Quality) { + return converter2; + } else { + // They are tied. Look at chosenConverter chain length. + + int converter1Length = converter1.getConverterChain().length; + int converter2Length = converter2.getConverterChain().length; + + if (converter1Length > converter2Length) { + return converter2; + } else if (converter2Length > converter1Length) { + return converter1; + } else { + /* + * Both have the same lossiness and same length. + * Arbitrary pick the first. + */ + return converter1; + } + } + } + + private int determineQuality(String lossiness) { + if (lossiness == LOSSY) { + return 0; + } else if (lossiness == null) { + return 1; + } else { + return 2; + } + } + + private Converter[] alphabetizeConverters(Converter[] converters) { + Arrays.sort(converters, new CompareAlphabetically()); + + return converters; + } + + protected void selectionMade(int selectedIndex) { + try { + getShell().setVisible(false); + this.chosenConverter = converters[selectedIndex]; +// final SaveAsController saver = new SaveAsController(getShell(), ciShellContext); + close(true); +// close(saver.save(chosenConverter, data)); + } catch (Exception exception) { + throw new RuntimeException(exception); + } + } + + public void createDialogButtons(Composite parent) { + Button select = new Button(parent, SWT.PUSH); + select.setText("Select"); + select.addSelectionListener( + new SelectionAdapter() { + public void widgetSelected(SelectionEvent selectionEvent) { + int index = converterListComponent.getSelectionIndex(); + + if (index != -1) { + selectionMade(index); + } + } + } + ); + select.setFocus(); + + Button cancel = new Button(parent, SWT.NONE); + cancel.setText("Cancel"); + cancel.addSelectionListener( + new SelectionAdapter() { + public void widgetSelected(SelectionEvent selectionEvent) { + close(false); + } + } + ); + } + + public Composite createContent(Composite parent) { + if (converters.length == 1) { + close(true); +// final SaveAsController saver = new SaveAsController((Shell) parent, ciShellContext); +// close(saver.save(converters[0], data)); + + return parent; + } else { + return initializeGUI(parent); + } + } + + private class CompareAlphabetically implements Comparator { + public int compare(Object object1, Object object2) { + if ((object1 instanceof Converter) && (object2 instanceof Converter)) { + Converter converter1 = (Converter)object1; + String converter1Label = getLabel(converter1); + + Converter converter2 = (Converter)object2; + String converter2Label = getLabel(converter2); + + if ((converter1Label != null) && (converter2Label != null)) { + return converter1Label.compareTo(converter2Label); + } else if (converter1Label == null) { + return 1; + } else if (converter2Label == null) { + return -1; + } else { + return 0; + } + } else { + throw new IllegalArgumentException("Can only compare Converters"); + } + } + + private String getLabel(Converter converter) { + String label = ""; + ServiceReference[] serviceReferences = converter.getConverterChain(); + + if ((serviceReferences != null) && (serviceReferences.length > 0)) { + label = (String)serviceReferences[serviceReferences.length - 1].getProperty( + AlgorithmProperty.LABEL); + } + + return label; + } + } +} Added: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/FileSaverServiceImpl.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/FileSaverServiceImpl.java (rev 0) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/FileSaverServiceImpl.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,141 @@ +package org.cishell.reference.app.service.filesaver; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; + +import org.cishell.app.service.filesaver.AbstractFileSaverService; +import org.cishell.app.service.filesaver.FileSaveException; +import org.cishell.framework.data.Data; +import org.cishell.service.conversion.Converter; +import org.cishell.service.conversion.DataConversionService; +import org.cishell.service.guibuilder.GUIBuilderService; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.osgi.service.component.ComponentContext; + +public class FileSaverServiceImpl extends AbstractFileSaverService { + public static final String SAVE_DIALOG_TITLE = "Save"; + + private DataConversionService conversionManager; + private GUIBuilderService guiBuilder; + + protected void activate(ComponentContext componentContext) { + this.conversionManager = (DataConversionService) componentContext.locateService("DCS"); + this.guiBuilder = (GUIBuilderService) componentContext.locateService("GBS"); + + } + + public Converter promptForConverter(final Data outDatum, String targetMimeType) + throws FileSaveException { + final Converter[] converters = + this.conversionManager.findConverters(outDatum, targetMimeType); + + if (converters.length == 0) { + throw new FileSaveException("No appropriate converters."); + } else if (converters.length == 1) { + // Only one possible choice in how to save data. Do it. + Converter onlyConverter = converters[0]; + + return onlyConverter; + } else { + final Shell parentShell = PlatformUI.getWorkbench().getWorkbenchWindows()[0].getShell(); + + if (parentShell.isDisposed()) { + throw new FileSaveException( + "Can't create dialog window -- graphical environment not available."); + } + + return showDataFormatChooser(outDatum, converters, parentShell); + } + } + + private Converter showDataFormatChooser( + final Data outDatum, + final Converter[] converters, + final Shell parentShell) throws FileSaveException{ + try { + final Converter[] chosenConverter = new Converter[1]; + guiRun(new Runnable() { + public void run() { + DataFormatChooser formatChooser = new DataFormatChooser( + outDatum, parentShell, converters, SAVE_DIALOG_TITLE); + formatChooser.createContent(new Shell(parentShell)); + formatChooser.open(); + chosenConverter[0] = formatChooser.getChosenConverter(); + } + }); + + return chosenConverter[0]; + } catch (Exception e) { + throw new FileSaveException(e.getMessage(), e); + } + } + + public File promptForTargetFile(final String fileName) throws FileSaveException { + final File[] resultFile = new File[1]; + + try { + guiRun(new Runnable() { + public void run() { + SaveAsController saveAs = + new SaveAsController(FileSaverServiceImpl.this.guiBuilder); + + resultFile[0] = saveAs.open(fileName); + } + }); + + return resultFile[0]; + } catch (Throwable e) { + throw new FileSaveException(e.getMessage(), e); + } + } + + public void saveTo(File sourceFile, File targetFile) throws FileSaveException { + if ((sourceFile != null) && (targetFile != null) && sourceFile.exists()) { + copyFile(sourceFile, targetFile); + } + } + + private void guiRun(Runnable run) { + final Shell parentShell = PlatformUI.getWorkbench().getWorkbenchWindows()[0].getShell(); + + if (Thread.currentThread() == Display.getDefault().getThread()) { + run.run(); + } else { + parentShell.getDisplay().syncExec(run); + } + } + + /* TODO: Don't use cns-utilities, use Files.copy in Guava + * This shouldn't throw FileSaveException -- too specific for a general utility. + * Catch whatever this throws then rethrow as FSE + */ + private static void copyFile(File sourceFile, File targetFile) throws FileSaveException { + try { + FileInputStream inputStream = new FileInputStream(sourceFile); + FileOutputStream outputStream = new FileOutputStream(targetFile); + + FileChannel readableChannel = inputStream.getChannel(); + FileChannel writableChannel = outputStream.getChannel(); + + writableChannel.truncate(0); + writableChannel.transferFrom( + readableChannel, 0, readableChannel.size()); + inputStream.close(); + outputStream.close(); + } catch (IOException ioException) { + String exceptionMessage = + "An error occurred when copying from the file \"" + + sourceFile.getAbsolutePath() + + "\" to the file \"" + + targetFile.getAbsolutePath() + + "\"."; + + throw new FileSaveException(exceptionMessage, ioException); // TODO Just throw IOException + } + } +} \ No newline at end of file Added: trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/SaveAsController.java =================================================================== --- trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/SaveAsController.java (rev 0) +++ trunk/core/org.cishell.reference/src/org/cishell/reference/app/service/filesaver/SaveAsController.java 2011-03-01 20:10:28 UTC (rev 1231) @@ -0,0 +1,115 @@ +package org.cishell.reference.app.service.filesaver; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import org.cishell.service.guibuilder.GUIBuilderService; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +public class SaveAsController { + public static final Collection<Character> INVALID_FILENAME_CHARACTERS = + Collections.unmodifiableCollection(Arrays.asList( + '\\', '/', ':', '*', '?', '"', '<', '>', '|', '%')); + public static final char FILENAME_CHARACTER_REPLACEMENT = '#'; + + public static final String FILE_EXTENSION_PREFIX = "file-ext:"; + + private static File currentDirectory; + + private GUIBuilderService guiBuilder; + + public SaveAsController(GUIBuilderService guiBuilder) { + ... [truncated message content] |