[Tynstep-svn] r141 - in trunk/step-web-server: . src src/main src/main/java src/main/java/com src/main/java/com/tyndalehouse src/main/java/com/tyndalehouse/step src/main/java/com/tyndalehouse/step/web src/main/java/com/tyndalehouse/step/web/server src/main/java/com/tyndalehouse/step/web/server/common src/main/java/com/tyndalehouse/step/web/server/db src/main/java/com/tyndalehouse/step/web/server/db/framework src/main/java/com/tyndalehouse/step/web/server/db/timeline src/main/java/com/tyndalehouse/step/web/server/guice src/main/java/com/tyndalehouse/step/web/server/handler src/main/java/com/tyndalehouse/step/web/server/handler/util src/main/java/com/tyndalehouse/step/web/server/handler/util/passage src/main/java/com/tyndalehouse/step/web/server/jsword src/main/java/com/tyndalehouse/step/web/server/jsword/com src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/step src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/step/web src/test src/test/java src/test/java/com src/test/java/com/tyndalehouse src/test/java/com/tyndalehouse/step src/test/java/com/tyndalehouse/step/web src/test/java/com/tyndalehouse/step/web/server src/test/java/com/tyndalehouse/step/web/server/db src/test/java/com/tyndalehouse/step/web/server/db/helper src/test/java/com/tyndalehouse/step/web/server/handlers src/test/resources src/test/resources/com src/test/resources/com/tyndalehouse src/test/resources/com/tyndalehouse/step src/test/resources/com/tyndalehouse/step/web src/test/resources/com/tyndalehouse/step/web/server src/test/resources/com/tyndalehouse/step/web/server/db src/test/resources/com/tyndalehouse/step/web/server/db/queries src/test/resources/com/tyndalehouse/step/web/server/db/queries/tests
ChrisBurrell at crosswire.org
ChrisBurrell at crosswire.org
Fri Jun 25 13:30:48 MST 2010
Author: ChrisBurrell
Date: 2010-06-25 13:30:48 -0700 (Fri, 25 Jun 2010)
New Revision: 141
Added:
trunk/step-web-server/pom.xml
trunk/step-web-server/src/
trunk/step-web-server/src/main/
trunk/step-web-server/src/main/java/
trunk/step-web-server/src/main/java/com/
trunk/step-web-server/src/main/java/com/tyndalehouse/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/AbstractStepHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/ConfigNotLoadedException.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/ConfigProvider.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/JSwordConstants.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/MalformedStepQueryException.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/Query.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/QueryImpl.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/ResultSetProcessor.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQuery.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunner.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunnerImpl.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/UnableToRunQueryException.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimeBandVisibleDateProcessor.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginDbBean.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginProcessor.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineSetupDataProcessor.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/CustomDispatchServiceServlet.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/DispatchServletModule.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/LogProvider.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/MyGuiceServletConfig.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/ServerModule.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetAvailableBibleVersionsHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetBibleBooksHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetCurrentBibleTextHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetDictionaryDefinitionHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetEventsForDateRangeHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetLocationsHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineOriginForScriptureHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineUISetupHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/InstallJswordModuleHandler.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/util/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/StrongMorphMap.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/ConfigurableHTMLConverter.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/XSLTProperty.java
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/com/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/step/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/step/web/
trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/step/web/server/
trunk/step-web-server/src/test/
trunk/step-web-server/src/test/java/
trunk/step-web-server/src/test/java/com/
trunk/step-web-server/src/test/java/com/tyndalehouse/
trunk/step-web-server/src/test/java/com/tyndalehouse/step/
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/StepQueryRunnerImplTest.java
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/TestProcessor.java
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/TestQueryImpl.java
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetCurrentBibleTextHandlerTest.java
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetDictionaryDefinitionHandlerTest.java
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetTimelineUISetupHandlerTest.java
trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/JSwordInstallTest.java
trunk/step-web-server/src/test/resources/
trunk/step-web-server/src/test/resources/com/
trunk/step-web-server/src/test/resources/com/tyndalehouse/
trunk/step-web-server/src/test/resources/com/tyndalehouse/step/
trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/
trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/server/
trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/server/db/
trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/server/db/queries/
trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/server/db/queries/tests/
trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/server/db/queries/tests/test_query_params_different_types.sql
Log:
creation of server side code for web-server
Added: trunk/step-web-server/pom.xml
===================================================================
--- trunk/step-web-server/pom.xml (rev 0)
+++ trunk/step-web-server/pom.xml 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,156 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>com.tyndalehouse</groupId>
+ <artifactId>step-parent</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.tyndalehouse</groupId>
+ <artifactId>step-web-server</artifactId>
+ <packaging>jar</packaging>
+ <name>step-web-server</name>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>com.tyndalehouse</groupId>
+ <artifactId>step-web-shared</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.crosswire</groupId>
+ <artifactId>jsword</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.gwt</groupId>
+ <artifactId>gwt-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.gwt</groupId>
+ <artifactId>gwt-user</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.inject.extensions
+ </groupId>
+ <artifactId>guice-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>net.customware.gwt.dispatch</groupId>
+ <artifactId>gwt-dispatch</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-dbcp</groupId>
+ <artifactId>commons-dbcp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jmock</groupId>
+ <artifactId>jmock</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jmock</groupId>
+ <artifactId>jmock-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derbyclient</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <systemPropertyVariables>
+ <db.driver>${db.driver}</db.driver>
+ <connection.string>${db.connection.string}</connection.string>
+ <step.proxy.host>${step.http.proxy}</step.proxy.host>
+ <step.proxy.port>{step.http.port}</step.proxy.port>
+ </systemPropertyVariables>
+ <includes>
+ <include>**/*Test.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.3</version>
+ <configuration>
+ <check>
+ <branchRate>85</branchRate>
+ <lineRate>85</lineRate>
+ <haltOnFailure>false</haltOnFailure>
+ <totalBranchRate>60</totalBranchRate>
+ <totalLineRate>60</totalLineRate>
+ <packageLineRate>60</packageLineRate>
+ <packageBranchRate>60</packageBranchRate>
+ <!--
+ <regexes> <regex>
+ <pattern>com.example.reallyimportant.*</pattern>
+ <branchRate>90</branchRate> <lineRate>80</lineRate> </regex>
+ <regex> <pattern>com.example.boringcode.*</pattern>
+ <branchRate>40</branchRate> <lineRate>30</lineRate> </regex>
+ </regexes>
+ -->
+ </check>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>clean</goal>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ </plugins>
+ </build>
+</project>
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/AbstractStepHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/AbstractStepHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/AbstractStepHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,45 @@
+package com.tyndalehouse.step.web.server.common;
+
+import java.lang.reflect.ParameterizedType;
+
+import net.customware.gwt.dispatch.server.ActionHandler;
+import net.customware.gwt.dispatch.shared.Action;
+import net.customware.gwt.dispatch.shared.Result;
+
+import org.apache.log4j.Logger;
+
+/**
+ * To abstract away the need for declaring getActionType every time.
+ *
+ * @author CJBurrell
+ *
+ * @param <A>
+ * the action in question
+ * @param <R>
+ * the response to be sent back to the client
+ */
+public abstract class AbstractStepHandler<A extends Action<R>, R extends Result> implements ActionHandler<A, R> {
+
+ /**
+ * Logger for a particular instance of a handler
+ */
+ private final Logger logger = Logger.getLogger(this.getClass());
+
+ @SuppressWarnings("unchecked")
+ /*
+ * returns the type of the action
+ *
+ * @return the type of the action
+ */
+ public final Class<A> getActionType() {
+ final ParameterizedType pt = (ParameterizedType) getClass().getGenericSuperclass();
+ return (Class<A>) pt.getActualTypeArguments()[0];
+ }
+
+ /**
+ * @return the logger
+ */
+ protected final Logger getLogger() {
+ return logger;
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/ConfigNotLoadedException.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/ConfigNotLoadedException.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/ConfigNotLoadedException.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,28 @@
+package com.tyndalehouse.step.web.server.common;
+
+/**
+ * an exceptoin to indicate that the configuration properties have not been
+ * loaded
+ *
+ * @author CJBurrell
+ *
+ */
+public class ConfigNotLoadedException extends Exception {
+
+ /**
+ * serial id for serialization
+ */
+ private static final long serialVersionUID = 1644291687028980017L;
+
+ /**
+ * public constructor an exceptoin to indicate that the configuration
+ * properties have not been loaded
+ *
+ * @param e
+ * the base exception
+ */
+ public ConfigNotLoadedException(final Exception e) {
+ super("The configuration files could not be loaded", e);
+ }
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/ConfigProvider.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/ConfigProvider.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/ConfigProvider.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,99 @@
+package com.tyndalehouse.step.web.server.common;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+/**
+ * Config Provider for Step. TODO: Possibly should be rewritten to have a Guice
+ * element to it, with @Singleton tag
+ *
+ * @author CJBurrell
+ *
+ */
+public final class ConfigProvider {
+ /**
+ * internal static provider
+ */
+ private static ConfigProvider pr;
+
+ /**
+ * Internal properties object
+ */
+ private final Properties p = new Properties();
+
+ /**
+ * private constructor to prevent initialisation.
+ *
+ * @throws ConfigNotLoadedException
+ * exception should it fail to look up the parameter name
+ */
+ private ConfigProvider() throws ConfigNotLoadedException {
+ load();
+ }
+
+ /**
+ * Loads or reloads a properties file from the classpath. TODO: investigate
+ * issue with concurrency here, since we might access p before it's fully
+ * loaded...
+ *
+ * @throws ConfigNotLoadedException
+ * exception should it fail to look up the parameter name
+ */
+ public void load() throws ConfigNotLoadedException {
+ final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ final URL url = loader.getResource("com/tyndalehouse/step/web/server/config/environment.properties");
+ try {
+ p.load(url.openStream());
+ } catch (final IOException e) {
+ throw new ConfigNotLoadedException(e);
+ }
+ }
+
+ /**
+ * Gets the value of a param.
+ *
+ * @param name
+ * the name of the param
+ * @return the value of the param
+ * @throws ConfigNotLoadedException
+ * A problem occured during loading of the config
+ */
+ public synchronized static String get(final String name) throws ConfigNotLoadedException {
+ if (ConfigProvider.pr == null) {
+ ConfigProvider.pr = new ConfigProvider();
+ }
+
+ String value = System.getProperty(name);
+ if (value == null) {
+ value = ConfigProvider.pr.readProperty(name);
+ }
+
+ return value;
+
+ }
+
+ /**
+ * reads a property on the properties object.
+ *
+ * @param name
+ * name of the property
+ * @return the value
+ */
+ private String readProperty(final String name) {
+ return p.getProperty(name);
+ }
+
+ /**
+ * returns an integer corresponding to the name of the parameter.
+ *
+ * @param paramName
+ * the name of the parameter
+ * @return an integer value for paramName
+ * @throws ConfigNotLoadedException
+ * exception should it fail to look up the parameter name
+ */
+ public static int getInt(final String paramName) throws ConfigNotLoadedException {
+ return Integer.parseInt(get(paramName));
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/JSwordConstants.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/JSwordConstants.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/common/JSwordConstants.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,53 @@
+package com.tyndalehouse.step.web.server.common;
+
+/**
+ * Constants to map back to the correct JSword modules, index entries
+ *
+ * @author CJBurrell
+ *
+ */
+public final class JSwordConstants {
+ /**
+ * the pattern with which strong references in OSIS start
+ */
+ public static final String STRONG_PATTERN_START = "strong:";
+
+ /**
+ * a greek marker for strong numbers, e.g. strong:Gxxxx
+ */
+ public static final char STRONG_GREEK_MARKER = 'G';
+
+ /**
+ * Strong hebrew marker, for e.g. strong:Hxxxx
+ */
+ public static final char STRONG_HEBREW_MARKER = 'H';
+
+ /**
+ * Initials of default Hebrew JSword module to use for lookup of dictionary
+ * definitions
+ */
+ public static final String STRONG_HEBREW_DICTIONARY_INITIALS = "StrongsHebrew";
+
+ /**
+ * Initials of default Strong JSword greek dictionary module for lookup of
+ * dictionary definitions
+ */
+ public static final String STRONG_GREEK_DICTIONARY_INITIALS = "StrongsGreek";
+
+ /**
+ * Default hebrew text for interlinear purposes
+ */
+ public static final String DEFAULT_HEBREW_INTERLINEAR_TEXT = "LXX";
+
+ // TODO:This gives us greek!
+ /**
+ * Default Greek text for interlinear purposes
+ */
+ public static final String DEFAULT_GREEK_INTERLINEAR_TEXT = "BYZ";
+
+ /**
+ * hiding default constructor
+ */
+ private JSwordConstants() {
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/MalformedStepQueryException.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/MalformedStepQueryException.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/MalformedStepQueryException.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,47 @@
+package com.tyndalehouse.step.web.server.db.framework;
+
+/**
+ * Query to be thrown if the query file cannot be parsed by our framework.
+ *
+ * @author CJBurrell
+ *
+ */
+public class MalformedStepQueryException extends Exception {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -3607780460262284122L;
+
+ /**
+ * to instantiate the exception when a particular parameter name is
+ * incorrect
+ *
+ * @param paramName
+ * parameter name that is incorrect
+ * @param sql
+ * sql in which parameter name was incorrect
+ */
+ public MalformedStepQueryException(final String paramName, final String sql) {
+ super(String.format("The argument %s was not recognised in query:\n %s", paramName, sql));
+ }
+
+ /**
+ * @param message
+ * the message
+ * @param ex
+ * base exception to be passed up to the super class
+ */
+ public MalformedStepQueryException(final String message, final Exception ex) {
+ super(message, ex);
+ }
+
+ /**
+ *
+ * @param message
+ * simple message to instantiate the default exception
+ */
+ public MalformedStepQueryException(final String message) {
+ super(message);
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/Query.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/Query.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/Query.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,21 @@
+package com.tyndalehouse.step.web.server.db.framework;
+
+/**
+ * The interface for any enum describing the queries to be run
+ *
+ * @author CJBurrell
+ *
+ */
+public interface Query {
+ /**
+ * @return the component name
+ */
+ String getComponent();
+
+ /**
+ * returns the name of the enum
+ *
+ * @return the name of the query
+ */
+ String name();
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/QueryImpl.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/QueryImpl.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/QueryImpl.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,51 @@
+package com.tyndalehouse.step.web.server.db.framework;
+
+/**
+ * List of queries to be executed against DB
+ *
+ * @author CJBurrell
+ *
+ */
+public enum QueryImpl implements Query {
+ /**
+ * gets events for a particular date range
+ */
+ GET_EVENTS_FOR_DATE_RANGE("timeline"),
+
+ /**
+ * gets timeline description data
+ */
+ GET_TIMELINE_SETUP_DATA("timeline"),
+
+ /**
+ * looks up which is the closest event, and on which timeline a given
+ * scripture passage is
+ */
+ LOOKUP_TIMELINE_ORIGIN("timeline");
+
+ /**
+ * component (folder) in which the component can be found
+ */
+ private final String component;
+
+ /**
+ * default constructor for this enum
+ *
+ * @param component
+ * component/folder where the query resides
+ */
+ QueryImpl(final String component) {
+ this.component = component;
+ }
+
+ /**
+ * (non-Javadoc)
+ *
+ * @see com.tyndalehouse.step.web.server.db.framework.Query#getComponent()
+ * @return component/folder where the query resides
+ */
+ public String getComponent() {
+ return component;
+ }
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/ResultSetProcessor.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/ResultSetProcessor.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/ResultSetProcessor.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,47 @@
+package com.tyndalehouse.step.web.server.db.framework;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+
+import com.tyndalehouse.step.web.server.common.ConfigNotLoadedException;
+
+/**
+ * @author CJBurrell This is used by the query runner to process result sets
+ * @param <T>
+ * the type of bean to be returned
+ */
+public interface ResultSetProcessor<T> {
+ /**
+ * returns the parameters. Typically this would only be called by the query
+ * framework
+ *
+ * @return a map, mapping the parameter name to the object to be passed into
+ * the query (generally native types or Strings)
+ */
+ Map<String, Object> getParameters();
+
+ /**
+ * Returns the enum defining which query should be executed.
+ *
+ * @return the query to be executed.
+ */
+ Query getQuery();
+
+ /**
+ * This method will be called after a query has been run by the query
+ * framework. It returns a list of beans to the caller
+ *
+ * @param rs
+ * ResultSet to be processed
+ * @return a list of beans to the UI of type T
+ * @throws MalformedStepQueryException
+ * the query run was malformed
+ * @throws ConfigNotLoadedException
+ * an error occured during the loading of the database config
+ * @throws SQLException
+ * a SQL exception occurred
+ */
+ List<T> process(ResultSet rs) throws MalformedStepQueryException, ConfigNotLoadedException, SQLException;
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQuery.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQuery.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQuery.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,170 @@
+package com.tyndalehouse.step.web.server.db.framework;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Step Query to be executed against the database. This this is then given to
+ * the StepQueryRunner and executed It contains the list of arguments, the types
+ * of those parameters and the sql statement to be executed
+ *
+ * @author CJBurrell
+ *
+ */
+public class StepQuery {
+ /**
+ * list of expected arguments
+ */
+ private final List<String> arguments;
+
+ /**
+ * the types of the expected parameters
+ */
+ private final Map<String, Integer> paramTypes;
+
+ /**
+ * the SQL statements
+ */
+ private String sql;
+
+ /**
+ * public constructor which initialises the arguments and parameters.
+ */
+ public StepQuery() {
+ arguments = new ArrayList<String>();
+ paramTypes = new HashMap<String, Integer>();
+ }
+
+ /**
+ * adding an argument as found in the query definition: e.g. <code>
+ * select 1 from table where value = #paramName#
+ * </code>
+ *
+ * @param paramName
+ * param name to be added to the query definition
+ *
+ */
+ public void addArgument(final String paramName) {
+ arguments.add(paramName);
+ }
+
+ /**
+ * addings a mapping from the definitions at the top of the file
+ *
+ * @param paramName
+ * parameter name
+ * @param type
+ * type of the parameter
+ */
+ public void addParamTypeMapping(final String paramName, final Integer type) {
+ paramTypes.put(paramName, type);
+ }
+
+ /**
+ * returns the SQL that gets executed
+ *
+ * @return the SQL query
+ */
+ public String getSQLText() {
+ return sql;
+ }
+
+ /**
+ * Sets the sql for the step query to be run
+ *
+ * @param sql
+ * sql representing the query to be run
+ */
+ public void setSQLText(final String sql) {
+ this.sql = sql;
+ }
+
+ /**
+ * Sets up the prepared statement arguments in the correct order.
+ *
+ * @param ps
+ * the prepared statement
+ * @param passedArguments
+ * the map of named arguments
+ * @throws SQLException
+ * this is thrown if the passed in arguments do not match the
+ * expected parameters as loaded from disk
+ *
+ */
+ public void setupParameters(final PreparedStatement ps, final Map<String, Object> passedArguments)
+ throws SQLException {
+ int argIndex = 1;
+ for (final String argName : arguments) {
+ setArgument(ps, paramTypes.get(argName), passedArguments.get(argName), argIndex++);
+ }
+ }
+
+ /**
+ * Validates the query loaded, to ensure that the number of arguments found
+ * in the query match the number of arguments found in the declarations
+ *
+ * @throws MalformedStepQueryException
+ * this is thrown if the validation fails
+ */
+ public void validate() throws MalformedStepQueryException {
+ for (final String arg : arguments) {
+ if (!paramTypes.containsKey(arg)) {
+ throw new MalformedStepQueryException(arg, sql);
+ }
+ }
+
+ // TODO: optimize by compiling prepared statement here!
+ }
+
+ /**
+ * Sets up the parameter into the prepared statement
+ *
+ * @param ps
+ * prepared statement
+ * @param sqlType
+ * the type of the parameter
+ * @param value
+ * the value of the parameter
+ * @param argIndex
+ * the position at which the parameter is to be placed in the
+ * prepared statement
+ * @throws SQLException
+ * an exception thrown in case something goes wrong
+ */
+ private void setArgument(final PreparedStatement ps, final int sqlType, final Object value, final int argIndex)
+ throws SQLException {
+ // check for null first
+ if (value == null) {
+ ps.setNull(argIndex, sqlType);
+ return;
+ }
+
+ // at this stage, we do not need to worry about null variables
+ switch (sqlType) {
+ case Types.INTEGER:
+ ps.setInt(argIndex, (Integer) value);
+ break;
+ case Types.VARCHAR:
+ ps.setString(argIndex, (String) value);
+ break;
+ case Types.BIGINT:
+ ps.setLong(argIndex, (Long) value);
+ break;
+ case Types.SMALLINT:
+ ps.setShort(argIndex, (Short) value);
+ break;
+ case Types.LONGVARCHAR:
+ ps.setString(argIndex, (String) value);
+ break;
+ default:
+ throw new SQLException(String.format(
+ "The STEP query framework does not yet support this type/value (%d, %s)", sqlType, value
+ .toString()));
+ }
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunner.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunner.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunner.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,38 @@
+package com.tyndalehouse.step.web.server.db.framework;
+
+import java.util.List;
+
+/**
+ * StepQueryRunner interface defining what should be present for the clients to
+ * use this as a library
+ *
+ * @author CJBurrell
+ *
+ */
+public interface StepQueryRunner {
+
+ /**
+ * Clears the cache of parsed queries that are currently in the query runner
+ */
+ void clearCache();
+
+ /**
+ * Tears down the database pool and starts it up again
+ */
+ void restartDatasourcePool();
+
+ /**
+ * To run a query in the database
+ *
+ * @param <T>
+ * Type of bean to be returned
+ * @param processor
+ * Processor to be invoked: @see {@link ResultSetProcessor}
+ * @return a list of beans of type T
+ * @throws UnableToRunQueryException
+ * if the configuration was not loaded or a sql exception during
+ * parsing or execution of the call
+ */
+ <T> List<T> run(final ResultSetProcessor<T> processor) throws UnableToRunQueryException;
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunnerImpl.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunnerImpl.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunnerImpl.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,363 @@
+package com.tyndalehouse.step.web.server.db.framework;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.tyndalehouse.step.web.server.common.ConfigNotLoadedException;
+import com.tyndalehouse.step.web.server.common.ConfigProvider;
+
+/**
+ * This class is the crux of the database access. An enum identifies the SQL
+ * file to be loaded. Arguments get defined in the query file as define
+ * variableName as sqlType A map can be passed in that ensures all arguments are
+ * mapped to the correct location in the prepared statement
+ *
+ * @author CJBurrell
+ */
+ at Singleton
+public class StepQueryRunnerImpl implements StepQueryRunner {
+ /**
+ * query to indicate whether to cache prepared statements. Currently doesn't
+ * work well with Apache Derby
+ */
+ private static final Object CACHE_QUERY_PROPERTY = "query.runner.cache";
+
+ /**
+ * Datasource object which gets loaded through a conection pool
+ */
+ private static DataSource datasource = null;
+
+ /**
+ * pattern definition of a declaration of argument at the top of a SQL file
+ */
+ private static final String DEFINITION_PATTERN = "define (\\w+) as (\\w+)";
+
+ /**
+ * the HASH character
+ */
+ private static final String HASH = "#";
+
+ /**
+ * the hashmap containing the cache of all queries
+ */
+ private static HashMap<Query, StepQuery> queries = new HashMap<Query, StepQuery>();
+
+ /**
+ * the ?, QUESTION MARK character
+ */
+ private static final String QUESTION_MARK = "?";
+
+ /**
+ * a pointer to the Log4J log
+ */
+ private final Log log;
+
+ /**
+ * prevent instantiation
+ *
+ * @param log
+ * default logger to use throughout implementation
+ */
+ @Inject
+ public StepQueryRunnerImpl(final Log log) {
+ this.log = log;
+ }
+
+ public void clearCache() {
+ StepQueryRunnerImpl.queries.clear();
+ }
+
+ public void restartDatasourcePool() {
+ // TODO: feature is to kill off all connections, and reload it.
+
+ }
+
+ /**
+ * returns a list of beans of type T
+ *
+ * @param processor
+ * processor to be used
+ * @param <T>
+ * the type of the bean to be returned
+ * @return list of beans of type T
+ * @throws UnableToRunQueryException
+ * unable to run the query for various reasons
+ * @see com.tyndalehouse.step.web.server.db.StepQueryRunner#run(com.tyndalehouse
+ * .step.web.server.db.ResultSetProcessor)
+ */
+ public <T> List<T> run(final ResultSetProcessor<T> processor) throws UnableToRunQueryException {
+ ResultSet rs;
+ Connection connection = null;
+ PreparedStatement ps = null;
+
+ // check for null
+ if (processor == null) {
+ log.error("The passed in ResultSetProcessor was null.");
+ throw new UnableToRunQueryException(new NullPointerException());
+ }
+
+ final long tInit = System.currentTimeMillis();
+ StepQuery stepQuery = null;
+ try {
+ stepQuery = prepareStepQuery(processor.getQuery());
+
+ final long tAfterLoad = System.currentTimeMillis();
+ connection = StepQueryRunnerImpl.datasource.getConnection();
+ ps = connection.prepareStatement(stepQuery.getSQLText());
+
+ final long tAfterParse = System.currentTimeMillis();
+ stepQuery.setupParameters(ps, processor.getParameters());
+
+ logStepQuery(processor, stepQuery);
+ final long tAfterLog = System.currentTimeMillis();
+
+ // TODO: not returning anything!
+ rs = ps.executeQuery();
+ final long tAfterExecute = System.currentTimeMillis();
+
+ final List<T> results = processor.process(rs);
+ final long tAfterParseResults = System.currentTimeMillis();
+
+ if (log.isInfoEnabled()) {
+ log.info(String.format("StepQueryRunner (load, parse, execute, return) = (%d, %d, %d, %d)", tAfterLoad
+ - tInit, tAfterParse - tAfterLoad, tAfterExecute - tAfterLog, tAfterParseResults
+ - tAfterExecute));
+ }
+
+ return results;
+ } catch (final ConfigNotLoadedException e) {
+ log.error("Unable to load the configuration file to set up datasource.");
+ throw new UnableToRunQueryException(e, stepQuery);
+ } catch (final MalformedStepQueryException e) {
+ log.error("An exception occured during the execution of the sql query");
+ throw new UnableToRunQueryException(e, stepQuery);
+ } catch (final SQLException e) {
+ log.error("An exception occured file trying to locate the file.");
+ throw new UnableToRunQueryException(e, stepQuery);
+ } finally {
+ // close the statement
+ if (ps != null) {
+ try {
+ ps.close();
+ } catch (final SQLException exception) {
+ log.error("Error finalising connection", exception);
+ }
+ }
+
+ // close the connection
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (final SQLException exception) {
+ log.error("Error finalising connection", exception);
+ }
+ }
+ }
+ }
+
+ /**
+ * if logging is enabled at trace level, then the query is output, with all
+ * its parameters
+ *
+ * @param processor
+ * processor to process results of the query, which contains the
+ * parameters
+ * @param stepQuery
+ * the query to be logged
+ */
+ private void logStepQuery(final ResultSetProcessor<?> processor, final StepQuery stepQuery) {
+ if (log.isTraceEnabled()) {
+ final StringBuffer logOutput = new StringBuffer();
+ logOutput.append("Query is: ");
+ logOutput.append(stepQuery.getSQLText());
+
+ for (final String paramName : processor.getParameters().keySet()) {
+ logOutput.append(' ');
+ logOutput.append(paramName);
+ logOutput.append('=');
+ logOutput.append(processor.getParameters().get(paramName));
+ logOutput.append(", ");
+ }
+ log.trace(logOutput.toString());
+ }
+ }
+
+ /**
+ * Faster than a regexp, so use this , in which we expect that there are
+ * arguments to be parsed These would be defined as #query-param# within the
+ * sql text. The function works by looking for a open and then a closed #
+ * Unfortunately, it is not perfect and will have TODO; be rewritten to
+ * ensure that the programmer can use the charact # in his query
+ *
+ * @param q
+ * is the query
+ * @return a object of type {@link StepQuery}
+ */
+ private StepQuery parseArguments(final StringBuffer q) {
+ final StepQuery query = new StepQuery();
+
+ int openingHash = 0;
+ while ((openingHash = q.indexOf(StepQueryRunnerImpl.HASH)) != -1) {
+ final int endingHash = q.indexOf(StepQueryRunnerImpl.HASH, openingHash + 1);
+ final String paramName = q.substring(openingHash + 1, endingHash);
+ query.addArgument(paramName);
+ q.replace(openingHash, endingHash + 1, StepQueryRunnerImpl.QUESTION_MARK);
+ }
+
+ return query;
+ }
+
+ /**
+ * Look for all lines containing the pattern define variable_name as type
+ * Then removes those into a map before continuing
+ *
+ * @param queryText
+ * sql text as loaded from disk
+ * @param q
+ * query text to look through
+ * @return a object of type {@link StepQuery}
+ * @throws MalformedStepQueryException
+ * an exception is thrown to indicate an
+ */
+ private StepQuery parseDefinitions(final StringBuffer queryText, final StepQuery q)
+ throws MalformedStepQueryException {
+ // all sql files with parameters will have definitions for their
+ // parameters at the top.
+ final Pattern p = Pattern.compile(StepQueryRunnerImpl.DEFINITION_PATTERN);
+ final Matcher m = p.matcher(queryText);
+
+ // iterate through definitions that have been found
+ while (m.find()) {
+ final String paramName = m.group(1);
+ final String paramType = m.group(2);
+
+ try {
+ final Integer type = Types.class.getField(paramType.toUpperCase()).getInt(null);
+ q.addParamTypeMapping(paramName, type);
+ } catch (final IllegalArgumentException e) {
+ throw new MalformedStepQueryException(String.format("Could not parse argument type: %s", paramType), e);
+ } catch (final SecurityException e) {
+ throw new MalformedStepQueryException(String.format("Could not parse argument type: %s", paramType), e);
+ } catch (final IllegalAccessException e) {
+ throw new MalformedStepQueryException(String.format("Could not parse argument type: %s", paramType), e);
+ } catch (final NoSuchFieldException e) {
+ throw new MalformedStepQueryException(String.format("Could not parse argument type: %s", paramType), e);
+ }
+ }
+
+ q.setSQLText(m.replaceAll(""));
+ return q;
+ }
+
+ /**
+ * @param query
+ * query to be executed. If already cached, then this query is
+ * returned otherwise, it is loaded from disk
+ * @return a object of type {@link StepQuery}
+ * @throws ConfigNotLoadedException
+ * if an issue occured during loading of the configuration for
+ * STEP
+ * @throws MalformedStepQueryException
+ * an exception is thrown to indicate an issue with the sql file
+ * that could not be parsed
+ */
+ private StepQuery prepareStepQuery(final Query query) throws ConfigNotLoadedException, MalformedStepQueryException {
+ StepQuery stepQuery = StepQueryRunnerImpl.queries.get(query);
+ // check whether query is in cache
+ if (stepQuery == null) {
+ stepQuery = readQueryFromFile(query);
+ }
+
+ // now check if datasource is null
+ if (StepQueryRunnerImpl.datasource == null) {
+ StepQueryRunnerImpl.datasource = setupDatasource();
+ }
+ return stepQuery;
+ }
+
+ /**
+ * Reads a query from the file
+ *
+ * @param query
+ * query to be loaded
+ * @return returns a loaded {@link StepQuery} object
+ * @throws ConfigNotLoadedException
+ * failed to load the configuration
+ * @throws MalformedStepQueryException
+ * thrown if arguments found don't match a declaration
+ */
+ private StepQuery readQueryFromFile(final Query query) throws ConfigNotLoadedException, MalformedStepQueryException {
+ // get base path from file
+ final String basePath = ConfigProvider.get("query.repository.path");
+ final String baseComponent = query.getComponent();
+ final String filenameBase = query.name();
+
+ // read query from file
+ final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ final String filename = String.format("%s%s/%s.sql", basePath, baseComponent, filenameBase.toLowerCase());
+ final URL fileLocation = loader.getResource(filename);
+ StepQuery stepQuery = null;
+ StringBuffer q;
+
+ // check file location is non null:
+ if (fileLocation == null) {
+ throw new MalformedStepQueryException(String.format("The filename %s does not exist.", filename));
+ }
+
+ try {
+ q = new StringBuffer(FileUtils.readFileToString(new File(fileLocation.getFile())));
+ stepQuery = parseDefinitions(q, parseArguments(q));
+ stepQuery.validate();
+
+ // check whether or not to cache the query:
+ if (ConfigProvider.get("query.runner.cache").equals(StepQueryRunnerImpl.CACHE_QUERY_PROPERTY)) {
+ StepQueryRunnerImpl.queries.put(query, stepQuery);
+ }
+ } catch (final IOException e) {
+ throw new MalformedStepQueryException(String.format("Error reading query file: %s", filenameBase), e);
+ }
+
+ return stepQuery;
+ }
+
+ /**
+ * sets up the datasource from properties
+ *
+ * @return the datasource properly configured
+ * @throws ConfigNotLoadedException
+ * throws if properties aren't found
+ */
+ private DataSource setupDatasource() throws ConfigNotLoadedException {
+ final BasicDataSource ds = new BasicDataSource();
+ ds.setDriverClassName(ConfigProvider.get("db.driver"));
+ ds.setUsername(ConfigProvider.get("db.user"));
+ ds.setPassword(ConfigProvider.get("db.password"));
+ ds.setUrl(ConfigProvider.get("connection.string"));
+ ds.setInitialSize(ConfigProvider.getInt("db.pool.initialSize"));
+ ds.setMaxActive(ConfigProvider.getInt("db.pool.maxSize"));
+ // ds.setValidationQuery(ConfigProvider.get("db.pool.validation.query"));
+ // ds.setPoolPreparedStatements(true); //NOT Supported by java DB :(
+ ds.setMaxOpenPreparedStatements(ConfigProvider.getInt("db.pool.prepared.size"));
+ ds.setDefaultAutoCommit(false);
+
+ return ds;
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/UnableToRunQueryException.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/UnableToRunQueryException.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/framework/UnableToRunQueryException.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,60 @@
+package com.tyndalehouse.step.web.server.db.framework;
+
+/**
+ * An issue occurred during the parsing or running of a query
+ *
+ * @author CJBurrell
+ *
+ */
+public class UnableToRunQueryException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7810594097160119720L;
+
+ /**
+ * The StepQuery at the origin of the exception
+ */
+ private StepQuery stepQuery;
+
+ /**
+ * Pass in the root cause of the exception
+ *
+ * @param e
+ * the root exception
+ */
+ public UnableToRunQueryException(final Exception e) {
+ super(e);
+ }
+
+ /**
+ * Unable to run a query exception, with the stepQuery itself, and the root
+ * exception
+ *
+ * @param e
+ * the exception to be wrapped
+ * @param stepQuery
+ * a step query that was attempted to be executed
+ */
+ public UnableToRunQueryException(final Exception e, final StepQuery stepQuery) {
+ this(e);
+ this.stepQuery = stepQuery;
+ }
+
+ /**
+ * @return the stepQuery
+ */
+ public final StepQuery getStepQuery() {
+ return stepQuery;
+ }
+
+ /**
+ * @param stepQuery
+ * the stepQuery to set
+ */
+ public final void setStepQuery(final StepQuery stepQuery) {
+ this.stepQuery = stepQuery;
+ }
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimeBandVisibleDateProcessor.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimeBandVisibleDateProcessor.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimeBandVisibleDateProcessor.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,145 @@
+package com.tyndalehouse.step.web.server.db.timeline;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.tyndalehouse.step.web.server.common.ConfigNotLoadedException;
+import com.tyndalehouse.step.web.server.db.framework.MalformedStepQueryException;
+import com.tyndalehouse.step.web.server.db.framework.Query;
+import com.tyndalehouse.step.web.server.db.framework.QueryImpl;
+import com.tyndalehouse.step.web.server.db.framework.ResultSetProcessor;
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineEventBean;
+
+/**
+ * Processes a list of timebands from the database
+ *
+ * @author CJBurrell cjburrell
+ *
+ */
+public class TimeBandVisibleDateProcessor implements ResultSetProcessor<TimelineEventBean> {
+
+ /**
+ * event type id
+ */
+ private static final String EVENT_TYPE_ID = "event_type_id";
+ /**
+ * certainty
+ */
+ private static final String CERTAINTY = "certainty";
+ /**
+ * importance if
+ */
+ private static final String IMPORTANCE_ID = "importance_id";
+ /**
+ * timeband id
+ */
+ private static final String TIMEBAND_ID = "timeband_id";
+ /**
+ * name
+ */
+ private static final String NAME = "name";
+ /**
+ * to precision
+ */
+ private static final String TO_PRECISION = "to_precision";
+ /**
+ * from precision
+ */
+ private static final String FROM_PRECISION = "from_precision";
+ /**
+ * to date
+ */
+ private static final String TO_DATE = "to_date";
+ /**
+ * from date
+ */
+ private static final String FROM_DATE = "from_date";
+ /**
+ * event id
+ */
+ private static final String EVENT_ID = "event_id";
+ /**
+ * min date
+ */
+ private static final String MIN_DATE = "min_date";
+ /**
+ * max date
+ */
+ private static final String MAX_DATE = "max_date";
+ /**
+ * params to be passed in to the query
+ */
+ private final Map<String, Object> params;
+
+ /**
+ * public constructor to create the processor with default parameters
+ *
+ * @param minDate
+ * min date to be passed to the query
+ * @param maxDate
+ * max date to be passed to the query
+ * @param timebandId
+ * the timeband id to be looked up
+ */
+ public TimeBandVisibleDateProcessor(final long minDate, final long maxDate, final int timebandId) {
+ params = new HashMap<String, Object>();
+ params.put(TimeBandVisibleDateProcessor.MIN_DATE, minDate);
+ params.put(TimeBandVisibleDateProcessor.MAX_DATE, maxDate);
+ params.put(TimeBandVisibleDateProcessor.TIMEBAND_ID, timebandId);
+ }
+
+ /**
+ * @see {@link ResultSetProcessor}
+ * @return the map of parameters
+ */
+ public final Map<String, Object> getParameters() {
+ return params;
+ }
+
+ /**
+ * @see {@link ResultSetProcessor}
+ * @return the query to be executed
+ */
+ public final Query getQuery() {
+ return QueryImpl.GET_EVENTS_FOR_DATE_RANGE;
+ }
+
+ /**
+ *
+ * @param rs
+ * result set to be processed
+ * @see com.tyndalehouse.step.web.server.db.framework.ResultSetProcessor#process(java.sql.ResultSet)
+ * @return a list of {@link TimelineEventBean} returned by the query
+ * @exception MalformedStepQueryException
+ * an error occurred during the execution of the query
+ * @exception ConfigNotLoadedException
+ * an error occurred during the loading of the configuration
+ * @exception SQLException
+ * an runtime SQL exception occurred
+ */
+ public final List<TimelineEventBean> process(final ResultSet rs) throws MalformedStepQueryException,
+ ConfigNotLoadedException, SQLException {
+ // TODO: parse the event in some object, as opposed to just fields like
+ // that!
+ // in particular the precision type
+ final List<TimelineEventBean> events = new ArrayList<TimelineEventBean>();
+ while (rs.next()) {
+ final Long toDate = rs.getObject(TimeBandVisibleDateProcessor.TO_DATE) == null ? null : rs
+ .getLong(TimeBandVisibleDateProcessor.TO_DATE);
+ final TimelineEventBean teb = new TimelineEventBean(rs.getInt(TimeBandVisibleDateProcessor.EVENT_ID), rs
+ .getLong(TimeBandVisibleDateProcessor.FROM_DATE), toDate, rs
+ .getString(TimeBandVisibleDateProcessor.FROM_PRECISION), rs
+ .getString(TimeBandVisibleDateProcessor.TO_PRECISION), rs
+ .getString(TimeBandVisibleDateProcessor.NAME), rs.getInt(TimeBandVisibleDateProcessor.TIMEBAND_ID),
+ rs.getInt(TimeBandVisibleDateProcessor.IMPORTANCE_ID), rs
+ .getString(TimeBandVisibleDateProcessor.CERTAINTY), rs
+ .getInt(TimeBandVisibleDateProcessor.EVENT_TYPE_ID));
+ events.add(teb);
+ }
+ return events;
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginDbBean.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginDbBean.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginDbBean.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,79 @@
+package com.tyndalehouse.step.web.server.db.timeline;
+
+import com.tyndalehouse.step.web.shared.timeline.Unit;
+
+/**
+ * Timeline Origin DB Bean, containing the default configuration for each
+ * timeband
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimelineOriginDbBean {
+
+ /**
+ * origin in time (milli seconds since epoch)
+ */
+ private long origin;
+ /**
+ * recommended time unit to be displayed
+ */
+ private Unit unit;
+
+ /**
+ * timeband id to be looked up
+ */
+ private int timebandId;
+
+ /**
+ * @return the origin
+ */
+ public final long getOrigin() {
+ return origin;
+ }
+
+ /**
+ * @return the unit
+ */
+ public final Unit getUnit() {
+ return unit;
+ }
+
+ /**
+ * Sets the origin field
+ *
+ * @param origin
+ * value in ms for oring
+ */
+ public final void setOrigin(final long origin) {
+ this.origin = origin;
+ }
+
+ /**
+ * Sets the unit for the bean
+ *
+ * @param unit
+ * unit that should be shown on screen
+ */
+ public final void setUnit(final String unit) {
+ this.unit = Unit.valueOf(unit);
+ }
+
+ /**
+ * returns the timeband id
+ *
+ * @return timeband id
+ */
+ public final int getTimebandId() {
+ return timebandId;
+ }
+
+ /**
+ * @param timebandId
+ * the timebandId to set
+ */
+ public final void setTimebandId(final int timebandId) {
+ this.timebandId = timebandId;
+ }
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginProcessor.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginProcessor.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginProcessor.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,79 @@
+package com.tyndalehouse.step.web.server.db.timeline;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.tyndalehouse.step.web.server.common.ConfigNotLoadedException;
+import com.tyndalehouse.step.web.server.db.framework.MalformedStepQueryException;
+import com.tyndalehouse.step.web.server.db.framework.Query;
+import com.tyndalehouse.step.web.server.db.framework.QueryImpl;
+import com.tyndalehouse.step.web.server.db.framework.ResultSetProcessor;
+
+/**
+ * Step Processor to retrieve the origin event, given a scripture passage
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimelineOriginProcessor implements ResultSetProcessor<TimelineOriginDbBean> {
+ /** result column origin */
+ private static final String ORIGIN = "origin";
+
+ /** input qry end,, verse no for which to restrict the query */
+ private static final String QRY_END = "qry_end";
+
+ /** input qry start, verse no for which to restrict the query */
+ private static final String QRY_START = "qry_start";
+
+ /** result column timeband id */
+ private static final String TIMEBAND = "timeband_id";
+
+ // TODO: move to enum
+ /** result column unit */
+ private static final String UNIT = "unit";
+
+ /** parameters to pass in to the query */
+ private final Map<String, Object> params;
+
+ /**
+ * Given a scripture range, it
+ *
+ * @param qryStart
+ * minimum verse no to restrict range lookup
+ * @param qryEnd
+ * maximum verse no to restrict range lookup
+ */
+ public TimelineOriginProcessor(final int qryStart, final int qryEnd) {
+ params = new HashMap<String, Object>();
+ params.put(TimelineOriginProcessor.QRY_START, qryStart);
+ params.put(TimelineOriginProcessor.QRY_END, qryEnd);
+ }
+
+ public Map<String, Object> getParameters() {
+ return params;
+
+ }
+
+ public Query getQuery() {
+ return QueryImpl.LOOKUP_TIMELINE_ORIGIN;
+ }
+
+ public List<TimelineOriginDbBean> process(final ResultSet rs) throws MalformedStepQueryException,
+ ConfigNotLoadedException, SQLException {
+ final List<TimelineOriginDbBean> origins = new ArrayList<TimelineOriginDbBean>();
+
+ while (rs.next()) {
+ final TimelineOriginDbBean bean = new TimelineOriginDbBean();
+ bean.setOrigin(rs.getLong(TimelineOriginProcessor.ORIGIN));
+ bean.setUnit(rs.getString(TimelineOriginProcessor.UNIT));
+ bean.setTimebandId(rs.getInt(TimelineOriginProcessor.TIMEBAND));
+ origins.add(bean);
+ }
+ return origins;
+ }
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineSetupDataProcessor.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineSetupDataProcessor.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineSetupDataProcessor.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,69 @@
+package com.tyndalehouse.step.web.server.db.timeline;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.tyndalehouse.step.web.server.common.ConfigNotLoadedException;
+import com.tyndalehouse.step.web.server.db.framework.MalformedStepQueryException;
+import com.tyndalehouse.step.web.server.db.framework.Query;
+import com.tyndalehouse.step.web.server.db.framework.QueryImpl;
+import com.tyndalehouse.step.web.server.db.framework.ResultSetProcessor;
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineBean;
+
+/**
+ * Data processor for the Step Query framework, to parse results from the
+ * timeline setup sql query
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimelineSetupDataProcessor implements ResultSetProcessor<TimelineBean> {
+ /**
+ * the result column timeband_description
+ */
+ private static final String TIMEBAND_DESCRIPTION = "timeband_description";
+
+ /** the result column timeband_id */
+ private static final String TIMEBAND_ID = "timeband_id";
+
+ /** the result column timeband unit */
+ private static final String TIMEBAND_UNIT = "timeband_unit";
+
+ /** the parameters to pass in to the query */
+ private final Map<String, Object> params;
+
+ /**
+ * public constructor
+ */
+ public TimelineSetupDataProcessor() {
+ params = new HashMap<String, Object>();
+ }
+
+ public Map<String, Object> getParameters() {
+ return params;
+
+ }
+
+ public Query getQuery() {
+ return QueryImpl.GET_TIMELINE_SETUP_DATA;
+ }
+
+ public List<TimelineBean> process(final ResultSet rs) throws MalformedStepQueryException, ConfigNotLoadedException,
+ SQLException {
+ final List<TimelineBean> timelines = new ArrayList<TimelineBean>();
+
+ while (rs.next()) {
+ final TimelineBean bean = new TimelineBean();
+ bean.setTimelineId(rs.getInt(TimelineSetupDataProcessor.TIMEBAND_ID));
+ bean.setTimelineDescription(rs.getString(TimelineSetupDataProcessor.TIMEBAND_DESCRIPTION));
+ bean.setUnit(rs.getString(TimelineSetupDataProcessor.TIMEBAND_UNIT));
+ timelines.add(bean);
+ }
+ return timelines;
+ }
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/CustomDispatchServiceServlet.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/CustomDispatchServiceServlet.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/CustomDispatchServiceServlet.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,49 @@
+package com.tyndalehouse.step.web.server.guice;
+
+import net.customware.gwt.dispatch.server.Dispatch;
+import net.customware.gwt.dispatch.server.service.DispatchServiceServlet;
+
+import org.apache.commons.logging.Log;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * Step dispatch servlet to use for the dispatchin of queries
+ *
+ * @author CJBurrell
+ *
+ */
+ at Singleton
+public class CustomDispatchServiceServlet extends DispatchServiceServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6063357416925075136L;
+
+ /**
+ * default logger
+ */
+ private final Log logger;
+
+ /**
+ * normal constructor
+ *
+ * @param dispatch
+ * dispath object
+ * @param logger
+ * logger to be provided
+ */
+ @Inject
+ public CustomDispatchServiceServlet(final Dispatch dispatch, final Log logger) {
+ super(dispatch);
+ this.logger = logger;
+ };
+
+ @Override
+ protected void doUnexpectedFailure(final Throwable e) {
+ logger.error("An unexpected error happened on the bridge between server and client", e);
+ }
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/DispatchServletModule.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/DispatchServletModule.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/DispatchServletModule.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,20 @@
+package com.tyndalehouse.step.web.server.guice;
+
+import com.google.inject.servlet.ServletModule;
+
+/**
+ * Servlet module for the Jetty/Tomcat server
+ *
+ * @author CJBurrell
+ *
+ */
+public class DispatchServletModule extends ServletModule {
+
+ @Override
+ public void configureServlets() {
+ // NOTE: the servlet context will probably need changing
+
+ serve("/step/dispatch").with(CustomDispatchServiceServlet.class);
+ }
+
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/LogProvider.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/LogProvider.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/LogProvider.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,43 @@
+package com.tyndalehouse.step.web.server.guice;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.impl.Log4JLogger;
+
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+/**
+ * A Gin provider for logging purposes.
+ *
+ * @author CJBurrell
+ *
+ */
+ at Singleton
+public class LogProvider implements Provider<Log> {
+ // enforce singleton to allow static methods to get to the same log
+ /**
+ * TODO: there should be a logger per class really. All appending to the
+ * same file, but so that we can turn them on and off
+ *
+ */
+ private static Log logger = new Log4JLogger("step.jetty");
+
+ /**
+ * The static equivalent of the above, so that static contexts can log as
+ * well
+ *
+ * @return the log to use
+ */
+ public static Log getLogger() {
+ return LogProvider.logger;
+ }
+
+ /**
+ * The instantiated log to be returned
+ *
+ * @return the Log file to be used
+ */
+ public Log get() {
+ return LogProvider.logger;
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/MyGuiceServletConfig.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/MyGuiceServletConfig.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/MyGuiceServletConfig.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,19 @@
+package com.tyndalehouse.step.web.server.guice;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.servlet.GuiceServletContextListener;
+
+/**
+ * The servlet configuraiton for Guice, which creates an injector
+ *
+ * @author CJBurrell
+ *
+ */
+public class MyGuiceServletConfig extends GuiceServletContextListener {
+
+ @Override
+ protected Injector getInjector() {
+ return Guice.createInjector(new ServerModule(), new DispatchServletModule());
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/ServerModule.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/ServerModule.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/guice/ServerModule.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,37 @@
+package com.tyndalehouse.step.web.server.guice;
+
+import net.customware.gwt.dispatch.server.guice.ActionHandlerModule;
+
+import org.apache.commons.logging.Log;
+
+import com.google.inject.Singleton;
+import com.tyndalehouse.step.web.server.db.framework.StepQueryRunner;
+import com.tyndalehouse.step.web.server.db.framework.StepQueryRunnerImpl;
+import com.tyndalehouse.step.web.server.handler.GetAvailableBibleVersionsHandler;
+import com.tyndalehouse.step.web.server.handler.GetBibleBooksHandler;
+import com.tyndalehouse.step.web.server.handler.GetCurrentBibleTextHandler;
+import com.tyndalehouse.step.web.server.handler.GetDictionaryDefinitionHandler;
+import com.tyndalehouse.step.web.server.handler.GetEventsForDateRangeHandler;
+import com.tyndalehouse.step.web.server.handler.GetTimelineOriginForScriptureHandler;
+import com.tyndalehouse.step.web.server.handler.GetTimelineUISetupHandler;
+
+/**
+ * Module which binds the handlers and configurations
+ *
+ */
+public class ServerModule extends ActionHandlerModule {
+
+ @Override
+ protected void configureHandlers() {
+ bindHandler(GetAvailableBibleVersionsHandler.class);
+ bind(Log.class).toProvider(LogProvider.class).in(Singleton.class);
+ bindHandler(GetBibleBooksHandler.class);
+ bindHandler(GetCurrentBibleTextHandler.class);
+ bindHandler(GetEventsForDateRangeHandler.class);
+ bindHandler(GetTimelineUISetupHandler.class);
+ bindHandler(GetTimelineOriginForScriptureHandler.class);
+ bindHandler(GetDictionaryDefinitionHandler.class);
+
+ bind(StepQueryRunner.class).to(StepQueryRunnerImpl.class).in(Singleton.class);
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetAvailableBibleVersionsHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetAvailableBibleVersionsHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetAvailableBibleVersionsHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,72 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.crosswire.jsword.book.Book;
+import org.crosswire.jsword.book.BookCategory;
+import org.crosswire.jsword.book.Books;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.shared.command.GetAvailableBibleVersionsCommand;
+import com.tyndalehouse.step.web.shared.result.GetAvailableBibleVersionsResult;
+import com.tyndalehouse.step.web.shared.result.beans.BibleVersion;
+
+/**
+ * Command handler returning all available bible versions
+ *
+ * @author CJBurrell TODO: add logging to this class
+ */
+public class GetAvailableBibleVersionsHandler extends
+ AbstractStepHandler<GetAvailableBibleVersionsCommand, GetAvailableBibleVersionsResult> {
+ /**
+ * Default logger
+ */
+ private final Log logger;
+
+ /**
+ * normal constructor
+ *
+ * @param logger
+ * provided by Gin
+ */
+ @Inject
+ public GetAvailableBibleVersionsHandler(final Log logger) {
+ this.logger = logger;
+ }
+
+ public GetAvailableBibleVersionsResult execute(final GetAvailableBibleVersionsCommand cmd,
+ final ExecutionContext arg1) throws ActionException {
+ // TODO: add handling of different types of book: bibles, commentaries,
+ // versions, etc.
+ @SuppressWarnings("unchecked")
+ final List<Book> books = Books.installed().getBooks();
+ final SortedMap<String, String> map = new TreeMap<String, String>();
+
+ final List<BibleVersion> versions = new ArrayList<BibleVersion>();
+ for (final Book b : books) {
+ if (b.getBookCategory().equals(BookCategory.BIBLE)) {
+ final BibleVersion bibleVersion = new BibleVersion();
+ bibleVersion.setInitials(b.getInitials());
+ bibleVersion.setName(b.getName());
+ bibleVersion.setLanguage(b.getLanguage().getName());
+ versions.add(bibleVersion);
+ }
+ }
+ final GetAvailableBibleVersionsResult result = new GetAvailableBibleVersionsResult();
+ result.setBibleVersions(versions);
+ return result;
+ }
+
+ public void rollback(final GetAvailableBibleVersionsCommand arg0, final GetAvailableBibleVersionsResult arg1,
+ final ExecutionContext arg2) throws ActionException {
+ logger.error("Rolling back GetAvailableBibleVersions");
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetBibleBooksHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetBibleBooksHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetBibleBooksHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,68 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.crosswire.jsword.passage.NoSuchVerseException;
+import org.crosswire.jsword.versification.BibleInfo;
+import org.crosswire.jsword.versification.BibleNames;
+import org.crosswire.jsword.versification.BookName;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.shared.command.GetBibleBooksCommand;
+import com.tyndalehouse.step.web.shared.result.GetBibleBooksCommandResult;
+
+/**
+ * Command handler for retrieving the different names of the books in a
+ * particular version TODO: only currently works for KJV
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetBibleBooksHandler extends AbstractStepHandler<GetBibleBooksCommand, GetBibleBooksCommandResult> {
+ /**
+ * public constructor
+ */
+ @Inject
+ public GetBibleBooksHandler() {
+ }
+
+ public GetBibleBooksCommandResult execute(final GetBibleBooksCommand command, final ExecutionContext arg1)
+ throws ActionException {
+
+ getLogger().debug("GetBibleBooksCommandResult has been called...");
+
+ // TODO: on start up, we should check a whole load of things: jsword
+ // installed, database can be started, database has got data
+
+ // find selection of books and then add stuff to the suggestbox.
+ final ArrayList<String> suggestions = new ArrayList<String>();
+
+ // http://www.crosswire.org/jsword/java2html/org/crosswire/jsword/bridge/BibleScope.java.html
+ // TODO: currently based on KJV versification, when better to base it on
+ // preferred version
+ // of the bible...
+ try {
+ final int booksInBible = BibleInfo.booksInBible();
+ BookName bn;
+ final BibleNames all = new BibleNames(Locale.getDefault());
+ for (int ii = 1; ii <= booksInBible; ii++) {
+ bn = all.getName(ii);
+ suggestions.add(bn.getPreferredName());
+ }
+ } catch (final NoSuchVerseException e) {
+ getLogger().error("Failed to generate list of bible books", e);
+ }
+
+ return new GetBibleBooksCommandResult(suggestions);
+ }
+
+ public void rollback(final GetBibleBooksCommand arg0, final GetBibleBooksCommandResult arg1,
+ final ExecutionContext context) throws ActionException {
+
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetCurrentBibleTextHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetCurrentBibleTextHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetCurrentBibleTextHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,536 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.transform.TransformerException;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.lang.StringUtils;
+import org.crosswire.common.util.Reporter;
+import org.crosswire.common.xml.SAXEventProvider;
+import org.crosswire.common.xml.TransformingSAXEventProvider;
+import org.crosswire.common.xml.XMLUtil;
+import org.crosswire.jsword.book.Book;
+import org.crosswire.jsword.book.BookData;
+import org.crosswire.jsword.book.BookException;
+import org.crosswire.jsword.book.BookMetaData;
+import org.crosswire.jsword.book.Books;
+import org.crosswire.jsword.book.OSISUtil;
+import org.crosswire.jsword.passage.NoSuchKeyException;
+import org.jdom.Attribute;
+import org.jdom.Content;
+import org.jdom.Element;
+import org.jdom.Text;
+import org.jdom.filter.Filter;
+import org.xml.sax.SAXException;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.server.common.JSwordConstants;
+import com.tyndalehouse.step.web.server.handler.util.passage.StrongMorphMap;
+import com.tyndalehouse.step.web.server.jsword.ConfigurableHTMLConverter;
+import com.tyndalehouse.step.web.shared.command.GetCurrentBibleTextCommand;
+import com.tyndalehouse.step.web.shared.result.GetCurrentBibleTextResult;
+import com.tyndalehouse.step.web.shared.scripture.Milestone;
+import com.tyndalehouse.step.web.shared.scripture.Note;
+import com.tyndalehouse.step.web.shared.scripture.OSISConstants;
+import com.tyndalehouse.step.web.shared.scripture.Passage;
+import com.tyndalehouse.step.web.shared.scripture.TextualElement;
+import com.tyndalehouse.step.web.shared.scripture.Title;
+import com.tyndalehouse.step.web.shared.scripture.TransChange;
+import com.tyndalehouse.step.web.shared.scripture.Verse;
+import com.tyndalehouse.step.web.shared.scripture.VerseContent;
+import com.tyndalehouse.step.web.shared.scripture.Word;
+
+/**
+ * Command handler returning a portion of scripture in different formats
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetCurrentBibleTextHandler extends
+ AbstractStepHandler<GetCurrentBibleTextCommand, GetCurrentBibleTextResult> {
+
+ /**
+ * default constructor with the getLogger
+ *
+ */
+ @Inject
+ public GetCurrentBibleTextHandler() {
+
+ }
+
+ public GetCurrentBibleTextResult execute(final GetCurrentBibleTextCommand command, final ExecutionContext arg1)
+ throws ActionException {
+ final String version = command.getVersion();
+ final String reference = command.getReference();
+
+ // check information has been passed in
+ // TODO: ensure error handling is handled properly
+ if (StringUtils.isEmpty(version)) {
+ throw new ActionException("Version was not provided");
+ }
+ if (StringUtils.isEmpty(reference)) {
+ throw new ActionException("Reference was not provided");
+ }
+
+ final GetCurrentBibleTextResult result = new GetCurrentBibleTextResult();
+
+ final BookData data = getBookData(version, reference);
+
+ switch (command.getTypeOfLookup()) {
+ case CLASSIC_INTERLINEAR:
+ addClassicInterlinear(result.getPassage(), reference);
+ break;
+ case LOGICAL:
+ addLogicalLookup(result, data);
+ break;
+ case PLAIN_TEXT:
+ try {
+ result.setPassageText(OSISUtil.getCanonicalText(data.getOsis()));
+ } catch (final BookException e) {
+ throw new ActionException("Unable to get simple canonical text from book", e);
+ }
+ break;
+ case REVERSE_INTERLINEAR:
+ addLogicalLookup(result, data);
+ addReverseInterlinear(result.getPassage(), reference);
+ break;
+ case XSLT:
+ result.setXsltedText(doXslt(data));
+ break;
+ default:
+ // do nothing since nothing was requested
+ break;
+ }
+ return result;
+ }
+
+ public void rollback(final GetCurrentBibleTextCommand arg0, final GetCurrentBibleTextResult arg1,
+ final ExecutionContext arg2) throws ActionException {
+ getLogger().error("Get Current Bible Text rolling back");
+
+ }
+
+ /**
+ * does a classic interlinear and populates the Passage
+ *
+ * @param p
+ * the logical passage to be populated
+ * @param reference
+ * the reference
+ */
+ private void addClassicInterlinear(final Passage p, final String reference) {
+ // TODO: feature
+ // identify the hebrew/greek version of the text, and get book data for
+ // the appropriate version
+ // final VerseRange vrf = VerseRangeFactory.fromString(reference);
+ // TODO updgrade to latest jsword version
+
+ // VerseRange.remainder(vrf, null);
+
+ // getBookData(version, reference);
+ }
+
+ /**
+ * adds a logical lookup to the result objet
+ *
+ * @param result
+ * the result object to populate
+ * @param data
+ * the data to base the lookup upon
+ * @throws ActionException
+ * an exception thrown if the parsing or lookup goes bad
+ */
+ private void addLogicalLookup(final GetCurrentBibleTextResult result, final BookData data) throws ActionException {
+ final Passage p = parseForGwt(data);
+ result.setPassage(p);
+ }
+
+ /**
+ * doing a reverse interlinear
+ *
+ * @param translatedText
+ * the passage as looked up in an non-original version
+ * @param reference
+ * the reference of the text so we can add the original text onto
+ * it
+ * @throws ActionException
+ * action exception thrown during execution of the reverse
+ * interlinear process
+ */
+ private void addReverseInterlinear(final Passage translatedText, final String reference) throws ActionException {
+ // first lookup passage from LXX or TODO user chosen version
+ // TODO: cope with Hebrew
+ String versionToUse;
+ StrongMorphMap strongMorphMap;
+
+ if (isGreek(translatedText)) {
+ versionToUse = JSwordConstants.DEFAULT_GREEK_INTERLINEAR_TEXT;
+ } else {
+ // assume Hebrew
+ versionToUse = JSwordConstants.DEFAULT_HEBREW_INTERLINEAR_TEXT;
+ }
+
+ // TODO: we need to do something different here,
+ // we don't need to parse through the whole lot, and probably JDom
+ // allows us to use filters to get all children of a certain kind,
+ // we want to end up with a keyed map, looking like [strong, morph?] ->
+ // word
+ try {
+ strongMorphMap = getStrongMorphMap(getBookData(versionToUse, reference));
+ } catch (final BookException e) {
+ throw new ActionException("Unable to lookup source text and parse to StrongMorphMap", e);
+ }
+
+ mergePassages(translatedText, strongMorphMap);
+ }
+
+ /**
+ * parsing a milestone into a logical element
+ *
+ * @param verseContent
+ * the Content on which to append the logical element
+ * @param v
+ * the verse
+ */
+ private void doMilestone(final Element verseContent, final Verse v) {
+ final Milestone m = new Milestone();
+ m.setMarker(verseContent.getAttributeValue(OSISConstants.MARKER));
+ m.setType(verseContent.getAttributeValue(OSISUtil.OSIS_ATTR_TYPE));
+ v.addTextualElement(m);
+ }
+
+ /**
+ * parsing a note into a logical element
+ *
+ * @param verseContent
+ * the Content on which to append the logical element
+ * @param v
+ * the verse
+ */
+ private void doNote(final Element verseContent, final Verse v) {
+ final Note n = new Note();
+ n.setType(verseContent.getAttributeValue(OSISUtil.OSIS_ATTR_TYPE));
+ n.setText(verseContent.getText());
+ v.addTextualElement(n);
+ }
+
+ /**
+ * parses a title
+ *
+ * @param titleElement
+ * the xml title element
+ * @param passage
+ * the passage to be parsed into
+ */
+ private void doTitle(final Element titleElement, final Passage passage) {
+ final Title title = new Title();
+ title.setType(titleElement.getAttributeValue(OSISUtil.OSIS_ATTR_TYPE));
+ title.setText(titleElement.getText());
+ passage.addPassageElement(title);
+ }
+
+ /**
+ * parses a TransChange element
+ *
+ * @param verseContent
+ * the trans change element
+ * @param v
+ * the verse to be parsed into
+ */
+ private void doTransChange(final Element verseContent, final Verse v) {
+ final TransChange t = new TransChange();
+ t.setType(verseContent.getAttributeValue(OSISUtil.OSIS_ATTR_TYPE));
+ t.setText(verseContent.getText());
+ v.addTextualElement(t);
+ }
+
+ /**
+ * parses a verse xml element
+ *
+ * @param e
+ * the verse element
+ * @param passage
+ * the passage to be parsed into
+ */
+ private void doVerse(final Element e, final Passage passage) {
+ final List<Content> verseWords = e.getContent();
+ final Verse v = new Verse();
+ v.setOsisID(e.getAttributeValue(OSISUtil.OSIS_ATTR_OSISID));
+ passage.addPassageElement(v);
+
+ for (final Content c : verseWords) {
+ if (c instanceof Element) {
+ final Element verseContent = (Element) c;
+ final String tagName = verseContent.getName();
+ if (tagName.equals(OSISUtil.OSIS_ELEMENT_W)) {
+ doWord(verseContent, v);
+ } else if (tagName.equals(OSISUtil.OSIS_ELEMENT_NOTE)) {
+ doNote(verseContent, v);
+ } else if (tagName.equals(OSISConstants.MILESTONE)) {
+ doMilestone(verseContent, v);
+ } else if (tagName.equals(OSISConstants.TRANS_CHANGE)) {
+ doTransChange(verseContent, v);
+ } else {
+ getLogger().warn(String.format("Unexpected element %s", tagName));
+ }
+ } else if (c instanceof Text) {
+ final Text textElement = (Text) c;
+ final com.tyndalehouse.step.web.shared.scripture.Text t = new com.tyndalehouse.step.web.shared.scripture.Text(
+ textElement.getText());
+ v.addTextualElement(t);
+ } else {
+ // we're in trouble
+ getLogger().warn("Content c is not recognised: " + c.getClass().getCanonicalName());
+ }
+ }
+ }
+
+ /**
+ * processes a word from the bible text passed in as XML
+ *
+ * @param verseContent
+ * verseContent in XML
+ * @param v
+ * the object version of this word
+ */
+ private void doWord(final Element verseContent, final Verse v) {
+ final Word w = new Word();
+
+ final String lemmas = verseContent.getAttributeValue(OSISUtil.ATTRIBUTE_W_LEMMA);
+ final String morphs = verseContent.getAttributeValue(OSISUtil.ATTRIBUTE_W_MORPH);
+
+ // TODO: make a constant
+ if (lemmas != null) {
+ w.addLemmas(lemmas.split(" "));
+ }
+ if (morphs != null) {
+ w.addMorphs(morphs.split(" "));
+ }
+ w.setText(verseContent.getText());
+ v.addTextualElement(w);
+ }
+
+ /**
+ * does an xslt transformation on some OSIS text
+ *
+ * @param data
+ * data of the book to use and the key in the book.
+ * @return the passage xslted version
+ */
+ private String doXslt(final BookData data) {
+ if (data == null) {
+ return "";
+ }
+
+ // Make sure Hebrew displays from Right to Left
+ final BookMetaData bmd = data.getFirstBook().getBookMetaData();
+ if (bmd == null) {
+ return "";
+ }
+
+ try {
+ final SAXEventProvider osissep = data.getSAXEventProvider();
+
+ final TransformingSAXEventProvider htmlsep = (TransformingSAXEventProvider) new ConfigurableHTMLConverter()
+ .convert(osissep);
+ final String text = XMLUtil.writeToString(htmlsep);
+ return text;
+ } catch (final SAXException e) {
+ Reporter.informUser(this, e);
+ } catch (final BookException e) {
+ Reporter.informUser(this, e);
+ } catch (final TransformerException e) {
+ Reporter.informUser(this, e);
+ }
+ return "";
+ }
+
+ /**
+ * returns the book data using the JSword API
+ *
+ * @param version
+ * version to be looked up
+ * @param reference
+ * reference of the passage
+ * @return the JSword BookData object
+ * @throws ActionException
+ * an exception should an problem happen
+ */
+ private BookData getBookData(final String version, final String reference) throws ActionException {
+ try {
+ final Book currentBook = Books.installed().getBook(version);
+ final BookData data = new BookData(currentBook, currentBook.getKey(reference));
+ return data;
+ } catch (final NoSuchKeyException e) {
+ getLogger().error("An error occurred looking up the passage", e);
+ throw new ActionException(e);
+ }
+ }
+
+ /**
+ * given a book data (referencing a biblical reference + a book), retrieves
+ * the morphs and the Strong numbers (lemmas) in the passage to help in the
+ * interlinear processing
+ *
+ * @param bookData
+ * the bookData from JSword specialised for the reference and
+ * bible book
+ * @return a map of strong numbers and morphs
+ * @throws BookException
+ * an exception occuring during parsing of the OSIS XML
+ */
+ @SuppressWarnings("unchecked")
+ private StrongMorphMap getStrongMorphMap(final BookData bookData) throws BookException {
+ final Element osis = bookData.getOsisFragment();
+ final StrongMorphMap strongMorphMap = new StrongMorphMap();
+ final Iterator<Element> it = osis.getDescendants(new Filter() {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 4171956787222841308L;
+
+ public boolean matches(final Object obj) {
+ return obj instanceof Element && ((Element) obj).getName().equals(OSISUtil.OSIS_ELEMENT_W);
+ }
+
+ });
+
+ while (it.hasNext()) {
+ final Element word = it.next();
+ final Attribute lemmaAttribute = word.getAttribute(OSISUtil.ATTRIBUTE_W_LEMMA);
+ final Attribute morphAttribute = word.getAttribute(OSISUtil.ATTRIBUTE_W_MORPH);
+
+ if (lemmaAttribute != null) {
+ if (morphAttribute != null) {
+ strongMorphMap.addWord(lemmaAttribute.getValue(), morphAttribute.getValue(), word.getValue());
+ } else {
+ strongMorphMap.addWord(lemmaAttribute.getValue(), word.getValue());
+ }
+ }
+ }
+
+ return strongMorphMap;
+ }
+
+ /**
+ * Look at the first word with a lemma and return lemma[0] == 'G'
+ *
+ * @param p
+ * passage to be looked up
+ * @return true if the word with the first lemma is in Greek
+ */
+ private boolean isGreek(final Passage p) {
+ for (final VerseContent vc : p.getVerseContent()) {
+ if (vc instanceof Verse) {
+ final Verse v = (Verse) vc;
+ for (final TextualElement te : v.getVerseContent()) {
+ if (te instanceof Word) {
+ final Word w = (Word) te;
+ if (w.getLemma() != null) {
+ return w.getLemma().get(0).charAt(JSwordConstants.STRONG_PATTERN_START.length()) == JSwordConstants.STRONG_GREEK_MARKER;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Iterates through the master passage and incorporates into it, the text
+ * given and mapped in the strongMorphMap
+ *
+ * @param masterPassage
+ * the passage to be enriched
+ * @param strongMorphMap
+ * the map containing the links.
+ */
+ // TODO: tidy up all the different iterator approaches, widely using
+ // instanceof
+ private void mergePassages(final Passage masterPassage, final StrongMorphMap strongMorphMap) {
+ // iterate through the masterPassage, and lookup the strong morph map
+ final List<VerseContent> verseContent = masterPassage.getVerseContent();
+ List<String> lemma, morph;
+ for (final VerseContent vc : verseContent) {
+ if (vc instanceof Verse) {
+ final Verse v = (Verse) vc;
+ for (final TextualElement te : v.getVerseContent()) {
+ if (te instanceof Word) {
+ final Word w = (Word) te;
+
+ // we have several lemmas for each word, and therefore,
+ // we need to loop round them
+ lemma = w.getLemma();
+ morph = w.getMorph();
+
+ final StringBuffer alternativeWording = new StringBuffer(64);
+
+ // we iterate through each lemma, knowing that we may
+ // not have morphs at all (Hebrew text)
+ // we cannot use the morph without the lemma, although
+ // TODO: check what we're supposed to do
+ // when we only have one morphology for several lemmas
+ // always 0 or equal to number of lemmas
+ for (int ii = 0; ii < lemma.size(); ii++) {
+ final String l = lemma.get(ii);
+ final String m = ii < morph.size() ? morph.get(ii) : null;
+ final String text = strongMorphMap.get(l, m);
+ if (text != null) {
+ alternativeWording.append(text);
+ alternativeWording.append(' ');
+ }
+ w.setAlternativeWord(alternativeWording.toString());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * parsing an element
+ *
+ * @param data
+ * the book data to used as a basis for parsing
+ * @return the passage once parsed, et al.
+ * @throws ActionException
+ * an exception to bubble up to the web UI
+ */
+ @SuppressWarnings("unchecked")
+ // TODO: upgrade to latest JSword version for generics
+ private Passage parseForGwt(final BookData data) throws ActionException {
+ Element osisFragment;
+ try {
+ osisFragment = data.getOsisFragment();
+ } catch (final BookException e1) {
+ throw new ActionException("Unable to get OSIS Fragment from selected version");
+ }
+
+ final List<Content> l = osisFragment.getContent();
+ final Passage passage = new Passage();
+
+ // First level can be title or verse
+ for (final Content el : l) {
+ // check whether we've just got text, or a verse or something
+ if (el instanceof Element) {
+ final Element e = (Element) el;
+
+ if (e.getName().equals(OSISUtil.OSIS_ELEMENT_TITLE)) {
+ doTitle(e, passage);
+ } else if (e.getName().equals(OSISUtil.OSIS_ELEMENT_VERSE)) {
+ doVerse(e, passage);
+ }
+ } else {
+ // this shouldn't happen
+ getLogger().warn("Unexpected text while parsing gwt");
+ }
+ }
+
+ return passage;
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetDictionaryDefinitionHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetDictionaryDefinitionHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetDictionaryDefinitionHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,176 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import java.util.List;
+
+import javax.xml.transform.TransformerException;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.lang.StringUtils;
+import org.crosswire.common.util.Reporter;
+import org.crosswire.common.xml.SAXEventProvider;
+import org.crosswire.common.xml.TransformingSAXEventProvider;
+import org.crosswire.common.xml.XMLUtil;
+import org.crosswire.jsword.book.Book;
+import org.crosswire.jsword.book.BookData;
+import org.crosswire.jsword.book.BookException;
+import org.crosswire.jsword.book.Books;
+import org.crosswire.jsword.passage.NoSuchKeyException;
+import org.jdom.Element;
+import org.xml.sax.SAXException;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.server.common.JSwordConstants;
+import com.tyndalehouse.step.web.server.jsword.ConfigurableHTMLConverter;
+import com.tyndalehouse.step.web.shared.command.GetDictionaryDefinitionCommand;
+import com.tyndalehouse.step.web.shared.result.GetDictionaryDefinitionResult;
+
+/**
+ * Looks up the dictionary definition in a JSword module and returns it to the
+ * client
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetDictionaryDefinitionHandler extends
+ AbstractStepHandler<GetDictionaryDefinitionCommand, GetDictionaryDefinitionResult> {
+
+ /**
+ * The dictionary definition handler's constructor
+ */
+ @Inject
+ public GetDictionaryDefinitionHandler() {
+ }
+
+ public GetDictionaryDefinitionResult execute(final GetDictionaryDefinitionCommand command,
+ final ExecutionContext arg1) throws ActionException {
+ final List<String> referenceList = command.getLookupReferencce();
+ final GetDictionaryDefinitionResult result = new GetDictionaryDefinitionResult();
+
+ final StringBuffer definitions = new StringBuffer(300);
+ // for each definition: TODO : probably want to pass back a list of
+ // definitions, and tab them
+ // on the popup!
+ for (final String reference : referenceList) {
+ definitions.append(lookUpDefinition(reference));
+ definitions.append("<hr />");
+
+ }
+ result.setDefinition(definitions.toString());
+ return result;
+ }
+
+ public void rollback(final GetDictionaryDefinitionCommand arg0, final GetDictionaryDefinitionResult arg1,
+ final ExecutionContext arg2) throws ActionException {
+ getLogger().error("Get Dictionary definition Text rolling back");
+
+ }
+
+ /**
+ * does a simple xslt transformation to show the definition on the screen
+ *
+ * @param data
+ * data to be shown
+ * @param osisFragment
+ * osisFragment to transform
+ * @return the xslted definition ready to be displayed on the user's screen
+ */
+ private String doXslt(final BookData data, final Element osisFragment) {
+ if (data == null) {
+ return "";
+ }
+
+ try {
+ final SAXEventProvider osissep = data.getSAXEventProvider();
+ // TODO: do some work on the XSLT definition
+ final TransformingSAXEventProvider htmlsep = (TransformingSAXEventProvider) new ConfigurableHTMLConverter()
+ .convert(osissep);
+ final String text = XMLUtil.writeToString(htmlsep);
+ return text;
+ } catch (final SAXException e) {
+ Reporter.informUser(this, e);
+ } catch (final BookException e) {
+ Reporter.informUser(this, e);
+ } catch (final TransformerException e) {
+ Reporter.informUser(this, e);
+ }
+ return "";
+ }
+
+ /**
+ * dependant on the reference, we return a different module to lookup the
+ * definition. For e.g. we use a Greek dictionary to lookup a reference
+ * starting strong:Gxxxxx
+ *
+ * @param reference
+ * reference to be looked up
+ * @return the module initials to use for the dictionary lookup
+ * @throws ActionException
+ * an exception to be thrown if the reference is not recognised
+ */
+ private String getInitialsFromReference(final String reference) throws ActionException {
+ if (reference.toLowerCase().startsWith(JSwordConstants.STRONG_PATTERN_START)) {
+ final int charPosition = JSwordConstants.STRONG_PATTERN_START.length();
+ if (reference.charAt(charPosition) == JSwordConstants.STRONG_HEBREW_MARKER) {
+ return JSwordConstants.STRONG_HEBREW_DICTIONARY_INITIALS;
+ } else if (reference.charAt(charPosition) == JSwordConstants.STRONG_GREEK_MARKER) {
+ return JSwordConstants.STRONG_GREEK_DICTIONARY_INITIALS;
+ }
+ // continuing will throw exception
+ }
+ throw new ActionException(String.format("Dictionary reference not recognised: %s", reference));
+ }
+
+ /**
+ * returns the actual reference, removing the strong pattern + first
+ * initial. For e.g. removes strong:H from "strong:H00002"
+ *
+ * @param reference
+ * reference to parse
+ * @return the key in the dictionary to be used for lookup purposes
+ * @throws ActionException
+ * the action exception
+ */
+ private String getLookupKeyFromReference(final String reference) throws ActionException {
+ if (reference.toLowerCase().startsWith(JSwordConstants.STRONG_PATTERN_START)) {
+ // remove strong:H or strong:G
+ return reference.substring(JSwordConstants.STRONG_PATTERN_START.length() + 1);
+ }
+ throw new ActionException(String.format("Lookup key not recognised: %s", reference));
+ }
+
+ /**
+ * Looks up a definition given a reference in the default JSword module
+ *
+ * @param reference
+ * reference, for e.g. a Strong number
+ * @return the definition
+ * @throws ActionException
+ * an exception occurring if the reference is invalid
+ */
+ private String lookUpDefinition(final String reference) throws ActionException {
+ if (StringUtils.isEmpty(reference)) {
+ throw new ActionException("Reference was not provided");
+ }
+ getLogger().error("definition lookup command");
+ final String initials = getInitialsFromReference(reference);
+ final String lookupKey = getLookupKeyFromReference(reference);
+
+ try {
+ // TODO: ensure a lookup key exists!
+ // TODO: make a common adapter api to access JSword
+ final Book currentBook = Books.installed().getBook(initials);
+ final BookData data = new BookData(currentBook, currentBook.getKey(lookupKey));
+ final String xsltedDefinition = doXslt(data, data.getOsisFragment());
+ return xsltedDefinition;
+ } catch (final NoSuchKeyException e) {
+ getLogger().error("An error occurred looking up the passage", e);
+ throw new ActionException(e);
+ } catch (final BookException e) {
+ getLogger().error("A book exception has occurred whilte looking up the passage", e);
+ throw new ActionException(e);
+ }
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetEventsForDateRangeHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetEventsForDateRangeHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetEventsForDateRangeHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,101 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.server.db.framework.StepQueryRunner;
+import com.tyndalehouse.step.web.server.db.framework.UnableToRunQueryException;
+import com.tyndalehouse.step.web.server.db.timeline.TimeBandVisibleDateProcessor;
+import com.tyndalehouse.step.web.shared.command.GetEventsForDateRangeCommand;
+import com.tyndalehouse.step.web.shared.common.timeline.TimeBandVisibleDate;
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineEventBean;
+import com.tyndalehouse.step.web.shared.result.GetEventsForDateRangeResult;
+
+/**
+ * Command that gets relevant events on a date range. Currently this executes
+ * multiple queries against the database
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetEventsForDateRangeHandler extends
+ AbstractStepHandler<GetEventsForDateRangeCommand, GetEventsForDateRangeResult> {
+
+ /**
+ * The step query runner to run queries against the database
+ */
+ private final StepQueryRunner queryRunner;
+
+ /**
+ * public constructor for this handler
+ *
+ * @param queryRunner
+ * the query runner object to use for executing the query
+ */
+ @Inject
+ public GetEventsForDateRangeHandler(final StepQueryRunner queryRunner) {
+ this.queryRunner = queryRunner;
+ }
+
+ // TODO: this needs to change to take into account the three different types
+ // of date precision but for now,
+ // let's get something working
+ public GetEventsForDateRangeResult execute(final GetEventsForDateRangeCommand event, final ExecutionContext arg1)
+ throws ActionException {
+ final GetEventsForDateRangeResult result = new GetEventsForDateRangeResult();
+ final List<TimeBandVisibleDate> timebands = event.getVisbleDates();
+ try {
+ for (final TimeBandVisibleDate tvd : timebands) {
+ List<TimelineEventBean> events;
+ events = queryRunner.run(new TimeBandVisibleDateProcessor(tvd.getMinDate(), tvd.getMaxDate(), tvd
+ .getTimebandId()));
+ result.getEvents().addAll(events);
+ }
+ } catch (final UnableToRunQueryException e) {
+ getLogger().error("An error occured while trying to retrieve new events from the datbase", e);
+ throw new ActionException(e);
+ }
+
+ logEventsRetrieved(result.getEvents());
+ return result;
+ }
+
+ public void rollback(final GetEventsForDateRangeCommand arg0, final GetEventsForDateRangeResult arg1,
+ final ExecutionContext arg2) throws ActionException {
+
+ }
+
+ /**
+ * Logs which events have been retrieved in trace mode
+ *
+ * @param events
+ * events to be traced
+ */
+ private void logEventsRetrieved(final List<TimelineEventBean> events) {
+ final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy G");
+
+ if (getLogger().isTraceEnabled()) {
+ for (final TimelineEventBean teb : events) {
+ if (teb.getFromDate() != null && teb.getToDate() != null) {
+ getLogger().trace(
+ String.format("returning: %s %s-%s (tb_id: %d)", teb.getName(), sdf.format(new Date(teb
+ .getFromDate())), sdf.format(new Date(teb.getToDate())), teb.getTimelineId()));
+
+ } else if (teb.getFromDate() != null) {
+ getLogger().trace(
+ String.format("returning: %s %s (tb_id: %d)", teb.getName(), sdf.format(new Date(teb
+ .getFromDate())), teb.getTimelineId()));
+ } else {
+ getLogger().trace(String.format("returning: %s (tb_id: %d)", teb.getName(), teb.getTimelineId()));
+ }
+ }
+ }
+ getLogger().trace(String.format("Returning %d events to the client", events.size()));
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetLocationsHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetLocationsHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetLocationsHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,50 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.server.db.framework.StepQueryRunner;
+import com.tyndalehouse.step.web.shared.command.GetLocationsCommand;
+import com.tyndalehouse.step.web.shared.result.GetLocationsResult;
+
+/**
+ * The GetLocations command gets geographical locations from the server
+ * datasources and sends them back to the client
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetLocationsHandler extends AbstractStepHandler<GetLocationsCommand, GetLocationsResult> {
+
+ /**
+ * Default constructor
+ *
+ * @param queryRunner
+ * a query runner
+ */
+ @Inject
+ public GetLocationsHandler(final StepQueryRunner queryRunner) {
+ // this.queryRunner = queryRunner;
+ }
+
+ public GetLocationsResult execute(final GetLocationsCommand arg0, final ExecutionContext arg1)
+ throws ActionException {
+ // try {
+ // final List<GeoLoc> timelines = queryRunner.run(new
+ // TimelineSetupDataProcessor());
+ final GetLocationsResult r = new GetLocationsResult();
+ return r;
+ // } catch (final UnableToRunQueryException e) {
+ // getLogger().error("An error occured while loading the config for the query",
+ // e);
+ // throw new ActionException(e);
+ // }
+ }
+
+ public void rollback(final GetLocationsCommand arg0, final GetLocationsResult arg1, final ExecutionContext arg2)
+ throws ActionException {
+ getLogger().error("Get Locations Handler rolling back");
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineOriginForScriptureHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineOriginForScriptureHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineOriginForScriptureHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,118 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import java.util.List;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.crosswire.jsword.passage.Key;
+import org.crosswire.jsword.passage.KeyFactory;
+import org.crosswire.jsword.passage.NoSuchKeyException;
+import org.crosswire.jsword.passage.PassageKeyFactory;
+import org.crosswire.jsword.passage.RestrictionType;
+import org.crosswire.jsword.passage.RocketPassage;
+import org.crosswire.jsword.passage.VerseRange;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.server.db.framework.ResultSetProcessor;
+import com.tyndalehouse.step.web.server.db.framework.StepQueryRunner;
+import com.tyndalehouse.step.web.server.db.framework.UnableToRunQueryException;
+import com.tyndalehouse.step.web.server.db.timeline.TimelineOriginDbBean;
+import com.tyndalehouse.step.web.server.db.timeline.TimelineOriginProcessor;
+import com.tyndalehouse.step.web.shared.command.GetTimelineOriginForScriptureCommand;
+import com.tyndalehouse.step.web.shared.result.GetTimelineOriginForScriptureResult;
+
+/**
+ * returns the timeline origin, i.e the best (closest in time) event for a given
+ * verse range.
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetTimelineOriginForScriptureHandler extends
+ AbstractStepHandler<GetTimelineOriginForScriptureCommand, GetTimelineOriginForScriptureResult> {
+ /**
+ * The step query runner to run queries against the database
+ */
+ private final StepQueryRunner queryRunner;
+
+ /**
+ * constructor for this handler
+ *
+ * @param queryRunner
+ * the query runner framework
+ */
+ @Inject
+ public GetTimelineOriginForScriptureHandler(final StepQueryRunner queryRunner) {
+ this.queryRunner = queryRunner;
+ }
+
+ // TODO: build a proper sql statement to query all time bands in one go
+ // TODO: this needs to change to take into account the three different types
+ // of date precision but for now,
+ // let's get something working
+ public GetTimelineOriginForScriptureResult execute(final GetTimelineOriginForScriptureCommand event,
+ final ExecutionContext arg1) throws ActionException {
+ try {
+ // TODO: this is bad - look at JSword to work out how to properly
+ // get the verserange out
+ final RocketPassage passage = (RocketPassage) resolveScriptureToVerseNumbers(event.getScriptureReference());
+
+ if (passage.isEmpty()) {
+ getLogger().warn("No passage was requested");
+ } else {
+
+ // TODO: we're doing only the first range - ignoring others...
+ // What would we do with several ranges? Interesting question -
+ // perhaps we could use as min/max
+ final VerseRange range = passage.getRangeAt(0, RestrictionType.NONE);
+ final int startVerseNo = range.getStart().getOrdinal();
+ final int endVerseNo = range.getEnd().getOrdinal();
+
+ final ResultSetProcessor<TimelineOriginDbBean> originProcessor = new TimelineOriginProcessor(
+ startVerseNo, endVerseNo);
+
+ // TODO: should be able to ensure this is implied, rather having
+ // to cast directly
+ final List<TimelineOriginDbBean> originList = queryRunner.run(originProcessor);
+
+ if (originList.size() != 0) {
+ final TimelineOriginDbBean origin = originList.get(0);
+ return new GetTimelineOriginForScriptureResult(origin.getOrigin(), origin.getUnit(), origin
+ .getTimebandId());
+ } // else {
+ // // TODO: work out the nearest passage and redo this...
+ // }
+ }
+ } catch (final NoSuchKeyException e) {
+ getLogger().warn("Could not resolve verse number", e);
+ // TODO: return a proper exception and show error message on the UI
+ return new GetTimelineOriginForScriptureResult(true);
+ } catch (final UnableToRunQueryException e) {
+ getLogger().error("An error occured while loading the config for the query", e);
+ throw new ActionException(e);
+ }
+ return new GetTimelineOriginForScriptureResult(true);
+ }
+
+ public void rollback(final GetTimelineOriginForScriptureCommand arg0,
+ final GetTimelineOriginForScriptureResult arg1, final ExecutionContext arg2) throws ActionException {
+
+ }
+
+ /**
+ * resolves a string to a range of verses
+ *
+ * @return the OSIS key to use to look up a particular scripture reference
+ * in a JSword module
+ * @throws NoSuchKeyException
+ * thrown if the passed in reference cannot be parsed //TODO:
+ * make into seperate util classes
+ */
+ private Key resolveScriptureToVerseNumbers(final String scriptureReference) throws NoSuchKeyException {
+ final KeyFactory keyFactory = PassageKeyFactory.instance();
+ return keyFactory.getKey(scriptureReference);
+
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineUISetupHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineUISetupHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineUISetupHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,65 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import java.util.List;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.server.db.framework.StepQueryRunner;
+import com.tyndalehouse.step.web.server.db.framework.UnableToRunQueryException;
+import com.tyndalehouse.step.web.server.db.timeline.TimelineSetupDataProcessor;
+import com.tyndalehouse.step.web.shared.command.GetTimelineUISetupCommand;
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineBean;
+import com.tyndalehouse.step.web.shared.result.GetTimelineUISetupResult;
+
+/**
+ * the timeline UI setup handler, which returns the initial set of data for the
+ * timeline module including the different bands, their recommended scales, etc.
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetTimelineUISetupHandler extends AbstractStepHandler<GetTimelineUISetupCommand, GetTimelineUISetupResult> {
+ /**
+ * The step query runner to run queries against the database
+ */
+ private final StepQueryRunner queryRunner;
+
+ /**
+ * Default constructor
+ *
+ * @param queryRunner
+ * a query runner
+ */
+ @Inject
+ public GetTimelineUISetupHandler(final StepQueryRunner queryRunner) {
+ this.queryRunner = queryRunner;
+ }
+
+ // TODO: this can be cached quite succesfully on the server
+
+ public GetTimelineUISetupResult execute(final GetTimelineUISetupCommand cmd, final ExecutionContext arg1)
+ throws ActionException {
+ try {
+ final List<TimelineBean> timelines = queryRunner.run(new TimelineSetupDataProcessor());
+ final GetTimelineUISetupResult r = new GetTimelineUISetupResult();
+ r.setTimelines(timelines);
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(String.format("Returning %d timebands to the client.", timelines.size()));
+ }
+ return r;
+ } catch (final UnableToRunQueryException e) {
+ getLogger().error("An error occured while loading the config for the query", e);
+ throw new ActionException(e);
+ }
+ }
+
+ public void rollback(final GetTimelineUISetupCommand arg0, final GetTimelineUISetupResult arg1,
+ final ExecutionContext arg2) throws ActionException {
+ getLogger().error("Get Timeline UI Setup Handler rolling back");
+
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/InstallJswordModuleHandler.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/InstallJswordModuleHandler.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/InstallJswordModuleHandler.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,147 @@
+package com.tyndalehouse.step.web.server.handler;
+
+import java.util.Set;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.crosswire.common.progress.JobManager;
+import org.crosswire.common.progress.Progress;
+import org.crosswire.jsword.book.Book;
+import org.crosswire.jsword.book.BookException;
+import org.crosswire.jsword.book.Books;
+import org.crosswire.jsword.book.install.sword.HttpSwordInstaller;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.server.common.AbstractStepHandler;
+import com.tyndalehouse.step.web.shared.command.InstallJswordModuleCommand;
+import com.tyndalehouse.step.web.shared.result.InstallJswordModuleResult;
+
+/**
+ * Handler that installs a JSword module (bible, etc.) on to the server (perhaps
+ * a localhost server)
+ *
+ * @author CJBurrell
+ *
+ */
+public class InstallJswordModuleHandler extends
+ AbstractStepHandler<InstallJswordModuleCommand, InstallJswordModuleResult> {
+
+ // TODO: move the lookup to properties file
+ /**
+ * proxy to use to access the internet from step
+ */
+ private static final String PROXY_HOST = "step.proxy.host";
+
+ /**
+ * proxy port to use for accessing the internet form step
+ */
+ private static final String PROXY_PORT = "step.proxy.port";
+
+ /**
+ * the time to wait for installer to kick in, so that we can then wait for
+ * it
+ */
+ private static final int WAIT_TIME_FOR_INSTALLER = 2000;
+
+ /**
+ * constructor to create this handler, usually via Guice
+ */
+ @Inject
+ public InstallJswordModuleHandler() {
+ }
+
+ public InstallJswordModuleResult execute(final InstallJswordModuleCommand cmd, final ExecutionContext context)
+ throws ActionException {
+
+ final String initials = cmd.getInitials();
+ if (initials == null) {
+ throw new ActionException("Module initials provided was null");
+ }
+
+ try {
+ final HttpSwordInstaller newCustomInstaller = getNewCustomInstaller();
+
+ // remove if already installed
+ final Book installed = Books.installed().getBook(initials);
+ if (installed != null) {
+ // remove first
+ // Books.installed().removeBook(installed);
+ installed.getDriver().delete(installed);
+ getLogger()
+ .debug(
+ String.format("%s (%s) is already installed, so removing first", initials, installed
+ .getName()));
+ }
+
+ // now kick off install
+ final Book bookToBeInstalled = newCustomInstaller.getBook(initials);
+ newCustomInstaller.install(bookToBeInstalled);
+
+ getLogger().debug(String.format("Installing %s", initials));
+
+ // finally wait for install to finish
+ // hack to wait for the thread to register with the manager
+ // TODO: check with jsword community
+ // TODO: use a timer instead...
+ Thread.sleep(InstallJswordModuleHandler.WAIT_TIME_FOR_INSTALLER);
+
+ @SuppressWarnings("unchecked")
+ final Set<Progress> jswordJobs = JobManager.getJobs();
+ for (final Progress p : jswordJobs) {
+ if (p.getJobName().equals("Installing book: " + bookToBeInstalled.getName())) {
+ // TODO: expose join on the thread and wait for it to exit
+ // this will depend on the JSword community
+ while (!p.isFinished()) {
+ // sleep
+ Thread.sleep(InstallJswordModuleHandler.WAIT_TIME_FOR_INSTALLER);
+ }
+ }
+ }
+ } catch (final BookException e) {
+ getLogger().error("An error occured during the installation of the book", e);
+ } catch (final InterruptedException e) {
+ getLogger().error("An error occurred during the downloading of the book", e);
+ }
+
+ // wait for module to be completed
+
+ return new InstallJswordModuleResult(true);
+ }
+
+ public void rollback(final InstallJswordModuleCommand arg0, final InstallJswordModuleResult arg1,
+ final ExecutionContext arg2) throws ActionException {
+ getLogger().error("Rolling back InstallJswordModule");
+ }
+
+ /**
+ * TODO: needs redoing to ensure we take all the installers provided by
+ * JSword
+ *
+ * @return a custom installer configured with the crosswire proxy
+ */
+ private HttpSwordInstaller getNewCustomInstaller() {
+ getLogger().info("Creating new installer for JSword");
+ final HttpSwordInstaller resourceInstaller = new HttpSwordInstaller();
+
+ getLogger().info("Currently hardcoded installer host to:" + "www.crosswire.org");
+ getLogger().info("Currently hardcoded property names for step");
+ final String host = "www.crosswire.org";
+ final String proxyHost = System.getProperty(InstallJswordModuleHandler.PROXY_HOST);
+ final String proxyPort = System.getProperty(InstallJswordModuleHandler.PROXY_PORT);
+ getLogger().info(String.format("Setting to (%1$s via %2$s:%3$s)", "www.crosswire.org", proxyHost, proxyPort));
+
+ resourceInstaller.setHost(host);
+ if (proxyHost != null) {
+ resourceInstaller.setProxyHost(proxyHost);
+ }
+ if (proxyPort != null) {
+ resourceInstaller.setProxyPort(Integer.parseInt(proxyPort));
+ }
+
+ getLogger().info("Setting package and catalog directories");
+ resourceInstaller.setPackageDirectory("/ftpmirror/pub/sword/packages/rawzip");
+ resourceInstaller.setCatalogDirectory("/ftpmirror/pub/sword/raw");
+ return resourceInstaller;
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/StrongMorphMap.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/StrongMorphMap.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/StrongMorphMap.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,126 @@
+package com.tyndalehouse.step.web.server.handler.util.passage;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * This map will store the mapping for strong,morph to the word However
+ * sometimes the morphology of the word is not present in the passage and since
+ * we still want to be able to render some sort of interlinear, it would be best
+ * to match just on the word as a result each entity will have the the three
+ * values associated to it text (what the word is) the strong number the
+ * morphology (optional) The map is keyed my strong number.
+ *
+ * In order to ensure rapid lookup, we will use the following way of mapping
+ * elements Strong numbers will map either directly to the word when no morph is
+ * available, or through a morph to the word
+ *
+ * TODO: It is assumed that given a strong and morph the text is unique TODO:
+ * change this, since there are multiple morphs per lemma and word strong
+ * ---------> morph --------> word (1) or strong ------------------------> word
+ * (2) A mapping (2) will not be stored if (1) is available, and therefore
+ * lookups lookup the morph first as this is prefered.
+ *
+ * @author CJBurrell
+ *
+ */
+public class StrongMorphMap {
+ // lemmas morphs word
+ /**
+ * this map maps strong numbers to morphs. it is the first level of
+ * indirection to the map of morphs which maps to a word
+ */
+ private final Map<String, Map<String, String>> strongToMorph;
+
+ /**
+ * this map maps the strong number ot the word directly
+ */
+ private final Map<String, String> strongToWord;
+
+ /**
+ * Default constructor that initialises the two maps
+ */
+ public StrongMorphMap() {
+ strongToMorph = new HashMap<String, Map<String, String>>();
+ strongToWord = new HashMap<String, String>();
+ }
+
+ /**
+ * only to be used if no morph is available
+ *
+ * @param strong
+ * the strong number or lemma
+ * @param word
+ * the word to be stored
+ */
+ public final void addWord(final String strong, final String word) {
+ strongToWord.put(strong, word);
+ }
+
+ /**
+ * adds a word to the map
+ *
+ * @param strong
+ * the lemma/strong number
+ * @param morph
+ * the morph / indicating morphology
+ * @param word
+ * the word
+ */
+ public final void addWord(final String strong, final String morph, final String word) {
+ if (morph == null) {
+ addWord(strong, word);
+ return;
+ }
+
+ Map<String, String> morphsToWords = strongToMorph.get(strong);
+ if (morphsToWords == null) {
+ morphsToWords = new HashMap<String, String>();
+ strongToMorph.put(strong, morphsToWords);
+ }
+
+ // guaranteed non-null map
+ morphsToWords.put(morph, word);
+ }
+
+ /**
+ * Looks up the (lemma, morph) key in the map. If morph is null, lookup is
+ * done solely on strong number, and takes the first of the morphs
+ *
+ * @param lemma
+ * lemma associated to a a word
+ * @param morph
+ * morph, can be passed in null, refering to the grammar of a
+ * word in a language
+ * @return the word associated in the map to the (lemma, morph) combination
+ */
+ // TODO: check for nulls on lemma
+ public final String get(final String lemma, final String morph) {
+ final Map<String, String> morphToWord = strongToMorph.get(lemma);
+
+ if (morphToWord != null) {
+ if (morph != null) {
+ // use the chain from morphs to word
+ final String word = morphToWord.get(morph);
+ if (word != null) {
+ return word;
+ } else {
+ // well we didn't find our morph, so the best option is to
+ // return another morph for the same strong number
+ final Collection<String> words = morphToWord.values();
+ final Iterator<String> wordsIterator = words.iterator();
+ if (wordsIterator.hasNext()) {
+ return wordsIterator.next();
+ }
+ }
+ }
+ }
+
+ // if we get here, there is nothing valuable in the map going through
+ // the morphs
+ // therefore, let's just return something from the other map
+ return strongToWord.get(lemma);
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/ConfigurableHTMLConverter.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/ConfigurableHTMLConverter.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/ConfigurableHTMLConverter.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,172 @@
+/**
+ * Distribution License:
+ * BibleDesktop is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 2 as published by
+ * the Free Software Foundation. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * The License is available on the internet at:
+ * http://www.gnu.org/copyleft/gpl.html
+ * or by writing to:
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2005
+ * The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: ConfigurableSwingConverter.java 1583 2007-07-30 17:04:04Z dmsmith $
+ */
+package com.tyndalehouse.step.web.server.jsword;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.MissingResourceException;
+
+import javax.xml.transform.TransformerException;
+
+import org.crosswire.common.util.FileUtil;
+import org.crosswire.common.util.NetUtil;
+import org.crosswire.common.util.ResourceUtil;
+import org.crosswire.common.util.URIFilter;
+import org.crosswire.common.xml.Converter;
+import org.crosswire.common.xml.SAXEventProvider;
+import org.crosswire.common.xml.TransformingSAXEventProvider;
+
+/**
+ * Turn XML from a Bible into HTML according to a Display style.
+ *
+ * @see gnu.gpl.License for license details. The copyright to this program is
+ * held by it's authors.
+ * @author Joe Walker [joe at eireneh dot com]
+ */
+public class ConfigurableHTMLConverter implements Converter {
+ /**
+ *
+ */
+ static final class XSLTFilter implements URIFilter {
+
+ public boolean accept(final String name) {
+ return name.endsWith(FileUtil.EXTENSION_XSLT);
+ }
+ }
+
+ /**
+ * The font to be used in OSIS->HTML generation
+ */
+ private static String font = "Serif-PLAIN-14"; //$NON-NLS-1$
+
+ /**
+ * The stylesheet we are transforming using
+ */
+ private static String style = "simple.xsl"; //$NON-NLS-1$
+
+ /**
+ * ripped off JSWord: TODO: needs to be down properly
+ */
+ public ConfigurableHTMLConverter() {
+
+ }
+
+ //
+ // /**
+ // * Accessor for the stylesheet we are transforming using
+ // */
+ // public static Font toFont()
+ // {
+ // return null;
+ // //return GuiConvert.string2Font(font);
+ // }
+
+ // /**
+ // * Accessor for the stylesheet we are transforming using
+ // */
+ // public static void setFont(String font)
+ // {
+ // ConfigurableHTMLConverter.font = font;
+ // XSLTProperty.FONT.setState(font);
+ // }
+
+ /**
+ * Accessor for the stylesheet we are transforming using
+ *
+ * @return the font
+ */
+ public static String getFont() {
+ return ConfigurableHTMLConverter.font;
+ }
+
+ /**
+ * Accessor for the stylesheet we are transforming using
+ *
+ * @return the resource name
+ */
+ public static String getResourceName() {
+ return ConfigurableHTMLConverter.style;
+ }
+
+ /**
+ * Accessor for the stylesheet we are transforming using
+ *
+ * @param style
+ * returns the resource name given a style
+ */
+ public static void setResourceName(final String style) {
+ ConfigurableHTMLConverter.style = style;
+ }
+
+ /**
+ *
+ *
+ * @see org.crosswire.common.xml.Converter#convert(org.crosswire.common.xml.
+ * SAXEventProvider)
+ * @param xmlsep
+ * the sax event provider
+ * @return the converted SAX event provider
+ * @throws TransformerException
+ * thrown if something bad happens during the transformation of
+ * the xml
+ */
+ public SAXEventProvider convert(final SAXEventProvider xmlsep) throws TransformerException {
+ try {
+ final String path = "xsl/cswing/" + ConfigurableHTMLConverter.style; //$NON-NLS-1$
+ final URL xslurl = ResourceUtil.getResource(path);
+
+ final TransformingSAXEventProvider tsep = new TransformingSAXEventProvider(NetUtil.toURI(xslurl), xmlsep);
+ // We used to do:
+ // tsep.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ // however for various reasons, now we don't but nothing seems to be
+ // broken ...
+ return tsep;
+ } catch (final MissingResourceException ex) {
+ throw new TransformerException(ex);
+ }
+ }
+
+ /**
+ * Get an array of the available style names for a given subject. Different
+ * subjects are available for different contexts. For example - for
+ * insertion into a web page we might want to use a set that had complex
+ * HTML, or IE/NS specific HTML, where as a JFC HTMLDocument needs simpler
+ * HTML - and special tags like the starting <HTML> tags.
+ * <p>
+ * If the protocol of the URL of the current directory is not file then we
+ * can't use File.list to get the contents of the directory. This will
+ * happen if this is being run as an applet. When we start doing that then
+ * we will need to think up something smarter here. Until then we just
+ * return a zero length array.
+ *
+ * @return An array of available style names
+ */
+ public String[] getStyles() {
+ try {
+ final String search = "xsl/cswing/" + NetUtil.INDEX_FILE; //$NON-NLS-1$
+ final URL index = ResourceUtil.getResource(search);
+ return NetUtil.listByIndexFile(NetUtil.toURI(index), new XSLTFilter());
+ } catch (final IOException ex) {
+ return new String[0];
+ }
+ }
+}
Added: trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/XSLTProperty.java
===================================================================
--- trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/XSLTProperty.java (rev 0)
+++ trunk/step-web-server/src/main/java/com/tyndalehouse/step/web/server/jsword/XSLTProperty.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,335 @@
+/**
+ * Distribution License:
+ * BibleDesktop is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 2 as published by
+ * the Free Software Foundation. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * The License is available on the internet at:
+ * http://www.gnu.org/copyleft/gpl.html
+ * or by writing to:
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2005
+ * The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: XSLTProperty.java 1583 2007-07-30 17:04:04Z dmsmith $
+ */
+package com.tyndalehouse.step.web.server.jsword;
+
+import java.io.File;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+
+import org.crosswire.common.util.NetUtil;
+import org.crosswire.common.util.Reporter;
+import org.crosswire.common.xml.TransformingSAXEventProvider;
+
+/* TODO: redo this class properly to behave as per where it cam from!
+ *
+ */
+
+/**
+ * Defines properties that control the behavior of translating OSIS to HTML.
+ *
+ * @see gnu.gpl.License for license details. The copyright to this program is
+ * held by it's authors.
+ * @author DM Smith [ dmsmith555 at yahoo dot com]
+ */
+ at SuppressWarnings(value = {})
+public final class XSLTProperty implements Serializable {
+ /**
+ * What is the base of the current document. Note this needs to be set each
+ * time the document is shown.
+ */
+ public static final XSLTProperty BASE_URL = new XSLTProperty("baseURL", "", true); //$NON-NLS-1$ //$NON-NLS-2$
+
+ /**
+ * Show book, chapter and verse numbers.
+ */
+ public static final XSLTProperty BCV = new XSLTProperty("BCVNum", false); //$NON-NLS-1$
+
+ /**
+ * What is the base of the current document.
+ */
+ public static final XSLTProperty CSS = new XSLTProperty("css", "", true); //$NON-NLS-1$ //$NON-NLS-2$
+
+ /**
+ * Show chapter and verse numbers.
+ */
+ public static final XSLTProperty CV = new XSLTProperty("CVNum", false); //$NON-NLS-1$
+
+ /**
+ * What is the base of the current document. Note this needs to be set each
+ * time the document is shown.
+ */
+ public static final XSLTProperty DIRECTION = new XSLTProperty("direction", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
+ /**
+ * What is the base of the current document. Note this needs to be set each
+ * time the font changes.
+ */
+ public static final XSLTProperty FONT = new XSLTProperty("font", "Serif-PLAIN-14"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ /**
+ * Should headings be shown
+ */
+ public static final XSLTProperty HEADINGS = new XSLTProperty("Headings", true); //$NON-NLS-1$
+
+ /**
+ * Determines whether Word Morphology (e.g. Robinson) should show
+ */
+ public static final XSLTProperty MORPH = new XSLTProperty("Morph", false); //$NON-NLS-1$
+
+ /**
+ * Show no verse numbers
+ */
+ public static final XSLTProperty NO_VERSE_NUMBERS = new XSLTProperty("NoVNum", false); //$NON-NLS-1$
+
+ /**
+ * Should notes be shown
+ */
+ public static final XSLTProperty NOTES = new XSLTProperty("Notes", true); //$NON-NLS-1$
+
+ /**
+ * Determines whether verses should start on a new line.
+ */
+ public static final XSLTProperty START_VERSE_ON_NEWLINE = new XSLTProperty("VLine", false); //$NON-NLS-1$
+
+ /**
+ * Determines whether Strong's Numbers should show
+ */
+ public static final XSLTProperty STRONGS_NUMBERS = new XSLTProperty("Strongs", false); //$NON-NLS-1$
+
+ /**
+ * Show verse numbers as a superscript.
+ */
+ public static final XSLTProperty TINY_VERSE_NUMBERS = new XSLTProperty("TinyVNum", true); //$NON-NLS-1$
+
+ /**
+ * Show verse numbers
+ */
+ public static final XSLTProperty VERSE_NUMBERS = new XSLTProperty("VNum", true); //$NON-NLS-1$
+
+ /**
+ * Should cross references be shown
+ */
+ public static final XSLTProperty XREF = new XSLTProperty("XRef", true); //$NON-NLS-1$
+
+ /**
+ * Support for serialization
+ *
+ */
+ private static int nextObj;
+
+ /**
+ * Serialization ID
+ */
+ private static final long serialVersionUID = 3257567325749326905L;
+
+ /**
+ * list of xslt properties
+ */
+ private static final XSLTProperty[] VALUES = { XSLTProperty.STRONGS_NUMBERS, XSLTProperty.MORPH,
+ XSLTProperty.START_VERSE_ON_NEWLINE, XSLTProperty.VERSE_NUMBERS, XSLTProperty.CV, XSLTProperty.BCV,
+ XSLTProperty.NO_VERSE_NUMBERS, XSLTProperty.TINY_VERSE_NUMBERS, XSLTProperty.HEADINGS, XSLTProperty.NOTES,
+ XSLTProperty.XREF, XSLTProperty.BASE_URL, XSLTProperty.DIRECTION, XSLTProperty.FONT, XSLTProperty.CSS, };
+
+ /**
+ * Whether the string state should be converted to an URL when setting the
+ * property.
+ */
+ private final boolean asURL;
+
+ /**
+ * The default state of the XSLTProperty
+ */
+ private final String defaultState;
+
+ /**
+ * The name of the XSLTProperty
+ */
+ private final String name;
+
+ /**
+ * TODO: don't know what this does, this class is a copy from JSword which
+ * needs revamping
+ */
+ private final int obj = XSLTProperty.nextObj++;
+
+ /**
+ * The current state of the XSLTProperty
+ */
+ private String state;
+
+ /**
+ * @param name
+ * The name of this property
+ * @param defaultState
+ * The initial state of the property.
+ */
+ private XSLTProperty(final String name, final boolean defaultState) {
+ this(name, Boolean.toString(defaultState));
+ }
+
+ /**
+ * @param name
+ * The name of this property
+ * @param defaultState
+ * The initial state of the property.
+ */
+ private XSLTProperty(final String name, final String defaultState) {
+ this(name, defaultState, false);
+ }
+
+ /**
+ * @param name
+ * The name of this property
+ * @param defaultState
+ * The initial state of the property.
+ * @param asURL
+ * whether it is a uRl?
+ */
+ private XSLTProperty(final String name, final String defaultState, final boolean asURL) {
+ this.name = name;
+ this.defaultState = defaultState;
+ this.state = defaultState;
+ this.asURL = asURL;
+ }
+
+ /**
+ * Lookup method to convert from an integer
+ *
+ * @param i
+ * gets a particular xslt property
+ * @return the XSLT property matching the index
+ */
+ public static XSLTProperty fromInteger(final int i) {
+ return XSLTProperty.VALUES[i];
+ }
+
+ /**
+ * Lookup method to convert from a String
+ *
+ * @param name
+ * a linear search for a property and returns the XSLT property
+ * @return a XSLT property
+ */
+ public static XSLTProperty fromString(final String name) {
+ for (int i = 0; i < XSLTProperty.VALUES.length; i++) {
+ final XSLTProperty o = XSLTProperty.VALUES[i];
+ if (o.name.equalsIgnoreCase(name)) {
+ return o;
+ }
+ }
+ assert false;
+ return null;
+ }
+
+ /**
+ *
+ * @param provider
+ * sets the SAX provider
+ */
+ public static void setProperties(final TransformingSAXEventProvider provider) {
+ for (int i = 0; i < XSLTProperty.VALUES.length; i++) {
+ XSLTProperty.VALUES[i].setProperty(provider);
+ }
+ }
+
+ /**
+ *
+ * @return default state
+ */
+ public boolean getDefaultState() {
+ return Boolean.valueOf(defaultState).booleanValue();
+ }
+
+ /**
+ *
+ * @return default state as a string
+ */
+ public String getDefaultStringState() {
+ return defaultState;
+ }
+
+ /**
+ * @return the name of the property
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the state
+ */
+ public boolean getState() {
+ return Boolean.valueOf(state).booleanValue();
+ }
+
+ /**
+ *
+ * @return state as a string
+ */
+ public String getStringState() {
+ return state;
+ }
+
+ /**
+ *
+ * @param provider
+ * a SAX provider
+ */
+ public void setProperty(final TransformingSAXEventProvider provider) {
+ if (state != null && state.length() > 0) {
+ String theState = state;
+ if (asURL) {
+ try {
+ theState = NetUtil.getURI(new File(state)).toURL().toString();
+ } catch (final MalformedURLException ex) {
+ Reporter.informUser(this, ex);
+ }
+ }
+ provider.setParameter(name, theState);
+ }
+ }
+
+ /**
+ * @param newState
+ * sets the state to newState
+ */
+ public void setState(final boolean newState) {
+ state = Boolean.toString(newState);
+ }
+
+ /**
+ * @param newState
+ * sets the state to newState
+ */
+ public void setState(final String newState) {
+ state = newState;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * TODO: redo this whole class
+ *
+ * @return an object
+ */
+ Object readResolve() {
+ return XSLTProperty.VALUES[obj];
+ }
+}
Added: trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/StepQueryRunnerImplTest.java
===================================================================
--- trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/StepQueryRunnerImplTest.java (rev 0)
+++ trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/StepQueryRunnerImplTest.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,85 @@
+package com.tyndalehouse.step.web.server.db;
+
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.apache.commons.logging.Log;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.tyndalehouse.step.web.server.db.framework.StepQueryRunnerImpl;
+import com.tyndalehouse.step.web.server.db.framework.UnableToRunQueryException;
+import com.tyndalehouse.step.web.server.db.helper.TestProcessor;
+
+/**
+ * Tests the StepQueryRunner framework
+ *
+ * @author CJBurrell
+ *
+ */
+ at RunWith(JMock.class)
+public class StepQueryRunnerImplTest {
+
+ /** the mock object */
+ private final Mockery context = new Mockery();
+
+ /** tests running a query */
+ @Test
+ public void testRunQuery() throws UnableToRunQueryException {
+ // set up the test
+ final TestProcessor processor = new TestProcessor();
+ final Log log = context.mock(Log.class);
+
+ context.checking(new Expectations() {
+ {
+ ignoring(log);
+ }
+ });
+
+ final StepQueryRunnerImpl impl = new StepQueryRunnerImpl(log);
+
+ // Take an example ResultSet
+
+ final List<String> events = impl.run(processor);
+ Assert.assertNotNull(events);
+ // Assert.assertEquals("Bantu expansion from Cameroon to Central Africa",
+ // events.get(0));
+ // Assert.assertEquals("Events in Africa", events.get(1));
+
+ // TODO: Db Date has changed. this needs investigation
+ // Assert.assertEquals("First date on the Mayan Long Count calendar",
+ // events.get(2));
+ }
+
+ /**
+ * tests and expects a exception to be returned
+ *
+ * @throws UnableToRunQueryException
+ * the query expected to be return on invalid query passed in
+ */
+ @Test(expected = UnableToRunQueryException.class)
+ public void testRunQueryWithNull() throws UnableToRunQueryException {
+ // set up the test
+ final Log log = context.mock(Log.class);
+
+ context.checking(new Expectations() {
+ {
+ allowing(log).debug(with(any(String.class)));
+ allowing(log).trace(with(any(String.class)));
+ allowing(log).info(with(any(String.class)));
+ allowing(log).isDebugEnabled();
+ allowing(log).isTraceEnabled();
+ allowing(log).isInfoEnabled();
+ allowing(log).isErrorEnabled();
+ atLeast(1).of(log).error(with(any(String.class)));
+ }
+ });
+
+ final StepQueryRunnerImpl impl = new StepQueryRunnerImpl(log);
+ impl.run(null);
+ }
+}
Added: trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/TestProcessor.java
===================================================================
--- trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/TestProcessor.java (rev 0)
+++ trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/TestProcessor.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,51 @@
+package com.tyndalehouse.step.web.server.db.helper;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.tyndalehouse.step.web.server.common.ConfigNotLoadedException;
+import com.tyndalehouse.step.web.server.db.framework.MalformedStepQueryException;
+import com.tyndalehouse.step.web.server.db.framework.Query;
+import com.tyndalehouse.step.web.server.db.framework.ResultSetProcessor;
+
+/**
+ * Test processor, to test the retrieval of data from the database
+ *
+ * @author CJBurrell
+ *
+ */
+public class TestProcessor implements ResultSetProcessor<String> {
+ /**
+ * simple constructor
+ */
+ public TestProcessor() {
+
+ }
+
+ public Map<String, Object> getParameters() {
+ final Map<String, Object> params = new HashMap<String, Object>();
+ params.put("event_name", "Events in Africa");
+ params.put("event_id", 2);
+ final long l = -160321161544388L;
+ params.put("date_of_event", l);
+ return params;
+ }
+
+ public Query getQuery() {
+ return TestQueryImpl.TEST_QUERY_PARAMS_DIFFERENT_TYPES;
+ }
+
+ public List<String> process(final ResultSet rs) throws MalformedStepQueryException, ConfigNotLoadedException,
+ SQLException {
+ final List<String> events = new ArrayList<String>();
+
+ while (rs.next()) {
+ events.add(rs.getString("name"));
+ }
+ return events;
+ }
+}
Added: trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/TestQueryImpl.java
===================================================================
--- trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/TestQueryImpl.java (rev 0)
+++ trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/db/helper/TestQueryImpl.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,27 @@
+package com.tyndalehouse.step.web.server.db.helper;
+
+import com.tyndalehouse.step.web.server.db.framework.Query;
+
+public enum TestQueryImpl implements Query {
+ /** a test query */
+ TEST_QUERY_PARAMS_DIFFERENT_TYPES("tests");
+
+ /**
+ * component, directory of the test queries
+ */
+ private final String component;
+
+ /**
+ * creates the enum
+ *
+ * @param component
+ * given a component/directory where the test sql script lives
+ */
+ TestQueryImpl(final String component) {
+ this.component = component;
+ }
+
+ public String getComponent() {
+ return component;
+ }
+}
Added: trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetCurrentBibleTextHandlerTest.java
===================================================================
--- trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetCurrentBibleTextHandlerTest.java (rev 0)
+++ trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetCurrentBibleTextHandlerTest.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,140 @@
+package com.tyndalehouse.step.web.server.handlers;
+
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.tyndalehouse.step.web.server.handler.GetCurrentBibleTextHandler;
+import com.tyndalehouse.step.web.shared.command.GetCurrentBibleTextCommand;
+import com.tyndalehouse.step.web.shared.common.scripturelookup.BibleTextLookupType;
+import com.tyndalehouse.step.web.shared.result.GetCurrentBibleTextResult;
+
+/**
+ * Tests the handler that retrieves scripture from the server
+ *
+ * @author CJBurrell
+ *
+ */
+ at RunWith(JMock.class)
+public class GetCurrentBibleTextHandlerTest {
+ /**
+ * The standard context for mocking objects
+ */
+ private final Mockery context = new Mockery();
+
+ /**
+ * tests a greek reverse interlinear
+ *
+ * @throws ActionException
+ * exception during test
+ **/
+ @Test
+ public void testGreekReverseInterlinear() throws ActionException {
+ final Log log = context.mock(Log.class);
+
+ context.checking(new Expectations() {
+ {
+ ignoring(log);
+ }
+ });
+
+ final GetCurrentBibleTextCommand cmd = new GetCurrentBibleTextCommand("KJV", "acts 1:1");
+ cmd.setTypeOfLookup(BibleTextLookupType.REVERSE_INTERLINEAR);
+
+ final GetCurrentBibleTextHandler handler = new GetCurrentBibleTextHandler();
+ final GetCurrentBibleTextResult result = handler.execute(cmd, null);
+
+ Assert.assertNotNull(result.getPassage());
+ Assert.assertNotNull(result.getPassage().getVerseContent());
+ Assert.assertTrue(result.getPassage().getVerseContent().size() != 0);
+
+ // TODO: add interlinear specific stuff
+
+ }
+
+ /**
+ * tests hebrew reverse interlinear
+ *
+ * @throws ActionException
+ * an exception during execution
+ */
+ @Test
+ public void testHebrewReverseInterlinear() throws ActionException {
+ final Log log = context.mock(Log.class);
+
+ context.checking(new Expectations() {
+ {
+ ignoring(log);
+ }
+ });
+
+ final GetCurrentBibleTextCommand cmd = new GetCurrentBibleTextCommand("KJV", "Gen 1:1");
+ cmd.setTypeOfLookup(BibleTextLookupType.REVERSE_INTERLINEAR);
+
+ final GetCurrentBibleTextHandler handler = new GetCurrentBibleTextHandler();
+ final GetCurrentBibleTextResult result = handler.execute(cmd, null);
+
+ Assert.assertNotNull(result.getPassage());
+ Assert.assertNotNull(result.getPassage().getVerseContent());
+ Assert.assertTrue(result.getPassage().getVerseContent().size() != 0);
+
+ // TODO: add interlinear specific stuff
+
+ }
+
+ /**
+ * tests a logical lookup of the passage, as opposed to plain text
+ *
+ * @throws ActionException
+ * exception during running
+ */
+ @Test
+ public void testLogicalPassage() throws ActionException {
+ final Log log = context.mock(Log.class);
+
+ context.checking(new Expectations() {
+ {
+ ignoring(log);
+ }
+ });
+
+ final GetCurrentBibleTextCommand cmd = new GetCurrentBibleTextCommand("ESV", "Gen 1:1");
+ cmd.setTypeOfLookup(BibleTextLookupType.LOGICAL);
+
+ final GetCurrentBibleTextHandler handler = new GetCurrentBibleTextHandler();
+ final GetCurrentBibleTextResult result = handler.execute(cmd, null);
+
+ Assert.assertEquals(result.getPassage().getText(), "In the beginning, God created the heavens and the earth.");
+ }
+
+ /**
+ * An lookup for plain text
+ *
+ * @throws ActionException
+ * exception during the retrieval of the text
+ */
+ @Test
+ public void testLookupText() throws ActionException {
+ final Log log = context.mock(Log.class);
+
+ context.checking(new Expectations() {
+ {
+ ignoring(log);
+ }
+ });
+
+ final GetCurrentBibleTextCommand cmd = new GetCurrentBibleTextCommand("ESV", "Gen 1:1");
+ cmd.setTypeOfLookup(BibleTextLookupType.PLAIN_TEXT);
+
+ final GetCurrentBibleTextHandler handler = new GetCurrentBibleTextHandler();
+ final GetCurrentBibleTextResult result = handler.execute(cmd, null);
+
+ Assert.assertEquals(result.getPassageText(), "In the beginning, God created the heavens and the earth.");
+ }
+}
Added: trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetDictionaryDefinitionHandlerTest.java
===================================================================
--- trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetDictionaryDefinitionHandlerTest.java (rev 0)
+++ trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetDictionaryDefinitionHandlerTest.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,70 @@
+package com.tyndalehouse.step.web.server.handlers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Assert;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.tyndalehouse.step.web.server.handler.GetDictionaryDefinitionHandler;
+import com.tyndalehouse.step.web.shared.command.GetDictionaryDefinitionCommand;
+import com.tyndalehouse.step.web.shared.result.GetDictionaryDefinitionResult;
+
+/**
+ * Tests the retrieval of a dictionary definition from a dictionary module
+ *
+ * @author CJBurrell
+ *
+ */
+ at RunWith(JMock.class)
+public class GetDictionaryDefinitionHandlerTest {
+
+ /**
+ * The standard context for mocking objects
+ */
+ private final Mockery context = new Mockery();
+
+ // TODO: add test to ensure that we have a negative,
+ // what happens when we lookup a reference that doesn't exist
+ // at the moment we get a false positive
+
+ /**
+ * looks up some text for two references, one greek, one hebrew
+ *
+ * @throws ActionException
+ * an exception during execution of the test
+ */
+ @Test
+ public void testLookupText() throws ActionException {
+ final List<String> lookupReferences = new ArrayList<String>();
+ lookupReferences.add("strong:G00051");
+ lookupReferences.add("strong:H00052");
+
+ final Log log = context.mock(Log.class);
+ context.checking(new Expectations() {
+ {
+ ignoring(log);
+ }
+ });
+
+ final GetDictionaryDefinitionCommand cmd = new GetDictionaryDefinitionCommand();
+ cmd.setLookupReference(lookupReferences);
+
+ final GetDictionaryDefinitionHandler handler = new GetDictionaryDefinitionHandler();
+ final GetDictionaryDefinitionResult result = handler.execute(cmd, null);
+
+ Assert.assertTrue(result.getXsltedDefinition().contains(">00051<"));
+ Assert.assertTrue(result.getXsltedDefinition().contains("Abshay"));
+
+ Assert.assertTrue(result.getXsltedDefinition().contains(">00052<"));
+ Assert.assertTrue(result.getXsltedDefinition().contains("a thing ignored"));
+
+ }
+}
Added: trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetTimelineUISetupHandlerTest.java
===================================================================
--- trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetTimelineUISetupHandlerTest.java (rev 0)
+++ trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/GetTimelineUISetupHandlerTest.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,61 @@
+package com.tyndalehouse.step.web.server.handlers;
+
+import java.util.ArrayList;
+
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.tyndalehouse.step.web.server.db.framework.StepQueryRunner;
+import com.tyndalehouse.step.web.server.handler.GetTimelineUISetupHandler;
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineBean;
+
+/**
+ * Testing the timeline setup handler
+ *
+ * @author CJBurrell
+ *
+ */
+ at RunWith(JMock.class)
+public class GetTimelineUISetupHandlerTest {
+
+ /**
+ * The standard context for mocking objects
+ */
+ private final Mockery context = new Mockery();
+
+ /**
+ * looks up
+ *
+ * @throws ActionException
+ * an exception during the running
+ */
+ @Test
+ public void testTimelineUIHandler() throws ActionException {
+ final Log log = context.mock(Log.class);
+
+ context.checking(new Expectations() {
+ {
+ ignoring(log);
+ }
+ });
+
+ final StepQueryRunner runner = context.mock(StepQueryRunner.class);
+ context.checking(new Expectations() {
+ {
+ atMost(1).of(runner);
+ will(returnValue(new ArrayList<TimelineBean>()));
+ }
+ });
+
+ new GetTimelineUISetupHandler(runner).execute(null, null);
+
+ // this test is purely to check we are not calling the database more
+ // than is required.
+ }
+}
Added: trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/JSwordInstallTest.java
===================================================================
--- trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/JSwordInstallTest.java (rev 0)
+++ trunk/step-web-server/src/test/java/com/tyndalehouse/step/web/server/handlers/JSwordInstallTest.java 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,40 @@
+package com.tyndalehouse.step.web.server.handlers;
+
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.junit.Test;
+
+/**
+ * Tests JSword installation handler
+ *
+ * @author CJBurrell
+ *
+ */
+public class JSwordInstallTest {
+ /**
+ * tests the installation of a bible version from JSword/crosswire.org
+ *
+ * @throws ActionException
+ * an exception during execution of the tests
+ */
+ @Test
+ public void testInstallESV() throws ActionException {
+ // TODO: change to a module that's tiny. Because this test is quite
+ // slow, also relies on outside world
+ //
+ // final String initials = "ASV";
+ // final InstallJswordModuleCommand cmd = new
+ // InstallJswordModuleCommand();
+ // cmd.setInitials(initials);
+ //
+ //
+ // final InstallJswordModuleHandler ijmh = new
+ // InstallJswordModuleHandler();
+ // final InstallJswordModuleResult result = ijmh.execute(cmd, null);
+ //
+ // Assert.assertTrue(result.isSuccessful());
+ // Assert.assertTrue(Books.installed().getBook(initials) != null);
+ // // check book is installed
+
+ }
+}
Added: trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/server/db/queries/tests/test_query_params_different_types.sql
===================================================================
--- trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/server/db/queries/tests/test_query_params_different_types.sql (rev 0)
+++ trunk/step-web-server/src/test/resources/com/tyndalehouse/step/web/server/db/queries/tests/test_query_params_different_types.sql 2010-06-25 20:30:48 UTC (rev 141)
@@ -0,0 +1,30 @@
+--------------------------------------------------------
+-- Query test
+-- This looks up 3 events
+--------------------------------------------------------
+define date_of_event as bigint
+define event_name as varchar
+define event_id as integer
+
+
+ select
+ name
+ from
+ step.event
+ where
+ name = #event_name# -- 'Events in Africa'
+union
+ select
+ name
+ from
+ step.event
+ where
+ event_id = #event_id# -- 2
+union
+ select
+ name
+ from
+ step.event
+ where
+ from_date = #date_of_event# -- = -160321161544388
+order by name
More information about the Tynstep-svn
mailing list