[Tynstep-svn] r120 - in trunk/step-web-app/src/main/java/com/tyndalehouse/step/web: . client client/common client/event client/eventhandler client/gin client/presenter client/service client/service/eventbus client/service/refdata client/toolkit client/toolkit/scripture client/toolkit/timeline client/toolkit/timeline/components client/toolkit/timeline/events client/toolkit/timeline/exceptions client/toolkit/timeline/helpers client/view server server/common server/db server/db/framework server/db/timeline server/guice server/handler server/handler/util server/handler/util/passage server/jsword server/jsword/com server/jsword/com/tyndalehouse server/jsword/com/tyndalehouse/step server/jsword/com/tyndalehouse/step/web shared shared/command shared/common shared/common/maps shared/common/scripturelookup shared/common/timeline shared/result shared/scripture shared/timeline
ChrisBurrell at crosswire.org
ChrisBurrell at crosswire.org
Wed Apr 14 15:11:51 MST 2010
Author: ChrisBurrell
Date: 2010-04-14 15:11:51 -0700 (Wed, 14 Apr 2010)
New Revision: 120
Added:
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/StepEntryPoint.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/common/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/common/CachingDispatchAsync.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/BookSelectedEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/DictionaryDefinitionFoundEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/LemmaClickedEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/ModuleChangeEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/ScriptureChangeEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/TimebandListUpdateRequiredEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/TimelineScrollEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/UserInterestInBandEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/VersionChangeEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/BookSelectedEventHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/DictionaryDefinitionFoundHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/LemmaClickedEventHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/ModuleChangeEventHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/ScriptureChangeEventHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/TimebandListUpdateRequiredEventHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/TimelineScrollEventHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/UserInterestInBandEventHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/VersionChangeEventHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/StepClientModule.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/StepInjector.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/AppPresenter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/HistoryModulePresenter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ModuleSelectorPresenter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ScripturePresenter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ScriptureSelectorPresenter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/StepPresenter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/TimebandListPresenter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/TimelinePresenter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/eventbus/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/eventbus/StepEventBusImpl.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/ModuleName.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/ModuleRefData.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/HasSource.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/HtmlList.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/SimpleListBox.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/SourceListBox.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/ScriptureDisplayConstants.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/VerseLabel.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TapeTrack.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEvent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEventDescriptor.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeScale.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeband.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeline.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/Orientation.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimebandRequestWindow.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimelineConstants.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/TimelineMouseHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/CannotDeleteEventException.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/IncapableOfCalculatingRequestWindowException.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/TimeBandNotFoundException.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/UnknownFiredElement.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/CurrentBandStats.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/TimeConversionUtil.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/painters/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/HistoryModuleView.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ModuleSelectorView.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ScriptureSelectorView.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ScriptureView.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/StepView.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/TimebandListView.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/TimelineView.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/AbstractStepHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/ConfigNotLoadedException.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/ConfigProvider.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/JSwordConstants.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/MalformedStepQueryException.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/Query.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/QueryImpl.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/ResultSetProcessor.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQuery.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunner.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunnerImpl.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/UnableToRunQueryException.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimeBandVisibleDateProcessor.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginDbBean.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginProcessor.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineSetupDataProcessor.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/CustomDispatchServiceServlet.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/DispatchServletModule.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/LogProvider.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/MyGuiceServletConfig.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/ServerModule.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetAvailableBibleVersionsHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetBibleBooksHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetCurrentBibleTextHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetDictionaryDefinitionHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetEventsForDateRangeHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetLocationsHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineOriginForScriptureHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineUISetupHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/InstallJswordModuleHandler.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/util/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/StrongMorphMap.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/ConfigurableHTMLConverter.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/XSLTProperty.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/com/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/step/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/step/web/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/com/tyndalehouse/step/web/server/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/BooksRequiredType.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetAvailableBibleVersionsCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetBibleBooksCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetCurrentBibleTextCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetDictionaryDefinitionCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetEventsForDateRangeCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetLocationsCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetTimelineOriginForScriptureCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetTimelineUISetupCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/InstallJswordModuleCommand.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/GeoLocation.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/GeoLocationType.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/LatLong.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/scripturelookup/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/scripturelookup/BibleTextLookupType.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimeBandVisibleDate.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimelineBean.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimelineEventBean.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetAvailableBibleVersionsResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetBibleBooksCommandResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetCurrentBibleTextResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetDictionaryDefinitionResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetEventsForDateRangeResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetLocationsResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetTimelineOriginForScriptureResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetTimelineUISetupResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/InstallJswordModuleResult.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Milestone.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Note.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/OSISConstants.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Passage.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Text.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/TextualElement.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Title.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/TransChange.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Verse.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/VerseContent.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Word.java
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/timeline/
trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/timeline/Unit.java
Log:
committing the core code
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/StepEntryPoint.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/StepEntryPoint.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/StepEntryPoint.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,32 @@
+package com.tyndalehouse.step.web.client;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.tyndalehouse.step.web.client.gin.StepInjector;
+import com.tyndalehouse.step.web.client.presenter.AppPresenter;
+
+/**
+ * Entry point to the one and only application page
+ *
+ * @author cjburrell
+ *
+ */
+public class StepEntryPoint implements EntryPoint {
+
+ /**
+ * Main step injector
+ */
+ private final StepInjector injector = GWT.create(StepInjector.class);
+
+ /**
+ * Entry point to the Step application
+ */
+ public void onModuleLoad() {
+ final AppPresenter appPresenter = injector.getAppPresenter();
+ appPresenter.go(RootPanel.get());
+
+ // injector.getPlaceManager().fireCurrentPlace();
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/common/CachingDispatchAsync.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/common/CachingDispatchAsync.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/common/CachingDispatchAsync.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,92 @@
+package com.tyndalehouse.step.web.client.common;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.dispatch.shared.Action;
+import net.customware.gwt.dispatch.shared.Result;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.inject.Inject;
+
+//TODO: investigate the user of this client side cache
+/**
+ * Dispatcher which support caching of data in memory
+ *
+ */
+public class CachingDispatchAsync implements DispatchAsync {
+ /**
+ *
+ */
+ private final Map<Action<Result>, Result> cache = new HashMap<Action<Result>, Result>();
+
+ /**
+ * The default dispatcher
+ */
+ private final DispatchAsync dispatcher;
+
+ /**
+ * The default constructor
+ *
+ * @param dispatcher uses the default dispatcher
+ */
+ @Inject
+ public CachingDispatchAsync(final DispatchAsync dispatcher) {
+ this.dispatcher = dispatcher;
+ }
+
+ /**
+ * Clear the cache
+ */
+ public void clear() {
+ cache.clear();
+ }
+
+ /**
+ * This method is a simple wrapper around the DispatchAsync class at the
+ * moment
+ *
+ * @param <A> Action implementation
+ * @param <R> Result implementation
+ * @param action the action
+ * @param callback the callback
+ * @see net.customware.gwt.dispatch.client.DispatchAsync#execute(A,
+ * com.google.gwt.user.client.rpc.AsyncCallback)
+ */
+ public <A extends Action<R>, R extends Result> void execute(final A action,
+ final AsyncCallback<R> callback) {
+ dispatcher.execute(action, callback);
+ }
+
+ /**
+ * Execute the given Action. If the Action was executed before it will get
+ * fetched from the cache
+ *
+ * @param <A> Action implementation
+ * @param <R> Result implementation
+ * @param action the action
+ * @param callback the callback
+ */
+ @SuppressWarnings("unchecked")
+ public <A extends Action<R>, R extends Result> void executeWithCache(final A action,
+ final AsyncCallback<R> callback) {
+ final Result r = cache.get(action);
+
+ if (r != null) {
+ callback.onSuccess((R) r);
+ } else {
+ dispatcher.execute(action, new AsyncCallback<R>() {
+
+ public void onFailure(final Throwable caught) {
+ callback.onFailure(caught);
+ }
+
+ public void onSuccess(final R result) {
+ cache.put((Action) action, (Result) result);
+ callback.onSuccess(result);
+ }
+ });
+ }
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/BookSelectedEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/BookSelectedEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/BookSelectedEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,32 @@
+package com.tyndalehouse.step.web.client.event;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.BookSelectedEventHandler;
+
+/**
+ * The user has selected a book on the UI, and this is being fired to the
+ * DefaultEventBus
+ *
+ * @author CJBurrell
+ *
+ */
+public class BookSelectedEvent extends GwtEvent<BookSelectedEventHandler> {
+
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ private static Type<BookSelectedEventHandler> TYPE = new Type<BookSelectedEventHandler>();
+
+ @Override
+ public Type<BookSelectedEventHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ @Override
+ protected void dispatch(final BookSelectedEventHandler handler) {
+ handler.onBookSelected(this);
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/DictionaryDefinitionFoundEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/DictionaryDefinitionFoundEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/DictionaryDefinitionFoundEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,59 @@
+package com.tyndalehouse.step.web.client.event;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.DictionaryDefinitionFoundHandler;
+
+/**
+ * The dictionary definition found event. This is fired when the server has
+ * responded with a dictionary definition and different parts of the system may
+ * require notification of it.
+ *
+ * @author cjburrell
+ *
+ */
+public class DictionaryDefinitionFoundEvent extends GwtEvent<DictionaryDefinitionFoundHandler> {
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ private static Type<DictionaryDefinitionFoundHandler> TYPE = new Type<DictionaryDefinitionFoundHandler>();
+
+ /**
+ * the definition that was retrieved
+ */
+ private String definition;
+
+ /**
+ * default constructor
+ *
+ * @param defintion this is the definition that was retrieved from the
+ * server
+ */
+ public DictionaryDefinitionFoundEvent(final String defintion) {
+ this.definition = defintion;
+ }
+
+ @Override
+ public Type<DictionaryDefinitionFoundHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * @return the definition
+ */
+ public String getDefinition() {
+ return definition;
+ }
+
+ /**
+ * @param definition the definition to set
+ */
+ public void setDefinition(final String definition) {
+ this.definition = definition;
+ }
+
+ @Override
+ protected void dispatch(final DictionaryDefinitionFoundHandler handler) {
+ handler.onDefinitionFound(this);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/LemmaClickedEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/LemmaClickedEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/LemmaClickedEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,59 @@
+package com.tyndalehouse.step.web.client.event;
+
+import java.util.List;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.LemmaClickedEventHandler;
+
+/**
+ * This event is fired when a portion of scripture tagged with 1 or more lemma
+ * (strong number for e.g.) has been clicked. The event contains details of the
+ * lemmas references.
+ *
+ * @author cjburrell
+ *
+ */
+public class LemmaClickedEvent extends GwtEvent<LemmaClickedEventHandler> {
+ /**
+ * Type of event
+ */
+ public static Type<LemmaClickedEventHandler> TYPE = new Type<LemmaClickedEventHandler>();
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ private List<String> lemma;
+
+ /**
+ * constructing the event with a list of lemmas
+ *
+ * @param lemmas the list of lemmas that were clicked upon
+ */
+ public LemmaClickedEvent(final List<String> lemmas) {
+ this.lemma = lemmas;
+ }
+
+ @Override
+ public Type<LemmaClickedEventHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * @return the lemma
+ */
+ public List<String> getLemma() {
+ return lemma;
+ }
+
+ /**
+ * @param lemma the lemma to set
+ */
+ public void setLemma(final List<String> lemma) {
+ this.lemma = lemma;
+ }
+
+ @Override
+ protected void dispatch(final LemmaClickedEventHandler handler) {
+ handler.onLemmaClicked(this);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/ModuleChangeEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/ModuleChangeEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/ModuleChangeEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,75 @@
+package com.tyndalehouse.step.web.client.event;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.ModuleChangeEventHandler;
+
+/**
+ * Event is fired when part of the module definition (module, sub module, depth)
+ * has been changed
+ *
+ * @author cjburrell
+ *
+ */
+public class ModuleChangeEvent extends GwtEvent<ModuleChangeEventHandler> {
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ private static Type<ModuleChangeEventHandler> TYPE = new Type<ModuleChangeEventHandler>();
+
+ /** newly selected depth of stud */
+ private final String newDepth;
+ /** newly selected module */
+ private final String newModule;
+ /** newly selected submodule */
+ private final String newSubModule;
+
+ /**
+ * creates an event alerting of the new chosen combination of
+ * module/sub-module/depth
+ *
+ * @param newModule new module
+ * @param newSubModule new sub module
+ * @param newDepth new depth of study
+ */
+ public ModuleChangeEvent(final String newModule, final String newSubModule,
+ final String newDepth) {
+ this.newModule = newModule;
+ this.newSubModule = newSubModule;
+ this.newDepth = newDepth;
+ }
+
+ @Override
+ public Type<ModuleChangeEventHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ *
+ * @return the depth
+ */
+ public String getNewDepth() {
+ return newDepth;
+ }
+
+ /**
+ * @return the new module
+ */
+ public String getNewModule() {
+ return newModule;
+ }
+
+ /**
+ *
+ * @return the new sub module
+ */
+ public String getNewSubModule() {
+ return newSubModule;
+ }
+
+ @Override
+ protected void dispatch(final ModuleChangeEventHandler handler) {
+ handler.onModuleChange(this);
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/ScriptureChangeEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/ScriptureChangeEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/ScriptureChangeEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,53 @@
+package com.tyndalehouse.step.web.client.event;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.ScriptureChangeEventHandler;
+
+/**
+ * Scripture change is fired when the scripture viewed on the screen is
+ * requested to be different
+ *
+ * @author cjburrell
+ *
+ */
+public class ScriptureChangeEvent extends GwtEvent<ScriptureChangeEventHandler> {
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ // TODO: remove this type into an abstract layer
+ public static Type<ScriptureChangeEventHandler> TYPE = new Type<ScriptureChangeEventHandler>();
+
+ /**
+ * This is the new reference that is being fired.
+ */
+ private final String newReference;
+
+ /**
+ * Constructor to create a scripture change even with a biblical reference
+ *
+ * @param newReference the new reference that has been chosen by the user
+ */
+ public ScriptureChangeEvent(final String newReference) {
+ this.newReference = newReference;
+ }
+
+ @Override
+ public Type<ScriptureChangeEventHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * @return the new biblical reference that has been selected
+ */
+ public String getNewReference() {
+ return newReference;
+ }
+
+ @Override
+ protected void dispatch(final ScriptureChangeEventHandler handler) {
+ handler.onScriptureChange(this);
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/TimebandListUpdateRequiredEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/TimebandListUpdateRequiredEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/TimebandListUpdateRequiredEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,60 @@
+package com.tyndalehouse.step.web.client.event;
+
+import java.util.List;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.TimebandListUpdateRequiredEventHandler;
+import com.tyndalehouse.step.web.client.toolkit.timeline.helpers.CurrentBandStats;
+
+/**
+ * Event signalling that the timebands have been changed and an update is
+ * required from any component keeping track of counts
+ *
+ * @author cjburrell
+ *
+ */
+public class TimebandListUpdateRequiredEvent extends
+ GwtEvent<TimebandListUpdateRequiredEventHandler> {
+
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ public static Type<TimebandListUpdateRequiredEventHandler> TYPE = new Type<TimebandListUpdateRequiredEventHandler>();
+
+ /**
+ * List of new statistics, one for each band
+ */
+ private final List<CurrentBandStats> stats;
+
+ /**
+ * The timeline is passed in, so that the timeband list can know what the
+ * new values are
+ *
+ * @param stats timeline to be passed in
+ */
+ public TimebandListUpdateRequiredEvent(final List<CurrentBandStats> stats) {
+ this.stats = stats;
+
+ }
+
+ @Override
+ public Type<TimebandListUpdateRequiredEventHandler> getAssociatedType() {
+ // TODO Auto-generated method stub
+ return TYPE;
+ }
+
+ /**
+ * @return the stats
+ */
+ public List<CurrentBandStats> getTimelineStats() {
+ return stats;
+ }
+
+ @Override
+ protected void dispatch(final TimebandListUpdateRequiredEventHandler handler) {
+ handler.onTimebandListRequiringUpdate(this);
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/TimelineScrollEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/TimelineScrollEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/TimelineScrollEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,85 @@
+package com.tyndalehouse.step.web.client.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.TimelineScrollEventHandler;
+import com.tyndalehouse.step.web.shared.common.timeline.TimeBandVisibleDate;
+
+/**
+ * Event signalling the timeline has been scrolled. This event contains the list
+ * of timebands, and the portions of those that need updating
+ *
+ * @author cjburrell
+ *
+ */
+public class TimelineScrollEvent extends GwtEvent<TimelineScrollEventHandler> {
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ public static Type<TimelineScrollEventHandler> TYPE = new Type<TimelineScrollEventHandler>();
+
+ /**
+ * list of requests to the server on which portions of which bands need to
+ * be updated
+ */
+ private List<TimeBandVisibleDate> timebandVisibleDates;
+
+ /**
+ * default constructor
+ */
+ public TimelineScrollEvent() {
+ timebandVisibleDates = new ArrayList<TimeBandVisibleDate>();
+ }
+
+ /**
+ * adds a timeband and the portion of time that needs updating
+ *
+ * @param timebandId the timeband id
+ * @param minDate the minimum date
+ * @param maxDate the maximum date
+ */
+ public void addTimebandVisibleDate(final int timebandId, final long minDate, final long maxDate) {
+ final TimeBandVisibleDate visibleDate = new TimeBandVisibleDate(timebandId, minDate,
+ maxDate);
+ addTimebandVisibleDate(visibleDate);
+ }
+
+ /**
+ * adds a @see {@link TimeBandVisibleDate} to the event
+ *
+ * @param visibleDate the TimeBandVisibleDate object containing details of
+ * which parts of the timeband (min, max) need updating.
+ */
+ public void addTimebandVisibleDate(final TimeBandVisibleDate visibleDate) {
+ if (!visibleDate.isNoRequest()) {
+ timebandVisibleDates.add(visibleDate);
+ }
+ }
+
+ @Override
+ public Type<TimelineScrollEventHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * @return the timebandVisibleDates
+ */
+ public List<TimeBandVisibleDate> getTimebandVisibleDates() {
+ return timebandVisibleDates;
+ }
+
+ /**
+ * @param timebandVisibleDates the timebandVisibleDates to set
+ */
+ public void setTimebandVisibleDates(final List<TimeBandVisibleDate> timebandVisibleDates) {
+ this.timebandVisibleDates = timebandVisibleDates;
+ }
+
+ @Override
+ protected void dispatch(final TimelineScrollEventHandler handler) {
+ handler.onScroll(this);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/UserInterestInBandEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/UserInterestInBandEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/UserInterestInBandEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,64 @@
+package com.tyndalehouse.step.web.client.event;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.UserInterestInBandEventHandler;
+
+/**
+ * Event signalling the user is interested or not interested in a new timeband
+ *
+ * @author cjburrell
+ *
+ */
+public class UserInterestInBandEvent extends GwtEvent<UserInterestInBandEventHandler> {
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ public static Type<UserInterestInBandEventHandler> TYPE = new Type<UserInterestInBandEventHandler>();
+
+ /**
+ * the band the user has selected to choose or dismiss
+ */
+ private final int bandId;
+
+ /**
+ * whether the user wants to see the band or not
+ */
+ private final Boolean isOfInterest;
+
+ /**
+ * creates the event
+ *
+ * @param bandId the band that the user selected
+ * @param isOfInterest whether the user is interested in it or not
+ */
+ public UserInterestInBandEvent(final int bandId, final Boolean isOfInterest) {
+ this.bandId = bandId;
+ this.isOfInterest = isOfInterest;
+ }
+
+ @Override
+ public Type<UserInterestInBandEventHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * @return the bandId
+ */
+ public int getBandId() {
+ return bandId;
+ }
+
+ /**
+ * @return the isOfInterest
+ */
+ public Boolean isOfInterest() {
+ return isOfInterest;
+ }
+
+ @Override
+ protected void dispatch(final UserInterestInBandEventHandler handler) {
+ handler.onUserInterestedInBand(this);
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/VersionChangeEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/VersionChangeEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/event/VersionChangeEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,29 @@
+package com.tyndalehouse.step.web.client.event;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.tyndalehouse.step.web.client.eventhandler.VersionChangeEventHandler;
+
+/**
+ * Event signalling a change of bible version of the UI
+ *
+ * @author cjburrell
+ *
+ */
+public class VersionChangeEvent extends GwtEvent<VersionChangeEventHandler> {
+ /**
+ * The default Type Handler Type is parameterized by the handler type in
+ * order to make the addHandler method type safe.
+ */
+ public static Type<VersionChangeEventHandler> TYPE = new Type<VersionChangeEventHandler>();
+
+ @Override
+ public Type<VersionChangeEventHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ @Override
+ protected void dispatch(final VersionChangeEventHandler handler) {
+ handler.onVersionChange(this);
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/BookSelectedEventHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/BookSelectedEventHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/BookSelectedEventHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,22 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.BookSelectedEvent;
+
+/**
+ * Contract for any handler wanting to handle a BookSelectedEvent In particular
+ * this means handling a click for e.g. on the UI in the list of bible books
+ * (Genesis, Exodus, etc.)
+ *
+ * @author cjburrell
+ *
+ */
+public interface BookSelectedEventHandler extends EventHandler {
+
+ /**
+ * This method is called when a @see {@link BookSelectedEvent} is triggered
+ *
+ * @param event that is provided to the handler
+ */
+ void onBookSelected(BookSelectedEvent event);
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/DictionaryDefinitionFoundHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/DictionaryDefinitionFoundHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/DictionaryDefinitionFoundHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,22 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.DictionaryDefinitionFoundEvent;
+
+/**
+ * This contract is relevant to any handler who wants to be notified when a
+ * definition was looked up from the server
+ *
+ * @author cjburrell
+ *
+ */
+public interface DictionaryDefinitionFoundHandler extends EventHandler {
+ /**
+ * This method is fired when a dictionary definition has been looked up from
+ * the server
+ *
+ * @param dictionaryDefintionFoundEvent the dictionary definition found
+ * event, containing the results from the server
+ */
+ void onDefinitionFound(DictionaryDefinitionFoundEvent dictionaryDefintionFoundEvent);
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/LemmaClickedEventHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/LemmaClickedEventHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/LemmaClickedEventHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,21 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.LemmaClickedEvent;
+
+/**
+ * Contract for handlers who are interested in the user clicking on a portion of
+ * scripture which was tagged with a lemma
+ *
+ * @author cjburrell
+ *
+ */
+public interface LemmaClickedEventHandler extends EventHandler {
+ /**
+ * This is fired when a click on a portion of scripture tagged with a lemma
+ * has occured
+ *
+ * @param lemmaClickedEvent the event that is provided to the handler
+ */
+ void onLemmaClicked(LemmaClickedEvent lemmaClickedEvent);
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/ModuleChangeEventHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/ModuleChangeEventHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/ModuleChangeEventHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,20 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.ModuleChangeEvent;
+
+/**
+ * Contract for handlers interested in a selection of a different module
+ *
+ * @author cjburrell
+ *
+ */
+public interface ModuleChangeEventHandler extends EventHandler {
+ /**
+ * Called when the user has selected a different module
+ *
+ * @param event provided to the handler containing the new module
+ * combination
+ */
+ void onModuleChange(ModuleChangeEvent event);
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/ScriptureChangeEventHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/ScriptureChangeEventHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/ScriptureChangeEventHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,20 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.ScriptureChangeEvent;
+
+/**
+ * Handler contract for when the user changes the portion of scripture he is
+ * viewing
+ *
+ * @author cjburrell
+ *
+ */
+public interface ScriptureChangeEventHandler extends EventHandler {
+ /**
+ * Fired when the user changes the portion of scripture currently viewed
+ *
+ * @param event event containing the details of the new scripture requested
+ */
+ void onScriptureChange(ScriptureChangeEvent event);
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/TimebandListUpdateRequiredEventHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/TimebandListUpdateRequiredEventHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/TimebandListUpdateRequiredEventHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,22 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.TimebandListUpdateRequiredEvent;
+
+/**
+ * Contract for handlers requiring notification of updates to the number of
+ * events on the timebands
+ *
+ * @author cjburrell
+ *
+ */
+public interface TimebandListUpdateRequiredEventHandler extends EventHandler {
+ /**
+ * This is fired when new events are added to the timeband, or when events
+ * are no longer in the visible section
+ *
+ * @param timebandListUpdateRequiredEvent the event containing the new
+ * statistics to be displayed
+ */
+ void onTimebandListRequiringUpdate(TimebandListUpdateRequiredEvent timebandListUpdateRequiredEvent);
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/TimelineScrollEventHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/TimelineScrollEventHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/TimelineScrollEventHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,23 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.TimelineScrollEvent;
+
+/**
+ * Contract for handlers wanting to be alerted when the timeline is being
+ * scrolled
+ *
+ * @author cjburrell
+ *
+ */
+public interface TimelineScrollEventHandler extends EventHandler {
+
+ /**
+ * Fired when the timeline is being scrolled, before new events are
+ * requested from the server
+ *
+ * @param event event containing the new portions of time to be requested
+ * from the server
+ */
+ void onScroll(TimelineScrollEvent event);
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/UserInterestInBandEventHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/UserInterestInBandEventHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/UserInterestInBandEventHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,23 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.UserInterestInBandEvent;
+
+/**
+ * Contract for handlers requiring notifications of timebands being
+ * selected/unselected
+ *
+ * @author cjburrell
+ *
+ */
+public interface UserInterestInBandEventHandler extends EventHandler {
+
+ /**
+ * fired when a timeband has been selected/nselected
+ *
+ * @param userInterestInBandEvent contains information about the timeband
+ * that was selected/nselected
+ */
+ void onUserInterestedInBand(UserInterestInBandEvent userInterestInBandEvent);
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/VersionChangeEventHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/VersionChangeEventHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/eventhandler/VersionChangeEventHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,21 @@
+package com.tyndalehouse.step.web.client.eventhandler;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.tyndalehouse.step.web.client.event.VersionChangeEvent;
+
+/**
+ * Contract for handlers requiring updates when the user changes the version of
+ * the bible he is currently accessing
+ *
+ * @author cjburrell
+ *
+ */
+public interface VersionChangeEventHandler extends EventHandler {
+
+ /**
+ * fired when the user selects a different bible version
+ *
+ * @param event the event containing the new version information
+ */
+ void onVersionChange(VersionChangeEvent event);
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/StepClientModule.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/StepClientModule.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/StepClientModule.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,74 @@
+package com.tyndalehouse.step.web.client.gin;
+
+import net.customware.gwt.dispatch.client.DefaultDispatchAsync;
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.gin.AbstractPresenterModule;
+import net.customware.gwt.presenter.client.place.PlaceManager;
+
+import com.google.inject.Singleton;
+import com.tyndalehouse.step.web.client.common.CachingDispatchAsync;
+import com.tyndalehouse.step.web.client.presenter.AppPresenter;
+import com.tyndalehouse.step.web.client.presenter.HistoryModulePresenter;
+import com.tyndalehouse.step.web.client.presenter.ModuleSelectorPresenter;
+import com.tyndalehouse.step.web.client.presenter.ScripturePresenter;
+import com.tyndalehouse.step.web.client.presenter.ScriptureSelectorPresenter;
+import com.tyndalehouse.step.web.client.presenter.StepPresenter;
+import com.tyndalehouse.step.web.client.presenter.TimebandListPresenter;
+import com.tyndalehouse.step.web.client.presenter.TimelinePresenter;
+import com.tyndalehouse.step.web.client.service.eventbus.StepEventBusImpl;
+import com.tyndalehouse.step.web.client.view.HistoryModuleView;
+import com.tyndalehouse.step.web.client.view.ModuleSelectorView;
+import com.tyndalehouse.step.web.client.view.ScriptureSelectorView;
+import com.tyndalehouse.step.web.client.view.ScriptureView;
+import com.tyndalehouse.step.web.client.view.StepView;
+import com.tyndalehouse.step.web.client.view.TimebandListView;
+import com.tyndalehouse.step.web.client.view.TimelineView;
+
+/**
+ * Gin configuration for the the step client. In addition to normal guice
+ * operations, this binds presenters to their views
+ *
+ * @author cjburrell
+ *
+ */
+public class StepClientModule extends AbstractPresenterModule {
+
+ @Override
+ protected void configure() {
+
+ // put the bindings in here
+
+ bind(EventBus.class).to(StepEventBusImpl.class).in(Singleton.class);
+ bind(TimebandListPresenter.Display.class).to(TimebandListView.class);
+
+ bind(AppPresenter.class).in(Singleton.class);
+ bind(PlaceManager.class).in(Singleton.class);
+
+ bindPresenter(StepPresenter.class, StepPresenter.Display.class, StepView.class);
+ bind(ScriptureSelectorPresenter.class);
+ bind(ScriptureSelectorPresenter.Display.class).to(ScriptureSelectorView.class).in(
+ Singleton.class);
+ bind(ModuleSelectorPresenter.class);
+ bind(ModuleSelectorPresenter.Display.class).to(ModuleSelectorView.class)
+ .in(Singleton.class);
+ bind(ScripturePresenter.class);
+ bind(ScripturePresenter.Display.class).to(ScriptureView.class); // .in(Singleton.class);
+ bind(TimelinePresenter.class);
+ bind(TimelinePresenter.Display.class).to(TimelineView.class); // .in(Singleton.class);
+
+ //
+ // bind(ITimeLineRender.class).to(TimelineRenderer.class);
+
+ bind(HistoryModulePresenter.class);
+ bind(HistoryModulePresenter.Display.class).to(HistoryModuleView.class);
+
+ // bind(new TypeLiteral<StepModulePresenter<? extends
+ // StepModulePresenter.Display>>() {
+ // }).to(HistoryModulePresenter.class);
+
+ bind(DispatchAsync.class).to(DefaultDispatchAsync.class).in(Singleton.class);
+ bind(CachingDispatchAsync.class);
+
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/StepInjector.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/StepInjector.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/gin/StepInjector.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,30 @@
+package com.tyndalehouse.step.web.client.gin;
+
+import net.customware.gwt.presenter.client.place.PlaceManager;
+
+import com.google.gwt.inject.client.GinModules;
+import com.google.gwt.inject.client.Ginjector;
+import com.tyndalehouse.step.web.client.presenter.AppPresenter;
+
+/**
+ * Gin injector. This defines the modules all the Gin modules
+ *
+ * @author cjburrell
+ *
+ */
+ at GinModules( StepClientModule.class )
+public interface StepInjector extends Ginjector {
+ /**
+ * Returns the App Presenter, the main presenter for STEP
+ *
+ * @return the main presenter for STEP
+ */
+ AppPresenter getAppPresenter();
+
+ /**
+ * Returns a place manager
+ *
+ * @return the step place manager
+ */
+ PlaceManager getPlaceManager();
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/AppPresenter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/AppPresenter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/AppPresenter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,67 @@
+package com.tyndalehouse.step.web.client.presenter;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.user.client.ui.HasWidgets;
+import com.google.inject.Inject;
+
+/**
+ * Main presenter for STEP, entry point
+ *
+ * @author cjburrell
+ *
+ */
+public class AppPresenter {
+ /**
+ * container for any main widgets
+ */
+ private HasWidgets container;
+
+ // TODO: investigate whether there is a neater way of doing this
+ /**
+ * Main dispatcher.
+ */
+ @SuppressWarnings(value = "unused")
+ private final DispatchAsync dispatcher;
+
+ /**
+ * The step presenter - TODO: probably one layer of abstration too many,
+ * should be moved this class into StepPresenter
+ */
+ private final StepPresenter stepPresenter;
+
+ /**
+ * The default app presenter for STEP.
+ *
+ * @param dispatcher the dispatcher to use within this class (passed in here
+ * to get it initialised)
+ * @param stepPresenter the step presenter responsible for handling all
+ * other presenters and views
+ */
+ // passing them in to have GIN initialise them!
+ @Inject
+ public AppPresenter(final DispatchAsync dispatcher, final StepPresenter stepPresenter) {
+ this.dispatcher = dispatcher;
+ this.stepPresenter = stepPresenter;
+ Log.debug("AppPresenter is being initialised");
+ }
+
+ /**
+ * Call go to initialise the step application and render
+ *
+ * @param container container on which to add the Step Application
+ */
+ public void go(final HasWidgets container) {
+ this.container = container;
+ showMain();
+ }
+
+ /**
+ * Repaints the page with the step presenter/view
+ */
+ private void showMain() {
+ container.clear();
+ container.add(stepPresenter.getDisplay().asWidget());
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/HistoryModulePresenter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/HistoryModulePresenter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/HistoryModulePresenter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,102 @@
+package com.tyndalehouse.step.web.client.presenter;
+
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.place.Place;
+import net.customware.gwt.presenter.client.place.PlaceRequest;
+import net.customware.gwt.presenter.client.widget.WidgetDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetPresenter;
+
+import com.google.inject.Inject;
+
+/**
+ * History module presenter, responsible for displaying articles on the page
+ *
+ * @author cjburrell
+ *
+ */
+public class HistoryModulePresenter extends WidgetPresenter<HistoryModulePresenter.Display> {
+
+ /**
+ * Interface for the History Module View
+ *
+ * @author cjburrell
+ *
+ */
+ public interface Display extends WidgetDisplay {
+
+ }
+
+ /**
+ * default constructor, injected by Gin
+ *
+ * @param display display, comes from Gin
+ * @param eventBus eventBus comes from Gin
+ */
+ @Inject
+ public HistoryModulePresenter(final Display display, final EventBus eventBus) {
+ super(display, eventBus);
+ bind();
+ }
+
+ @Override
+ public Place getPlace() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refreshDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void revealDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onBind() {
+
+ // eventBus.addHandler(MultipleWordsSelectedEvent.TYPE, new
+ // MultipleWordsSelectedEventHandler() {
+ //
+ // @Override
+ // public void onMultipleWordsSelected(MultipleWordsSelectedEvent event)
+ // {
+ // // TODO Auto-generated method stub
+ //
+ // }
+ // });
+ //
+ // eventBus.addHandler(WordSelectedEvent.TYPE, new
+ // WordSelectedEventHandler() {
+ //
+ // @Override
+ // public void onWordSelectedEvent(WordSelectedEvent event) {
+ //
+ // }
+ // });
+ //
+ // eventBus.addHandler(DepthChangeEvent.TYPE, new
+ // DepthChangeEventHandler() {
+ //
+ // @Override
+ // public void onDepthChange(DepthChangeEvent event) {
+ //
+ // }
+ // });
+ }
+
+ @Override
+ protected void onPlaceRequest(final PlaceRequest request) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onUnbind() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ModuleSelectorPresenter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ModuleSelectorPresenter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ModuleSelectorPresenter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,205 @@
+package com.tyndalehouse.step.web.client.presenter;
+
+import java.util.List;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.place.Place;
+import net.customware.gwt.presenter.client.place.PlaceRequest;
+import net.customware.gwt.presenter.client.widget.WidgetDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetPresenter;
+
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.HasChangeHandlers;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.event.ModuleChangeEvent;
+import com.tyndalehouse.step.web.client.service.refdata.ModuleRefData;
+import com.tyndalehouse.step.web.client.toolkit.HasSource;
+
+/**
+ * Module selector module, responsible for displaying the dropdowns on the user
+ * interface
+ *
+ * @author cjburrell
+ *
+ */
+public class ModuleSelectorPresenter extends WidgetPresenter<ModuleSelectorPresenter.Display> implements
+ ChangeHandler {
+
+ /**
+ * Interface to the module selector view
+ *
+ * @author cjburrell
+ *
+ */
+ public interface Display extends WidgetDisplay {
+ /**
+ *
+ * @return Returns any change handlers so that the presenter can
+ * register event handlers
+ */
+ HasChangeHandlers getModuleChangeHandlers();
+
+ /**
+ *
+ * @return returns a change handler for the "Depth" dropdown/list
+ */
+ HasChangeHandlers getModuleDepthChangeHandlers();
+
+ /**
+ * @return returns the source associated to the Module Depth
+ * dropdown/list
+ */
+ HasSource<List<String>> getModuleDepthSource();
+
+ /**
+ *
+ * @return the source for the module list/dropdown
+ */
+ HasSource<List<String>> getModuleSource();
+
+ /**
+ *
+ * @return current selected depth (for example scholarly detail)
+ */
+ String getSelectedDepth();
+
+ /**
+ *
+ * @return currently selected module
+ */
+ String getSelectedModule();
+
+ /**
+ *
+ * @return currently selected sub-module
+ */
+ String getSelectedSubModule();
+
+ /**
+ *
+ * @return change handlers on which to register event handlers for the
+ * sub module dropdown/list
+ */
+ HasChangeHandlers getSubModuleChangeHandlers();
+
+ /**
+ *
+ * @return source for the sub module dropdown/list
+ */
+ HasSource<List<String>> getSubModuleSource();
+
+ /**
+ * Changes the selected module
+ *
+ * @param newlySelectedModule the new module to be selected
+ */
+ void setSelectedModule(String newlySelectedModule);
+ }
+
+ /**
+ * Default constructor
+ *
+ * @param display display passed in by Gin
+ * @param eventBus eventBus passed in by Gin
+ * @param dispatcher dispatch passed in by Gin
+ */
+ @Inject
+ public ModuleSelectorPresenter(final Display display, final EventBus eventBus,
+ final DispatchAsync dispatcher) {
+ super(display, eventBus);
+ bind();
+ }
+
+ @Override
+ public Place getPlace() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * Used for submodule and depth
+ *
+ * @param event event that was fired by the view.
+ */
+ public void onChange(final ChangeEvent event) {
+ fireChange();
+ }
+
+ public void refreshDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void revealDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * adds the module change handlers, for module list, sub module list and
+ * depth list
+ */
+ private void addDropdownChangeHandlers() {
+ // fires the dropdown change event as a ModuleChangeEvent
+ display.getModuleChangeHandlers().addChangeHandler(new ChangeHandler() {
+
+ public void onChange(final ChangeEvent event) {
+ // in here, we need to reload the events
+ display.getSubModuleSource().setSource(
+ ModuleRefData.getInstance().getListOfModules(display.getSelectedModule()));
+ // this hopefully fires the on Change below since the sub module
+ // dropdown changes...
+ // but it doesn't :( so...
+ fireChange();
+ }
+ });
+
+ display.getSubModuleChangeHandlers().addChangeHandler(this);
+ display.getModuleDepthChangeHandlers().addChangeHandler(this);
+ }
+
+ /**
+ * fires the change of dropdown selectors to the event bus.
+ */
+ private void fireChange() {
+ eventBus.fireEvent(new ModuleChangeEvent(display.getSelectedModule(), display.getSelectedSubModule(),
+ display.getSelectedDepth()));
+
+ }
+
+ @Override
+ protected void onBind() {
+ // do nothing at the moment
+ // add event notifications...
+ addDropdownChangeHandlers();
+
+ // TODO: remove default into configurable options, preferences, etc.
+ final String defaultModule = "History";
+ final ModuleRefData mrd = ModuleRefData.getInstance();
+ final List<String> moduleNames = mrd.getListOfModules("Module");
+ final List<String> subModules = mrd.getListOfModules(defaultModule);
+ final List<String> depths = mrd.getDepths();
+
+ display.setSelectedModule(defaultModule);
+ display.getModuleSource().setSource(moduleNames);
+ display.getSubModuleSource().setSource(subModules);
+ display.getModuleDepthSource().setSource(depths);
+
+ // do i need to fire an module change event?
+ }
+
+ @Override
+ protected void onPlaceRequest(final PlaceRequest request) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onUnbind() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ScripturePresenter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ScripturePresenter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ScripturePresenter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,230 @@
+package com.tyndalehouse.step.web.client.presenter;
+
+import java.util.List;
+import java.util.SortedMap;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.presenter.client.DisplayCallback;
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.place.Place;
+import net.customware.gwt.presenter.client.place.PlaceRequest;
+import net.customware.gwt.presenter.client.widget.WidgetDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetPresenter;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.HasChangeHandlers;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.event.LemmaClickedEvent;
+import com.tyndalehouse.step.web.client.event.ScriptureChangeEvent;
+import com.tyndalehouse.step.web.client.event.VersionChangeEvent;
+import com.tyndalehouse.step.web.client.eventhandler.LemmaClickedEventHandler;
+import com.tyndalehouse.step.web.client.eventhandler.ScriptureChangeEventHandler;
+import com.tyndalehouse.step.web.client.toolkit.HasSource;
+import com.tyndalehouse.step.web.shared.command.GetAvailableBibleVersionsCommand;
+import com.tyndalehouse.step.web.shared.command.GetCurrentBibleTextCommand;
+import com.tyndalehouse.step.web.shared.common.scripturelookup.BibleTextLookupType;
+import com.tyndalehouse.step.web.shared.result.GetAvailableBibleVersionsResult;
+import com.tyndalehouse.step.web.shared.result.GetCurrentBibleTextResult;
+import com.tyndalehouse.step.web.shared.scripture.Passage;
+
+/**
+ * This presenter is responsible for displaying scripture to the user, in an
+ * interactive way including the highlight-on-click, querying the server for
+ * portions of text, etc.
+ *
+ * @author cjburrell
+ *
+ */
+public class ScripturePresenter extends WidgetPresenter<ScripturePresenter.Display> {
+
+ /**
+ * Description of the view for presenting scripture to the user
+ *
+ * @author cjburrell
+ *
+ */
+ public interface Display extends WidgetDisplay {
+ /**
+ * TODO: change the name, it's a bit meaningless change handlers to the
+ * bible versions dropdown
+ *
+ * @return bible versions change handlers
+ */
+ HasChangeHandlers getChangeHandlers();
+
+ /**
+ *
+ * @return the currently selected bible version on the UI
+ */
+ String getSelectedBibleVersion();
+
+ /**
+ *
+ * @return a map (intials -> bible Name) used as the source of the bible
+ * versions dropdown
+ */
+ HasSource<SortedMap<String, String>> getSource();
+
+ /**
+ * action to highlight portions of the biblical text that are tagged
+ * with a lemma
+ *
+ * @param lemmas lemmas to look for in the presented biblical text.
+ */
+ void highlight(List<String> lemmas);
+
+ /**
+ * @param passage a logical passage to be displayed
+ */
+ void setPassage(Passage passage);
+
+ /**
+ * @param text the text form of the passage
+ */
+ void setPassage(String text);
+ }
+
+ /**
+ * default asynchronous dispatcher
+ */
+ private final DispatchAsync dispatcher;
+
+ /**
+ * the view itself, used to interact with it
+ */
+ private final ScriptureSelectorPresenter.Display scriptureSelectorView;
+
+ /**
+ *
+ * @param display the view, provided by Gin
+ * @param eventBus the event bus, provided by Gin
+ * @param dispatcher the dispatcher, provided by Gin
+ * @param scriptureSelectorView the scripture selector view (i.e. the bit
+ * with the reference in it), provided by Gin
+ */
+ @Inject
+ public ScripturePresenter(final Display display, final EventBus eventBus,
+ final DispatchAsync dispatcher,
+ final ScriptureSelectorPresenter.Display scriptureSelectorView) {
+ super(display, eventBus);
+ // TODO: remove dependency on scripture selector view
+ this.dispatcher = dispatcher;
+ this.scriptureSelectorView = scriptureSelectorView;
+ Log.debug("Initialising Scripture Presenter");
+ bind();
+ }
+
+ @Override
+ public Place getPlace() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refreshDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void revealDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * Sends a request to the server to get the new text to be displayed. TODO:
+ * this should be parameterized since the cmd options are set to defaults
+ * here for testing
+ */
+ private void doRefreshScripture() {
+ final GetCurrentBibleTextCommand cmd = new GetCurrentBibleTextCommand(display
+ .getSelectedBibleVersion(), scriptureSelectorView.getReference().getValue());
+ // TODO: decide if this should be made static or UI driven
+ cmd.setTypeOfLookup(BibleTextLookupType.REVERSE_INTERLINEAR);
+
+ dispatcher.execute(cmd, new DisplayCallback<GetCurrentBibleTextResult>(display) {
+
+ @Override
+ protected void handleFailure(final Throwable e) {
+ Log.error("An error has occurred", e);
+ }
+
+ @Override
+ protected void handleSuccess(final GetCurrentBibleTextResult result) {
+ // String text = result.getPassageText();
+ display.setPassage(result.getPassage());
+ }
+
+ });
+ }
+
+ @Override
+ protected void onBind() {
+ Log.debug("Binding Scripture Presenter");
+ // get list of versions now...
+ dispatcher.execute(new GetAvailableBibleVersionsCommand(),
+ new DisplayCallback<GetAvailableBibleVersionsResult>(display) {
+ @Override
+ protected void handleFailure(final Throwable e) {
+ Log.error("An error occurred while retrieving bible versions: ", e);
+ }
+
+ @Override
+ protected void handleSuccess(final GetAvailableBibleVersionsResult result) {
+ display.getSource().setSource(result.getBooks());
+ }
+ });
+
+ display.getChangeHandlers().addChangeHandler(new ChangeHandler() {
+ public void onChange(final ChangeEvent event) {
+ eventBus.fireEvent(new VersionChangeEvent());
+ doRefreshScripture();
+ }
+ });
+
+ eventBus.addHandler(ScriptureChangeEvent.TYPE, new ScriptureChangeEventHandler() {
+
+ public void onScriptureChange(final ScriptureChangeEvent event) {
+ Log.debug("Scripture Change event captured");
+ doRefreshScripture();
+ }
+ });
+
+ // TODO: this handler needs to be moved somewhere else, and fire off
+ // definition found
+ // TODO: given the handler name, our event bus, should be able to derive
+ // the type of it,
+ // since the type = Type<HandlerName>, at which point we can probably
+ // get rid of
+ // the type variable in the event.
+ // we would have to change the event to return the static type declared
+ // in the
+ // event handler
+
+ final LemmaClickedEventHandler lceh = new LemmaClickedEventHandler() {
+ public void onLemmaClicked(final LemmaClickedEvent lemmaClickedEvent) {
+ Log.error("Lemma Clicked event handler invoked");
+ highlightAllLemmas(lemmaClickedEvent.getLemma());
+ }
+
+ private void highlightAllLemmas(final List<String> lemmas) {
+ display.highlight(lemmas);
+ }
+ };
+ eventBus.addHandler(LemmaClickedEvent.TYPE, lceh);
+ }
+
+ @Override
+ protected void onPlaceRequest(final PlaceRequest request) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onUnbind() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ScriptureSelectorPresenter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ScriptureSelectorPresenter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/ScriptureSelectorPresenter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,160 @@
+package com.tyndalehouse.step.web.client.presenter;
+
+import java.util.Collection;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.presenter.client.DisplayCallback;
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.place.Place;
+import net.customware.gwt.presenter.client.place.PlaceRequest;
+import net.customware.gwt.presenter.client.widget.WidgetDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetPresenter;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.user.client.ui.HasValue;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.event.ScriptureChangeEvent;
+import com.tyndalehouse.step.web.shared.command.GetBibleBooksCommand;
+import com.tyndalehouse.step.web.shared.result.GetBibleBooksCommandResult;
+
+/**
+ * Presenter for the Scripture Selector Presenter module. This module aims to
+ * present the user with a way of selecting a passage, including suggesting the
+ * bible book.
+ *
+ * @author cjburrell
+ *
+ */
+public class ScriptureSelectorPresenter extends WidgetPresenter<ScriptureSelectorPresenter.Display> {
+ /**
+ * The contract with the view, which will disaply a way for the user to
+ * select/key in a bible reference
+ *
+ * @author cjburrell
+ *
+ */
+ public interface Display extends WidgetDisplay {
+ /**
+ * adds a suggestion to the list of bibles
+ *
+ * @param suggestion a suggestion, such as a bible book name
+ */
+ void addSuggestion(String suggestion);
+
+ /**
+ * Adds a list of suggestions
+ *
+ * @param suggestions the collection of suggestions (bible book names,
+ * for e.g.)
+ */
+ void addSuggestions(Collection<String> suggestions);
+
+ /**
+ * @return the reference which is currently keyed in
+ */
+ HasValue<String> getReference();
+
+ /**
+ * @return the handler for clicking on a search button
+ */
+ HasClickHandlers getSearch();
+
+ }
+
+ /**
+ * The default dispatcher to use to send requests to the server
+ */
+ private final DispatchAsync dispatcher;
+
+ /**
+ * Constructor to set up the timeline module
+ *
+ * @param display the view, passed in by Gin
+ * @param eventBus the event bus, passed in by Gin
+ * @param dispatcher the dispatcher, passed in by Gin
+ */
+ @Inject
+ public ScriptureSelectorPresenter(final Display display, final EventBus eventBus,
+ final DispatchAsync dispatcher) {
+ super(display, eventBus);
+
+ this.dispatcher = dispatcher;
+
+ Log.debug("ScriptureSelectorPresenter initialised");
+ bind();
+ }
+
+ /**
+ * @return the current reference as keyed in by the user.
+ */
+ public String getCurrentReference() {
+ return display.getReference().getValue();
+ }
+
+ @Override
+ public Place getPlace() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refreshDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void revealDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onBind() {
+ Log.debug("onBind called in ScriptureSelector");
+
+ dispatcher.execute(new GetBibleBooksCommand(), new DisplayCallback<GetBibleBooksCommandResult>(
+ display) {
+ @Override
+ protected void handleFailure(final Throwable e) {
+ // TODO Auto-generated method stub
+ Log.error("Unable to get books from server", e);
+ }
+
+ @Override
+ protected void handleSuccess(final GetBibleBooksCommandResult value) {
+ display.addSuggestions(value.getBooks());
+ }
+ });
+
+ display.getSearch().addClickHandler(new ClickHandler() {
+
+ public void onClick(final ClickEvent event) {
+ // can't use complicated classes here, as GWT java doesn't cope!
+ final String reference = display.getReference().getValue();
+ if (reference == null || reference.length() == 0) {
+ // return validation message perhaps? or ignore?
+ Log.error("No reference was provided, so no lookup can occur.");
+ return;
+ }
+
+ eventBus.fireEvent(new ScriptureChangeEvent(display.getReference().getValue()));
+ }
+ });
+
+ }
+
+ @Override
+ protected void onPlaceRequest(final PlaceRequest request) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onUnbind() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/StepPresenter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/StepPresenter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/StepPresenter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,139 @@
+package com.tyndalehouse.step.web.client.presenter;
+
+import java.util.List;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.presenter.client.DisplayCallback;
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.place.Place;
+import net.customware.gwt.presenter.client.place.PlaceRequest;
+import net.customware.gwt.presenter.client.widget.WidgetDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetPresenter;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.event.LemmaClickedEvent;
+import com.tyndalehouse.step.web.client.eventhandler.LemmaClickedEventHandler;
+import com.tyndalehouse.step.web.shared.command.GetDictionaryDefinitionCommand;
+import com.tyndalehouse.step.web.shared.result.GetDictionaryDefinitionResult;
+
+/**
+ * This is the main Presenter, when the view is created, all other presenters
+ * are created as a result.
+ *
+ * It acts as a singleton for each browser
+ *
+ * @author cjburrell
+ *
+ */
+public class StepPresenter extends WidgetPresenter<StepPresenter.Display> {
+ /**
+ * The contract with the Step View, the main layout of Step
+ *
+ * @author cjburrell
+ *
+ */
+ public interface Display extends WidgetDisplay {
+ }
+
+ /**
+ * the default dispatcher for async server requests
+ */
+ private final DispatchAsync dispatcher;
+
+ /**
+ * Constructor to set up the timeline module
+ *
+ * @param display the view, passed in by Gin
+ * @param eventBus the event bus, passed in by Gin
+ * @param dispatcher the dispatcher, passed in by Gin
+ */
+ @Inject
+ public StepPresenter(final Display display, final EventBus eventBus, final DispatchAsync dispatcher) {
+ super(display, eventBus);
+ this.dispatcher = dispatcher;
+
+ Log.debug("StepPresenter initialised");
+ bind();
+ }
+
+ @Override
+ public Place getPlace() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refreshDisplay() {
+ // TODO Auto-generated method stub
+ }
+
+ public void revealDisplay() {
+ // TODO Auto-generated method stub
+ }
+
+ /**
+ * adds event handlers when they need to be parsed only once, but multiple
+ * presenters may be interested this is a proxy. Typically an event should
+ * then be fired if necessary to the presenters
+ */
+ private void addSingletonEventHandlers() {
+ // TODO: this handler needs to be moved somewhere else, and fire off
+ // definition found
+ eventBus.addHandler(LemmaClickedEvent.TYPE, new LemmaClickedEventHandler() {
+
+ public void onLemmaClicked(final LemmaClickedEvent lemmaClickedEvent) {
+ Log.error("Lemma Clicked event handler invoked");
+ getLemmaDefinition(lemmaClickedEvent.getLemma());
+ }
+
+ private void getLemmaDefinition(final List<String> lemmaDefs) {
+ final GetDictionaryDefinitionCommand cmd = new GetDictionaryDefinitionCommand();
+ cmd.setLookupReference(lemmaDefs);
+
+ dispatcher.execute(cmd, new DisplayCallback<GetDictionaryDefinitionResult>(display) {
+ @Override
+ protected void handleFailure(final Throwable e) {
+ Log.error(e.getMessage());
+ }
+
+ @Override
+ protected void handleSuccess(final GetDictionaryDefinitionResult lemmaDefinition) {
+ Log.warn(lemmaDefinition.getXsltedDefinition());
+
+ // TODO: check whether definition came back alright!
+ // TODO: change the XSLT to something nicer
+ final PopupPanel popup = new PopupPanel();
+ popup.setWidget(new HTML(lemmaDefinition.getXsltedDefinition()));
+ popup.setAutoHideEnabled(true);
+ popup.show();
+
+ // scripture view doesn't need to know about this...
+ // TODO: remove DictionaryDefinitionFoundEvent and
+ // Handler
+ // eventBus.fireEvent(new
+ // DictionaryDefinitionFoundEvent(lemmaDefinition.getXsltedDefinition()));
+ }
+ });
+ }
+ });
+
+ }
+
+ @Override
+ protected void onBind() {
+ Log.debug("onBind called in STEP presenter");
+ addSingletonEventHandlers();
+ }
+
+ @Override
+ protected void onPlaceRequest(final PlaceRequest request) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ protected void onUnbind() {
+ // TODO Auto-generated method stub
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/TimebandListPresenter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/TimebandListPresenter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/TimebandListPresenter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,98 @@
+package com.tyndalehouse.step.web.client.presenter;
+
+import java.util.List;
+
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.place.Place;
+import net.customware.gwt.presenter.client.place.PlaceRequest;
+import net.customware.gwt.presenter.client.widget.WidgetDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetPresenter;
+
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.event.TimebandListUpdateRequiredEvent;
+import com.tyndalehouse.step.web.client.eventhandler.TimebandListUpdateRequiredEventHandler;
+import com.tyndalehouse.step.web.client.toolkit.timeline.helpers.CurrentBandStats;
+
+/**
+ * The TimebandList presenter is the presenter for the Timeband list module.
+ * This module is a list of items, each one representing one timeband. Each item
+ * contains the real-time statistics of what is displayed on the timeband,
+ * including the number of event and the number of events currently visible
+ *
+ * @author cjburrell
+ *
+ */
+// TODO: refactor to ensure events get captured and dealt with in the presenter,
+// rather than in the view.
+
+public class TimebandListPresenter extends WidgetPresenter<TimebandListPresenter.Display> {
+
+ /**
+ * Contract with any TimebandList view
+ *
+ * @author cjburrell
+ *
+ */
+ public interface Display extends WidgetDisplay {
+ /**
+ * This method updates the list displayed with the latest statistics
+ *
+ * @param stats statistics to be sent to the view for update
+ */
+ void updateList(List<CurrentBandStats> stats);
+ }
+
+ /**
+ * Default constructor, injected with Gin
+ *
+ * @param display the view, provided by Gin
+ * @param eventBus the event bus, provided by Gin
+ */
+ @Inject
+ public TimebandListPresenter(final TimebandListPresenter.Display display, final EventBus eventBus) {
+ super(display, eventBus);
+ bind();
+ }
+
+ @Override
+ protected void onBind() {
+ eventBus.addHandler(TimebandListUpdateRequiredEvent.TYPE,
+ new TimebandListUpdateRequiredEventHandler() {
+
+ public void onTimebandListRequiringUpdate(
+ final TimebandListUpdateRequiredEvent timebandListUpdateRequiredEvent) {
+ final List<CurrentBandStats> stats = timebandListUpdateRequiredEvent
+ .getTimelineStats();
+ display.updateList(stats);
+ }
+ });
+ }
+
+ @Override
+ public Place getPlace() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refreshDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void revealDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onPlaceRequest(final PlaceRequest request) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onUnbind() {
+ // TODO Auto-generated method stub
+
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/TimelinePresenter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/TimelinePresenter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/presenter/TimelinePresenter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,301 @@
+package com.tyndalehouse.step.web.client.presenter;
+
+import java.util.List;
+
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.presenter.client.DisplayCallback;
+import net.customware.gwt.presenter.client.EventBus;
+import net.customware.gwt.presenter.client.place.Place;
+import net.customware.gwt.presenter.client.place.PlaceRequest;
+import net.customware.gwt.presenter.client.widget.WidgetDisplay;
+import net.customware.gwt.presenter.client.widget.WidgetPresenter;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.event.ScriptureChangeEvent;
+import com.tyndalehouse.step.web.client.event.TimebandListUpdateRequiredEvent;
+import com.tyndalehouse.step.web.client.event.TimelineScrollEvent;
+import com.tyndalehouse.step.web.client.eventhandler.ScriptureChangeEventHandler;
+import com.tyndalehouse.step.web.client.eventhandler.TimelineScrollEventHandler;
+import com.tyndalehouse.step.web.client.toolkit.timeline.TimeEvent;
+import com.tyndalehouse.step.web.client.toolkit.timeline.Timeband;
+import com.tyndalehouse.step.web.client.toolkit.timeline.Timeline;
+import com.tyndalehouse.step.web.client.toolkit.timeline.components.TimelineConstants;
+import com.tyndalehouse.step.web.client.toolkit.timeline.exceptions.TimeBandNotFoundException;
+import com.tyndalehouse.step.web.shared.command.GetEventsForDateRangeCommand;
+import com.tyndalehouse.step.web.shared.command.GetTimelineOriginForScriptureCommand;
+import com.tyndalehouse.step.web.shared.command.GetTimelineUISetupCommand;
+import com.tyndalehouse.step.web.shared.common.timeline.TimeBandVisibleDate;
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineBean;
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineEventBean;
+import com.tyndalehouse.step.web.shared.result.GetEventsForDateRangeResult;
+import com.tyndalehouse.step.web.shared.result.GetTimelineOriginForScriptureResult;
+import com.tyndalehouse.step.web.shared.result.GetTimelineUISetupResult;
+import com.tyndalehouse.step.web.shared.timeline.Unit;
+
+/**
+ * TimelinePresenter is the presenter object for the Timeline module This is
+ * responsible for getting all the events from the server, firing changes across
+ * the event bus, if need be, repainting the timeline module, etc.
+ *
+ * @author cjburrell
+ *
+ */
+// TODO: timeline module needs refactoring quite a bit, since most of the logic
+// seems to be doing the view
+// as well, really ought to rewrite parts of it to remove the logic from the
+// display component
+public class TimelinePresenter extends WidgetPresenter<TimelinePresenter.Display> {
+ /**
+ * the view contract for the timeline module
+ *
+ * @author cjburrell
+ *
+ */
+ public interface Display extends WidgetDisplay {
+
+ /**
+ * @return the timeline module
+ */
+ Timeline getTimeline();
+
+ /**
+ * @return the zoom in Button
+ */
+ HasClickHandlers getZoomIn();
+
+ /**
+ * @return The zoom out button
+ */
+ HasClickHandlers getZoomOut();
+ }
+
+ /**
+ * The dispatcher for requests to the server
+ */
+ private final DispatchAsync dispatcher;
+
+ /**
+ * Constructor to set up the timeline module
+ *
+ * @param display the view, passed in by Gin
+ * @param eventBus the event bus, passed in by Gin
+ * @param dispatcher the dispatcher, passed in by Gin
+ */
+ @Inject
+ public TimelinePresenter(final Display display, final EventBus eventBus, final DispatchAsync dispatcher) {
+ super(display, eventBus);
+ this.dispatcher = dispatcher;
+
+ bind();
+ }
+
+ @Override
+ public Place getPlace() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refreshDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void revealDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * registers interest in @see {@link ScriptureChangeEvent}
+ */
+ private void addScriptureChangeHandler() {
+ eventBus.addHandler(ScriptureChangeEvent.TYPE, new ScriptureChangeEventHandler() {
+
+ public void onScriptureChange(final ScriptureChangeEvent event) {
+ Log.debug("Scripture Change event captured");
+
+ dispatcher.execute(new GetTimelineOriginForScriptureCommand(event.getNewReference()),
+ new DisplayCallback<GetTimelineOriginForScriptureResult>(display) {
+
+ @Override
+ protected void handleFailure(final Throwable e) {
+ Log.error("Failed to get timeline origin", e);
+ }
+
+ @Override
+ protected void handleSuccess(final GetTimelineOriginForScriptureResult value) {
+ if (!value.isEmpty()) {
+ final Timeline tl = display.getTimeline();
+ tl.repaint(value.getOriginDate(), value.getSuggestedTimeScale(), value
+ .getTimebandId());
+ // don't fire event to update list here,
+ // events haven't been requested yet!
+ }
+ // validation will be coped for elsewhere, in
+ // the relevant module, therefore do nothing at
+ // this stage
+ }
+
+ });
+
+ // so now we update the timeline, and we need to work out
+ // where to go.
+
+ }
+ });
+ }
+
+ /**
+ *
+ */
+ private void addScrollHandler() {
+ eventBus.addHandler(TimelineScrollEvent.TYPE, new TimelineScrollEventHandler() {
+ public void onScroll(final TimelineScrollEvent event) {
+ dispatcher.execute(new GetEventsForDateRangeCommand(event.getTimebandVisibleDates()),
+ new DisplayCallback<GetEventsForDateRangeResult>(display) {
+ @Override
+ protected void handleFailure(final Throwable e) {
+ Log.error("An error occurred while tyring to get events for the timeline", e);
+ }
+
+ // TODO: push this down in to timeline component?
+ @Override
+ protected void handleSuccess(final GetEventsForDateRangeResult resultingEvents) {
+ Log.debug("Request for events came back succesfully!");
+ Log.debug("Request was for " + event.getTimebandVisibleDates().size()
+ + " timebands.");
+
+ final List<TimelineEventBean> events = resultingEvents.getEvents();
+ final Timeline tl = getDisplay().getTimeline();
+
+ for (final TimelineEventBean ev : events) {
+ final int timebandId = ev.getTimelineId();
+
+ try {
+ final Timeband correctBand = tl.getBand(timebandId);
+ correctBand.addEvent(new TimeEvent(ev.getEventId(), ev.getName(), ev
+ .getFromDate(), ev.getToDate(), correctBand));
+ } catch (final TimeBandNotFoundException e) {
+ Log.debug("Could not find timeband");
+ }
+ }
+
+ // now that we've added something, we can notify
+ // the timebands that their minimum received
+ // windows are slightly more
+ // and also resize the bands too
+ for (final TimeBandVisibleDate tbvd : event.getTimebandVisibleDates()) {
+ try {
+ final Timeband tb = tl.getBand(tbvd.getTimebandId());
+ tb.adjustRequestedView(tbvd.getMinDate(), tbvd.getMaxDate());
+ tb.resizeBand();
+ } catch (final TimeBandNotFoundException e) {
+ // if for some reason the timeband has
+ // gone, we can but ignore
+ // the error
+ Log.error("Timeband " + tbvd.getTimebandId() + " cannot be found.");
+ }
+ }
+
+ eventBus.fireEvent(new TimebandListUpdateRequiredEvent(tl
+ .getCurrentBandStats()));
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * Adds zoom in and out handlers to the timeline module
+ */
+ private void addZoomHandlers() {
+ display.getZoomIn().addClickHandler(new ClickHandler() {
+
+ public void onClick(final ClickEvent event) {
+ // call zoom in on the timeline widget
+ display.getTimeline().zoomIn();
+ }
+ });
+
+ display.getZoomOut().addClickHandler(new ClickHandler() {
+
+ public void onClick(final ClickEvent event) {
+ // call zoom in on the timeline widget
+ display.getTimeline().zoomOut();
+ }
+ });
+ }
+
+ /**
+ * calling the server for the initial data setup
+ */
+ private void doInitialSetup() {
+ // TODO: this result can be cached quite successfully on the server
+ // (perhaps in the dispatch module
+ dispatcher.execute(new GetTimelineUISetupCommand(), new DisplayCallback<GetTimelineUISetupResult>(
+ display) {
+
+ @Override
+ protected void handleFailure(final Throwable e) {
+ Log.debug("Unable to initialise UI", e);
+ }
+
+ @Override
+ protected void handleSuccess(final GetTimelineUISetupResult setupData) {
+ Log.debug("Succesfully got timeline setup data");
+ setupTimeline(setupData);
+ }
+ });
+ }
+
+ @Override
+ protected void onBind() {
+ // TODO: all those anonymous classes make the code rather untidy... can
+ // we possible put all this somewhere else?
+ doInitialSetup();
+ addScrollHandler();
+ addZoomHandlers();
+ addScriptureChangeHandler();
+ }
+
+ @Override
+ protected void onPlaceRequest(final PlaceRequest request) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void onUnbind() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * sets up the timeline view, height, intial timebands, etc.
+ *
+ * @param setupData data returned from the server including all the
+ * timebands, and their units, etc.
+ */
+ protected void setupTimeline(final GetTimelineUISetupResult setupData) {
+ final Timeline timeline = display.getTimeline();
+
+ // copy across to UI widget
+ // we could avoid the copying here, since the timline bean
+ // is essentially what is needed, but nice to have it decoupled.
+ // TODO: change TimelineBean to be a TimebandBean
+ for (final TimelineBean tb : setupData.getTimelines()) {
+ final Timeband band = new Timeband(timeline, tb.getTimelineId(), tb.getTimelineDescription());
+
+ band.setPixelsPerUnit(TimelineConstants.DEFAULT_PIXELS_PER_UNIT);
+ Log.debug("Unit of band is: " + tb.getUnit());
+ band.setOriginalUnit(Unit.valueOf(tb.getUnit()));
+ band.setCurrentDate(TimelineConstants.INITIAL_DATE);
+ band.setCurrentDateX(TimelineConstants.TIMELINE_WIDTH);
+ timeline.addBand(band);
+ }
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/eventbus/StepEventBusImpl.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/eventbus/StepEventBusImpl.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/eventbus/StepEventBusImpl.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,23 @@
+package com.tyndalehouse.step.web.client.service.eventbus;
+
+import net.customware.gwt.presenter.client.DefaultEventBus;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.event.shared.GwtEvent;
+
+/**
+ * Default Step event bus to be used. Provides extra logging and in flight
+ * monitoring capability later
+ *
+ * @author cjburrell
+ *
+ */
+public class StepEventBusImpl extends DefaultEventBus {
+
+ @Override
+ public void fireEvent(final GwtEvent<?> event) {
+ Log.debug("StepEventBus:: firing event " + event.toDebugString());
+ super.fireEvent(event);
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/ModuleName.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/ModuleName.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/ModuleName.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,63 @@
+package com.tyndalehouse.step.web.client.service.refdata;
+
+/**
+ * Bean representing a module and its direct parent (if there is a hierarchy
+ *
+ * @author cjburrell
+ *
+ */
+public class ModuleName {
+ /**
+ * Module name
+ */
+ private String moduleName;
+
+ /**
+ * Parent if applicable of the module
+ */
+ private String parent;
+
+ /**
+ * Cosntructs a module with a given name and parent
+ *
+ * @param moduleName module name
+ * @param parent parent may be null
+ */
+ public ModuleName(final String moduleName, final String parent) {
+ this.moduleName = moduleName;
+
+ if (parent == null) {
+ this.parent = "Module";
+ } else {
+ this.parent = parent;
+ }
+ }
+
+ /**
+ * @return the moduleName
+ */
+ public String getModuleName() {
+ return moduleName;
+ }
+
+ /**
+ * @return the parent
+ */
+ public String getParent() {
+ return parent;
+ }
+
+ /**
+ * @param moduleName the moduleName to set
+ */
+ public void setModuleName(final String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ /**
+ * @param parent the parent to set
+ */
+ public void setParent(final String parent) {
+ this.parent = parent;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/ModuleRefData.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/ModuleRefData.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/service/refdata/ModuleRefData.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,100 @@
+package com.tyndalehouse.step.web.client.service.refdata;
+
+import java.util.ArrayList;
+import java.util.List;
+
+//TODO: remove singleton pattern and use @Singleton and Gin instead.
+/**
+ * Client side service to serve the reference data to the user
+ */
+// TODO: Ginify the singleton pattern
+public final class ModuleRefData {
+ /**
+ * This class is a singleton, so this is the unique private instance
+ */
+ private static ModuleRefData instance;
+
+ /**
+ * List of depths populating the Depth dropdown (level at which the user
+ * wants to see articles)
+ */
+ private final List<String> depths;
+
+ /**
+ * List of module names to be displayed in the drop downs
+ */
+ private final List<ModuleName> moduleNames;
+
+ /**
+ * Private constructor setting up all modules, and their hierarchies For
+ * e.g. People, Events and Eras come under History TODO: This needs
+ * internationalising
+ */
+ private ModuleRefData() {
+ moduleNames = new ArrayList<ModuleName>();
+
+ // no hashtable on client side...
+
+ // History Modules
+ moduleNames.add(new ModuleName("People", "History"));
+ moduleNames.add(new ModuleName("Events", "History"));
+ moduleNames.add(new ModuleName("Eras", "History"));
+
+ // Geography Modules
+ moduleNames.add(new ModuleName("Places", "Geography"));
+ moduleNames.add(new ModuleName("Maps", "Geography"));
+ moduleNames.add(new ModuleName("Google Maps", "Geography"));
+
+ // Main modules
+ // TODO: tidy up and send to paremeter files
+ moduleNames.add(new ModuleName("History", "Module"));
+ moduleNames.add(new ModuleName("Geography", "Module"));
+ moduleNames.add(new ModuleName("Language", "Module"));
+ moduleNames.add(new ModuleName("Parallels", "Module"));
+ moduleNames.add(new ModuleName("Translations", "Module"));
+ moduleNames.add(new ModuleName("Commentaries", "Module"));
+ moduleNames.add(new ModuleName("Publications", "Module"));
+ moduleNames.add(new ModuleName("Presentations", "Module"));
+
+ // DEPTHS
+ depths = new ArrayList<String>();
+ depths.add("Quick Look");
+ depths.add("Deep Study");
+ depths.add("Scholarly Details");
+ }
+
+ /**
+ * @return the instance
+ */
+ public static synchronized ModuleRefData getInstance() {
+ if (instance == null) {
+ instance = new ModuleRefData();
+ }
+
+ return instance;
+ }
+
+ /**
+ * @return the depths
+ */
+ public List<String> getDepths() {
+ return depths;
+ }
+
+ /**
+ * Returns a list of modules given a parent module
+ *
+ * @param parentModule parent module, or "Module" if none
+ * @return the list of available modules
+ */
+ public List<String> getListOfModules(final String parentModule) {
+ final List<String> subset = new ArrayList<String>();
+
+ for (final ModuleName mn : moduleNames) {
+ if (mn.getParent().equals(parentModule)) {
+ subset.add(mn.getModuleName());
+ }
+ }
+ return subset;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/HasSource.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/HasSource.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/HasSource.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,24 @@
+package com.tyndalehouse.step.web.client.toolkit;
+
+/**
+ * Indicates that the view (generally) has got a source, a dropdown list for
+ * e.g.) and can be set
+ *
+ * @author cjburrell
+ *
+ * @param <T> The type of data it is expecting
+ */
+public interface HasSource<T> {
+ /**
+ * Clears the source, i.e. resets to an empty list
+ */
+ void clearSource();
+
+ /**
+ * Settings the data
+ *
+ * @param source source of the data
+ */
+ void setSource(T source);
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/HtmlList.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/HtmlList.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/HtmlList.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,114 @@
+package com.tyndalehouse.step.web.client.toolkit;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.LIElement;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * A HTML list, taken partially from the web This can be ordered or unordered
+ *
+ * @author cjburrell
+ */
+public class HtmlList extends Widget {
+ /**
+ * Two types of list, ordered or undered
+ *
+ * @author cjburrell
+ *
+ */
+ public static enum ListType {
+ /**
+ * An ordered list
+ */
+ ORDERED {
+ /**
+ * Creates an UL element on the DOM
+ *
+ * @return the element created
+ */
+ @Override
+ public Element createElement() {
+ return Document.get().createOLElement();
+ }
+ },
+ /**
+ * An unordered list
+ */
+ UNORDERED {
+ /**
+ * Creates an UL element on the DOM
+ *
+ * @return the element created
+ */
+ @Override
+ public Element createElement() {
+ return Document.get().createULElement();
+ }
+ };
+
+ /**
+ * Creates an UL element on the DOM
+ *
+ * @return the element created
+ */
+ public abstract Element createElement();
+ }
+
+ /**
+ * list of items to be mapped in the list. And whether they should launch
+ * Commands on selected
+ */
+ private final Map<Element, Command> listItems = new HashMap<Element, Command>();
+
+ /**
+ * Constructor to create a HTML unordered or ordered list
+ *
+ * @param listType whether an ordered or unordered list should be created
+ */
+ public HtmlList(final ListType listType) {
+ setElement(listType.createElement());
+ setStylePrimaryName("html-list");
+ }
+
+ /**
+ * Adds an item to the HtmlList
+ *
+ * @param text the text next to the bullet/numbered point
+ * @param command the command to be executed if a user clicks on it
+ */
+ public void addItem(final String text, final Command command) {
+ final LIElement liElement = Document.get().createLIElement();
+ liElement.setInnerText(text);
+ getElement().appendChild(liElement);
+
+ listItems.put(liElement, command);
+
+ // All the events we're interested in
+ sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONCLICK);
+ }
+ //
+ // @Override
+ // public void onBrowserEvent(Event event) {
+ // switch(event.getTypeInt()) {
+ // case Event.ONCLICK:
+ // Element target = event.getTarget();
+ // if (listItems.containsKey(target))
+ // DeferredCommand.addCommand(listItems.get(target));
+ //
+ // break;
+ // case Event.ONMOUSEOUT:
+ // event.getTarget().setClassName(null);
+ // break;
+ //
+ // case Event.ONMOUSEOVER:
+ // event.getTarget().setClassName("highlightOn");
+ // break;
+ // }
+ // }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/SimpleListBox.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/SimpleListBox.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/SimpleListBox.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,27 @@
+package com.tyndalehouse.step.web.client.toolkit;
+
+import java.util.List;
+
+import com.google.gwt.user.client.ui.ListBox;
+
+/**
+ * An extension to the GWT ListBox, mainly to allow the setSource method
+ * exposure, and hide implementation details of the ListBox from the presenter
+ *
+ * @author cjburrell
+ *
+ */
+public class SimpleListBox extends ListBox implements HasSource<List<String>> {
+
+ public void clearSource() {
+ this.clear();
+
+ }
+
+ public void setSource(final List<String> source) {
+ clearSource();
+ for (final String key : source) {
+ addItem(key);
+ }
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/SourceListBox.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/SourceListBox.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/SourceListBox.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,28 @@
+package com.tyndalehouse.step.web.client.toolkit;
+
+import java.util.SortedMap;
+import java.util.Map.Entry;
+
+import com.google.gwt.user.client.ui.ListBox;
+
+/**
+ * Similar to @see {@link SimpleListBox}, but the source is given as a HashMap
+ *
+ * @author cjburrell
+ *
+ */
+public class SourceListBox extends ListBox implements HasSource<SortedMap<String, String>> {
+
+ public void clearSource() {
+ this.clear();
+
+ }
+
+ public void setSource(final SortedMap<String, String> source) {
+ clearSource();
+ for (final Entry<String, String> entry : source.entrySet()) {
+ addItem(entry.getValue(), entry.getKey());
+ }
+
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/ScriptureDisplayConstants.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/ScriptureDisplayConstants.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/ScriptureDisplayConstants.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,22 @@
+package com.tyndalehouse.step.web.client.toolkit.scripture;
+
+/**
+ * Scripture display module constants
+ *
+ * @author cjburrell
+ *
+ */
+public final class ScriptureDisplayConstants {
+
+ /**
+ * To emphasis text in the module, for e.g. when a user clicks on a word
+ */
+ public static final String EMPHASISE = "scripture-emphasise";
+
+ /**
+ * making constructor private
+ */
+ private ScriptureDisplayConstants() {
+
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/VerseLabel.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/VerseLabel.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/scripture/VerseLabel.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,132 @@
+package com.tyndalehouse.step.web.client.toolkit.scripture;
+
+import java.util.List;
+
+import net.customware.gwt.presenter.client.EventBus;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.tyndalehouse.step.web.client.event.LemmaClickedEvent;
+
+/**
+ * Composite wrapper around a portion of scriptural text. The wrapper contains
+ * data retrieved from the server such as lemmas (Strong numbers), morphological
+ * data and an alternative word in the case of an interlinear
+ *
+ * @author cjburrell
+ *
+ */
+public class VerseLabel extends Composite {
+ /**
+ * if there is an interlinear, then this is where the alternative word is
+ * stored
+ */
+ private Label alternativeWord;
+
+ /**
+ * TODO: this should be removed into the presenter the event bus to fire off
+ * events
+ */
+ private final EventBus eventBus;
+
+ /**
+ * Flow panel for display
+ */
+ private final FlowPanel fp;
+
+ /**
+ * List of Strong numbers associated to this portion of text
+ */
+ private List<String> lemmas;
+
+ /**
+ * The main word(s) to be displayed
+ */
+ private final Label mainWord;
+
+ /**
+ * list of morphs associated to this wrapper of text
+ */
+ private List<String> morphs;
+
+ /**
+ * This constructors initialises an instance of the composite wrapper and
+ * sets up the panel, css, etc.
+ *
+ * @param text the text to be wrapped
+ * @param eventBus the event bus if events are to be fired
+ */
+ public VerseLabel(final String text, final EventBus eventBus) {
+ fp = new FlowPanel();
+
+ // TODO: store all strings to do with css somewhere central
+ fp.setStyleName("scripture-interlinear");
+ initWidget(fp);
+
+ // main word display (from the version selected)
+ mainWord = new Label(text);
+ fp.add(mainWord);
+
+ this.eventBus = eventBus;
+ }
+
+ /**
+ * @return the lemma
+ */
+ public List<String> getLemma() {
+ return lemmas;
+ }
+
+ /**
+ * @return the morph
+ */
+ public List<String> getMorph() {
+ return morphs;
+ }
+
+ /**
+ * sets the alternative word. This could be a Hebrew word, but for a classic
+ * interlinear it could also be a English word, where the main word is the
+ * Hebrew
+ *
+ * @param originalWord an original word (for e.g. a hebrew translation)
+ */
+ public void setAlternativeWord(final String originalWord) {
+ if (alternativeWord != null) {
+ alternativeWord.setText(originalWord);
+ return;
+ }
+
+ alternativeWord = new Label(originalWord);
+ fp.add(alternativeWord);
+ }
+
+ /**
+ * @param lemma the lemma to set
+ */
+ public void setLemmas(final List<String> lemma) {
+ this.lemmas = lemma;
+
+ if (lemma != null) {
+ // add a click listener
+ mainWord.addClickHandler(new ClickHandler() {
+
+ public void onClick(final ClickEvent event) {
+ Log.debug("Firing event");
+ eventBus.fireEvent(new LemmaClickedEvent(lemma));
+ }
+ });
+ }
+ }
+
+ /**
+ * @param morph the morph to set
+ */
+ public void setMorphs(final List<String> morph) {
+ this.morphs = morph;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TapeTrack.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TapeTrack.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TapeTrack.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,111 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * A tape track is the track on which events are painted. The events are
+ * contained by the TimeBand as that's where they logically reside. However,
+ * they are painted on the timetracks.
+ *
+ * @author cjburrell
+ *
+ */
+public class TapeTrack extends Widget {
+ /**
+ * The following variable defines the earliest spot at which an event can be
+ * painted
+ */
+ private int earliestPaintOpportunity;
+
+ /**
+ * Determines whether the Tape Track is part of the DOM yet
+ */
+ private boolean isRendered;
+
+ /**
+ * The following spot defines the latest spot at which an event needs to be
+ * finished if it is to be painted on this track
+ */
+ private int latestPaintOpportunity;
+
+ /**
+ * Element on the DOM that is the track
+ */
+ private final Element track;
+
+ /**
+ * The default constructor initialises in memory a tape track. This includes
+ * setting up the div outside of the DOM, and setting the default earliest
+ * and latest opportunities for painting as Max and Min Integers hence
+ * allowing everything to be painted
+ */
+ public TapeTrack() {
+ isRendered = false;
+ track = DOM.createDiv();
+ track.setClassName("step-tape-track");
+ earliestPaintOpportunity = Integer.MAX_VALUE;
+ latestPaintOpportunity = Integer.MIN_VALUE;
+
+ setElement(track);
+ }
+
+ /**
+ * Checks and then adds an event to the timetrack Logically it is still
+ * added to the band, but it is painted on the timetrack
+ *
+ * @param event even to be painted
+ * @return whether the event has been painted
+ */
+ public boolean addEvent(final TimeEvent event) {
+ if (canPaintAt(event.getLeftPixelPosition(), event.getTotalWidth())) {
+ // Log.debug(event.getDescription() +
+ // " can be painted on timetrack");
+ event.paint(this);
+
+ // now update the available bands
+ // Log.debug("Old latest and earliest times were: " +
+ // latestPaintOpportunity + "," + earliestPaintOpportunity);
+ latestPaintOpportunity = Math.max(latestPaintOpportunity, event.getLeftPixelPosition()
+ + event.getTotalWidth());
+ earliestPaintOpportunity = Math.min(earliestPaintOpportunity, event.getLeftPixelPosition());
+ // Log.debug("New latest and earliest times were: " +
+ // latestPaintOpportunity + "," + earliestPaintOpportunity);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * The events need to be added in order, otherwise the time taping will not
+ * be efficient Returns whether an event of width width can be painted at
+ * position pixel
+ *
+ * @param pixel pixel position at which to be painted
+ * @param width width of the event
+ * @return true if the event can be painted
+ */
+ public boolean canPaintAt(final int pixel, final int width) {
+ return pixel > latestPaintOpportunity || (pixel + width + 1) < earliestPaintOpportunity;
+ }
+
+ /**
+ * @return the track
+ */
+ public Element getTrack() {
+ return track;
+ }
+
+ /**
+ * paints the timetrack on to the timeband
+ *
+ * @param band the band to be painteds
+ */
+ public void paint(final Timeband band) {
+ if (!isRendered) {
+ band.getBandDiv().appendChild(track);
+ isRendered = true;
+ }
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEvent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEvent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEvent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,396 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline;
+
+import com.extjs.gxt.ui.client.core.El;
+import com.extjs.gxt.ui.client.util.TextMetrics;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.tyndalehouse.step.web.client.toolkit.timeline.components.TimelineConstants;
+import com.tyndalehouse.step.web.client.toolkit.timeline.helpers.TimeConversionUtil;
+
+/**
+ * A time event, to be positioned on the screen
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimeEvent {
+
+ /**
+ * events can move from one timeband to another
+ */
+ private final Timeband currentTimeband;
+
+ /**
+ * description of the event
+ */
+ private String description;
+
+ /**
+ * If this event is a duration, this captures the width to be displayed
+ */
+ private int durationWidth;
+
+ /**
+ * The master div containing all the relevant DOM elements representing it
+ */
+ private Element eventDiv;
+
+ /**
+ * default to a standard event or duration we will drive this from the
+ * database
+ */
+ private String eventType;
+
+ /**
+ * The picture if appropriate, displaying the type of event
+ */
+ private Element icon;
+ /**
+ * id of the event
+ */
+ private int id;
+
+ /**
+ * whether the time event has been rendered on to the DOM yet
+ */
+ private boolean isRendered = false;
+
+ /**
+ * The label containing the text going with the event
+ */
+ private Element label;
+
+ /**
+ * The left-most position at which the event is located, in relation to the
+ * timeband
+ */
+ private int leftPixelPosition;
+ /**
+ * the end date of a duration event
+ */
+ private Long maxDate;
+
+ /**
+ * the date of the event, and if a duration, the start date
+ *
+ */
+ private Long minDate;
+
+ /**
+ * Show event text
+ */
+ private boolean showText;
+
+ /**
+ * A representation of the total width occupied by the event, including the
+ * text next to it. This is particularly important for events that are
+ * single point in time, where the text will be much wider than the icon
+ *
+ */
+ private int totalWidth;
+
+ /**
+ * The
+ *
+ * @param id id of the event
+ * @param description a description to be displayed
+ * @param minDate a minimum date
+ * @param maxDate a maximum date, optional, in case of single point in time
+ * events
+ * @param tb the timeband
+ */
+ public TimeEvent(final int id, final String description, final Long minDate, final Long maxDate,
+ final Timeband tb) {
+ this.id = id;
+ this.description = description;
+ this.minDate = minDate;
+ this.maxDate = maxDate;
+ this.currentTimeband = tb;
+
+ setupEventSpecificOptions();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final TimeEvent other = (TimeEvent) obj;
+ if (id != other.getId()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * returns the event div that is shown on the screen
+ *
+ * @return the eventDiv
+ */
+ public Element getEventDiv() {
+ return eventDiv;
+ }
+
+ /**
+ * @return the eventType
+ */
+ public String getEventType() {
+ return eventType;
+ }
+
+ /**
+ * @return the id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * @return the leftPixelPosition
+ */
+ public int getLeftPixelPosition() {
+ return leftPixelPosition;
+ }
+
+ /**
+ * @return the maxDate
+ */
+ public Long getMaxDate() {
+ return maxDate;
+ }
+
+ /**
+ * @return the minDate
+ */
+ public long getMinDate() {
+ return minDate;
+ }
+
+ /**
+ * @return the totalWidth
+ */
+ public int getTotalWidth() {
+ return totalWidth;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ return result;
+ }
+
+ /**
+ * returns whether this event is a duration or point in time event
+ *
+ * @return true if this is a duration event
+ */
+ public boolean isDuration() {
+ return maxDate == null;
+ }
+
+ /**
+ * @return the isRendered
+ */
+ public boolean isRendered() {
+ return isRendered;
+ }
+
+ /**
+ * @return the showText
+ */
+ public boolean isShowText() {
+ return showText;
+ }
+
+ /**
+ * the main responsible culprit for painting events on the timeband
+ *
+ * @param track the track on which the event will be painted
+ */
+ public void paint(final TapeTrack track) {
+ // all we do is attach it to the parent if need be.
+ if (!isRendered) {
+ setupDivProperties();
+ track.getTrack().appendChild(eventDiv);
+ isRendered = true;
+ }
+ }
+
+ /**
+ * ensures the event gets rendered next time paint() is called
+ */
+ public void reset() {
+ isRendered = false;
+
+ // also recalculate the times and dates of the events (perhaps this is
+ // not always necessary)
+ setupEventSpecificOptions(); // a few extra bits in there, but nothing
+ // that takes time
+ }
+
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ /**
+ * @param eventType the eventType to set
+ */
+ public void setEventType(final String eventType) {
+ this.eventType = eventType;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(final int id) {
+ this.id = id;
+ }
+
+ /**
+ * @param leftPixelPosition the leftPixelPosition to set
+ */
+ public void setLeftPixelPosition(final int leftPixelPosition) {
+ this.leftPixelPosition = leftPixelPosition;
+ }
+
+ /**
+ * @param maxDate the maxDate to set
+ */
+ public void setMaxDate(final long maxDate) {
+ this.maxDate = maxDate;
+ }
+
+ /**
+ * @param maxDate the maxDate to set
+ */
+ public void setMaxDate(final Long maxDate) {
+ this.maxDate = maxDate;
+ }
+
+ /**
+ * @param minDate the minDate to set
+ */
+ public void setMinDate(final long minDate) {
+ this.minDate = minDate;
+ }
+
+ /**
+ * @param minDate the minDate to set
+ */
+ public void setMinDate(final Long minDate) {
+ this.minDate = minDate;
+ }
+
+ /**
+ * @param showText the showText to set
+ */
+ public void setShowText(final boolean showText) {
+ this.showText = showText;
+ }
+
+ /**
+ * Creates all the elements/styles/etc.
+ */
+ private void setupDivProperties() {
+ eventDiv = DOM.createDiv();
+ icon = DOM.createDiv();
+ label = DOM.createDiv();
+ final El gxtEvent = new El(eventDiv);
+ final El gxtLabel = new El(label);
+
+ // setup div hierarchy
+ eventDiv.appendChild(icon);
+ eventDiv.appendChild(label);
+
+ // setup CSS properties
+ eventDiv.setClassName(TimelineConstants.EVENT);
+
+ // setup positioning
+ gxtEvent.setLeft(leftPixelPosition);
+
+ // setup values
+ label.setInnerText(description);
+
+ // specific properties
+ if (maxDate != null) {
+ setupDurationProperties();
+ } else {
+ setupPointInTimeProperties();
+ }
+
+ // all css is setup, take measurement of label element:
+
+ final TextMetrics ruler = TextMetrics.get();
+ ruler.bind(new El(label));
+ final int labelWidth = ruler.getWidth(description);
+ gxtLabel.setWidth(labelWidth);
+
+ // set up width: if event, then labelWidth, otherwise
+ // max(duration,label)
+ totalWidth = maxDate == null ? labelWidth : Math.max(durationWidth, labelWidth);
+ gxtEvent.setWidth(totalWidth);
+ }
+
+ /**
+ * Sets up duration properties
+ */
+ private void setupDurationProperties() {
+ final El gxtIcon = new El(icon);
+ final El gxtLabel = new El(label);
+ gxtIcon.setWidth(durationWidth);
+ gxtIcon.setStyleName(eventType, true);
+ gxtLabel.setStyleName(TimelineConstants.DURATION_LABEL, true);
+ }
+
+ /**
+ * Sets up properties and fields that depend on the type of event
+ */
+ private void setupEventSpecificOptions() {
+ this.leftPixelPosition = TimeConversionUtil.timeToPixel(minDate.longValue(), currentTimeband);
+ if (maxDate == null) {
+ // then it's a point in time
+ eventType = TimelineConstants.POINT_IN_TIME_EVENT;
+ } else {
+ eventType = TimelineConstants.DURATION;
+ durationWidth = Math.max(TimelineConstants.EVENT_MIN_WIDTH, TimeConversionUtil.timeToPixel(
+ maxDate.longValue(), currentTimeband)
+ - leftPixelPosition);
+ }
+ }
+
+ /**
+ * Sets up point in time properties
+ */
+ private void setupPointInTimeProperties() {
+ final El gxtLabel = new El(label);
+ gxtLabel.setStyleName(TimelineConstants.POINT_IN_TIME_LABEL, true);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEventDescriptor.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEventDescriptor.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeEventDescriptor.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,82 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline;
+
+import com.extjs.gxt.ui.client.core.El;
+import com.google.gwt.event.dom.client.MouseEvent;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.tyndalehouse.step.web.client.toolkit.timeline.components.TimelineConstants;
+
+/**
+ * There is only one TimeEvent descriptor for the timeline module. This is the
+ * hover over the time event on the timeline module. For e.g. a user might over
+ * a point in time event, and get a description of what/when it represents
+ *
+ * @author cjburrell
+ *
+ */
+public class TimeEventDescriptor {
+
+ /**
+ * DOM Element containing the time event description
+ */
+ private final Element div;
+
+ /**
+ * a wrapper (div) around the main element
+ */
+ private final El divWrapper;
+
+ /**
+ * The timeline component on which to draw the popup
+ */
+ private final Timeline timeline;
+
+ /**
+ * public constructor initialising the descriptor
+ *
+ * @param timeline the timeline on which the popup is to be displayed
+ */
+ public TimeEventDescriptor(final Timeline timeline) {
+ this.timeline = timeline;
+ div = DOM.createDiv();
+ divWrapper = new El(div);
+
+ divWrapper.setStyleName("step-timeline-time-event-descriptor");
+ divWrapper.setDisplayed(false);
+
+ // append to timeline component
+ timeline.getElement().appendChild(div);
+ }
+
+ /**
+ * @return the divWrapper
+ */
+ public El getDivWrapper() {
+ return divWrapper;
+ }
+
+ /**
+ * Hides the timeline
+ */
+ public void hide() {
+ getDivWrapper().setDisplayed(false);
+ }
+
+ /**
+ * Given a timed event, this shows the description in a div
+ *
+ * @param te the TimeEvent to be displayed
+ * @param me the mouse event that was triggered, contains details of pixel
+ * positions
+ */
+ public void show(final TimeEvent te, final MouseEvent<?> me) {
+ final El divWrapper = getDivWrapper();
+ divWrapper.setInnerHtml(te.getId() + " - " + te.getDescription());
+ divWrapper.setDisplayed(true);
+ // Log.debug("x: " + me.getX());
+ // Log.debug("y: " + me.getY());
+
+ divWrapper.setLeft(timeline.getAbsoluteLeft() + me.getX());
+ divWrapper.setTop(timeline.getAbsoluteTop() + me.getY() - TimelineConstants.SPACE_BELOW_POPUP);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeScale.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeScale.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/TimeScale.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,164 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline;
+
+import java.util.HashMap;
+
+import com.extjs.gxt.ui.client.core.El;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.tyndalehouse.step.web.client.toolkit.timeline.helpers.TimeConversionUtil;
+import com.tyndalehouse.step.web.shared.timeline.Unit;
+
+/**
+ * time scale, in charge of drawing the different columns on the timeband at
+ * various lengths, dependant on the uni of the timeband
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimeScale {
+ /**
+ * timeband on which the TimeScale resides
+ */
+ private final Timeband band;
+
+ /**
+ * true if time scale rendered
+ */
+ private boolean isRendered = false;
+
+ /**
+ * Maps of all timescales that have been drawn on the timeband
+ */
+ private final HashMap<Integer, Element> paintedTimescaleBands;
+
+ /**
+ * DOM element containing the scale columns
+ */
+ private Element scaleBand;
+
+ /**
+ * A timescale is attached to a timeband
+ *
+ * @param band timeband to attach the scale on
+ */
+ public TimeScale(final Timeband band) {
+ this.band = band;
+ paintedTimescaleBands = new HashMap<Integer, Element>();
+ }
+
+ /**
+ * this paints the timescale band on those bits that need painting...
+ */
+ public void paint() {
+ // check band is rendered, otherwise this is a waste of time
+ if (!band.isRendered()) {
+ return;
+ }
+
+ // if rendered already? skip!
+ if (!isRendered) {
+ scaleBand = DOM.createDiv();
+ paintedTimescaleBands.clear(); // reset in case we're in a zoom
+
+ final El gxtScaleBand = new El(scaleBand);
+ band.getBandDiv().appendChild(scaleBand);
+ gxtScaleBand.setStyleName("step-scale-band", true);
+ isRendered = true;
+ }
+
+ // finally render those bits that are visible only
+ paintVisibleScale();
+ }
+
+ /**
+ * The easy way is to get rid of everything and repaint The slightly more
+ * clever way is to actually repaint the existing dom elements. It uses more
+ * memory though, however, we can try both eventually if need be.
+ */
+ public void repaint() {
+ // remove oneself first
+ reset();
+ paint();
+ }
+
+ /**
+ * resets to redraw
+ */
+ public void reset() {
+ isRendered = false;
+ }
+
+ /**
+ * draws the segments on the TimeScale DOM element
+ *
+ * @param firstVisibleSegmentPixel first visible pixel, left most, of the
+ * band
+ * @param numberOfVisibleSegments number of segments to draw
+ */
+ private synchronized void drawSegments(final long firstVisibleSegmentPixel,
+ final long numberOfVisibleSegments) {
+ final El gxtScaleBand = new El(scaleBand);
+ final int pixelsPerUnit = band.getPixelsPerUnit();
+ int relativeLeft = (int) firstVisibleSegmentPixel;
+ // Log.debug("Drawing segments");
+ for (long ii = 0; ii < numberOfVisibleSegments + 1; ii++) {
+ // check segment not already drawn...
+ final Integer key = Integer.valueOf(relativeLeft);
+ final Integer keyMinus1 = Integer.valueOf(relativeLeft - 1);
+ final Integer keyPlus1 = Integer.valueOf(relativeLeft + 1);
+
+ // due to rounding errors, we need to check 1 below key and 1 above
+ // too
+ // TODO: instead of relying on time for drawing these, draw the
+ // first one,
+ // then rely on intervals. Saves computations for storage.
+ if (!paintedTimescaleBands.containsKey(key) && !paintedTimescaleBands.containsKey(keyPlus1)
+ && !paintedTimescaleBands.containsKey(keyMinus1)) {
+ final Element un = DOM.createDiv();
+ final El gxtUn = new El(un);
+ gxtUn.setWidth(pixelsPerUnit);
+
+ un.setInnerText(TimeConversionUtil.formatPixelToTime(relativeLeft, band));
+ gxtScaleBand.appendChild(un);
+
+ // set left position:
+ gxtUn.setLeft(relativeLeft);
+ gxtUn.setTop(0); // if this is laid out after events, then 0
+ // makes sure it lines up to the top
+ gxtUn.setHeight("100%");
+
+ paintedTimescaleBands.put(key, un);
+ }
+ // else {
+ // TODO: log should come in next
+ // Log.debug("Segment not drawn as already painted");
+ // }
+ relativeLeft += pixelsPerUnit;
+ }
+ }
+
+ /**
+ * paints the visible segments (columns) on to the band This method mainly
+ * sets up all the relevant mathematics, and passes down
+ */
+ private void paintVisibleScale() {
+ final long visibleLeft = band.getMinVisibleDate();
+ final long visibleRight = band.getMaxVisibleDate();
+
+ final Unit unit = band.getUnit();
+
+ // We do not want to generate all the time scale segments,
+ // the number of visible segments is number of time 'unit' is in the
+ // visible section
+ final long numberOfVisibleSegments = (visibleRight - visibleLeft) / unit.getMilliseconds();
+
+ // first visible segment is going to be located at
+ final long firstVisibleSegmentPixel = TimeConversionUtil.timeToPixel(visibleLeft
+ - (visibleLeft % unit.getMilliseconds()), band);
+
+ // TODO: uncomment all the debug statements and change global logging
+ // level to info
+ // Log.debug("Drawing segments for timeband" + band.getId());
+ drawSegments(firstVisibleSegmentPixel, numberOfVisibleSegments);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeband.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeband.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeband.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,952 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeMap;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.extjs.gxt.ui.client.core.El;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Widget;
+import com.tyndalehouse.step.web.client.toolkit.timeline.components.TimebandRequestWindow;
+import com.tyndalehouse.step.web.client.toolkit.timeline.components.TimelineConstants;
+import com.tyndalehouse.step.web.client.toolkit.timeline.exceptions.CannotDeleteEventException;
+import com.tyndalehouse.step.web.client.toolkit.timeline.exceptions.IncapableOfCalculatingRequestWindowException;
+import com.tyndalehouse.step.web.client.toolkit.timeline.helpers.TimeConversionUtil;
+import com.tyndalehouse.step.web.shared.common.timeline.TimeBandVisibleDate;
+import com.tyndalehouse.step.web.shared.timeline.Unit;
+
+/**
+ * The TimeBand object represents a section of the timeline that contains the
+ * events. There are many timebands on the timeline. Timebands contain
+ * TimeScales representing units as well as TapeTracks which contain the events
+ * The events are logically held on the Timeband, but painted on the time track.
+ *
+ * @author CJBurrell
+ */
+public class Timeband extends Widget {
+ /**
+ * The DOM element containing all timeband elements
+ */
+ private Element bandDiv;
+
+ /**
+ * The current date that is shown
+ */
+ private long currentDate;
+
+ /**
+ * The current pixel on the timeband representing the current date (above)
+ */
+ private long currentDateX = 0;
+
+ /**
+ * when this is set to true, then we can use the request window object to
+ * determine whether or not we are showing all the events we are able to If
+ * events can be deleted or moved to other timebands, it becomes difficult
+ * to work out what the request window should be.
+ */
+ private boolean deletionsDisabled = true;
+
+ /**
+ * The timeband description
+ */
+ private String description;
+
+ /**
+ * this contains all the events on the time band
+ */
+ private final TreeMap<Integer, TimeEvent> events;
+
+ /**
+ * Id of the timeband
+ */
+ private int id;
+
+ /**
+ * This indicates whether the band has been painted and is showing
+ */
+ private boolean isRendered = false;
+
+ /**
+ * whether the user is interested in this timeband or not
+ */
+ private boolean isUserInterested;
+
+ /**
+ * Max date that the timeband is expected to paint
+ */
+ private long maxDate;
+
+ /**
+ * Min date that the timeband is expected to paint
+ */
+ private long minDate;
+
+ /**
+ * The last recorded mouse position on the mouse down event
+ */
+ private int mouseDownScrollLeft;
+
+ /**
+ * original unit as set up before it was rendered for the first time This is
+ * used so that we can revert back to the original, recommended unit at
+ * point in time
+ */
+ private Unit originalUnit = null;
+
+ // TODO:Derive this from a properties file? somehow? or database?
+ /**
+ * this describes how much of a unit needs to be visible before calling back
+ * to the server
+ */
+ private double outstandingUnitFactor = TimelineConstants.MINIMUM_UNIT_PORTION_BEFORE_SERVER_CALL;
+
+ /**
+ * this is the parent widget Timeline object
+ */
+ private final Timeline parent;
+
+ /**
+ * Number of pixels to be shown per unit
+ */
+ private int pixelsPerUnit;
+
+ /**
+ * Each timeband is given a request window. This object is responsible of
+ * working out how much to request from the server, so as not to flood it
+ * with requests of stuff it already has
+ */
+ private TimebandRequestWindow requestWindow = null;
+
+ /**
+ * Whether or not to show the scale band
+ */
+ private boolean showScale = true;
+
+ /**
+ * The list of tape tracks on this timeband.
+ */
+ private final List<TapeTrack> tapeTracks;
+
+ /**
+ * The timeband container which contains the bandDiv
+ */
+ private final Element timebandContainer;
+
+ /**
+ * label of the timeband
+ */
+ private Element timebandLabel;
+
+ /**
+ * This is the timescale visible on the timeband drawing lines across the
+ * timebands for each unit
+ */
+ private TimeScale timescale;
+
+ /**
+ * Determines the unit of the timeband and how to convert from/to
+ * time/pixels
+ */
+ private Unit unit;
+
+ /**
+ * This determines how much of a zoom is applied. For example a factor of
+ * 0.25 changes the scale of 50 pixels per decade to (1 + 0.25) * 50 = 75
+ * pixels
+ */
+ private double zoomFactor = TimelineConstants.ZOOM_FACTOR;
+
+ /**
+ * To create a new timeband on the timeline
+ *
+ * @param parent the timeline on which it is to be created
+ * @param id the id of the timeband
+ * @param description its description
+ */
+ public Timeband(final Timeline parent, final int id, final String description) {
+ this.parent = parent;
+ this.id = id;
+ this.description = description;
+
+ // set up collections
+ events = new TreeMap<Integer, TimeEvent>();
+ tapeTracks = new ArrayList<TapeTrack>();
+
+ // set up page properties
+ bandDiv = DOM.createDiv();
+ timebandContainer = DOM.createDiv();
+ bandDiv.setClassName("step-timeband");
+ setElement(timebandContainer);
+ }
+
+ /**
+ * Adds an event to the timeband, and therefore on to a random timetack. The
+ * first available spot to minimize the space required. In particular this
+ * delegates to addEventToTapeTrack after checking the event is not already
+ * in our list of events
+ *
+ * @param event event to be added
+ */
+ public void addEvent(final TimeEvent event) {
+ // need to check the event isn't already in our list:
+ if (!events.containsKey(event.getId())) {
+ events.put(event.getId(), event);
+ addEventToTapeTrack(event);
+
+ // TODO: analyse this, but it is likely that it is not possible
+ // that the bit in the middle is redundant
+ if (isEventInVisibleSection(event)) {
+ Log.debug("Adding event to hidden band: " + event.getDescription());
+ addEventToTapeTrack(event);
+ }
+ // otherwise, autoHide is set to false, so leave hidden
+ }
+ }
+
+ /**
+ * This method is used to tell the Timeband that it now has all events
+ * within the section: (x1,x2). We can then use this to ensure subsequent
+ * requests don't request the same thing from the server, hence reducing
+ * load between the server and the client and also reducing the load on the
+ * server
+ *
+ * @param minDateRequested the minimum date that was requested and retrieved
+ * from the back-end
+ * @param maxDateRequested the maximum date that was requested and retrieved
+ * from the back-end
+ */
+ public void adjustRequestedView(final long minDateRequested, final long maxDateRequested) {
+ if (requestWindow == null) {
+ requestWindow = new TimebandRequestWindow(minDateRequested, maxDateRequested);
+ } else {
+ requestWindow.adjustRange(minDateRequested, maxDateRequested);
+ }
+ }
+
+ /**
+ * when a mousedown event has been captured, update the position at which
+ * the mouse was
+ *
+ * @param e the mousedown event
+ */
+ public void captureScrollLeft(final MouseDownEvent e) {
+ this.mouseDownScrollLeft = timebandContainer.getScrollLeft();
+ }
+
+ /**
+ * @return the bandDiv
+ */
+ public Element getBandDiv() {
+ return bandDiv;
+ }
+
+ /**
+ * @return the currentDate
+ */
+ public long getCurrentDate() {
+ return currentDate;
+ }
+
+ /**
+ * @return the currentDateX
+ */
+ public long getCurrentDateX() {
+ return currentDateX;
+ }
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @return the events
+ */
+ public TreeMap<Integer, TimeEvent> getEvents() {
+ return events;
+ }
+
+ /**
+ * @return the id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * @return the maxDate
+ */
+ public long getMaxDate() {
+ return maxDate;
+ }
+
+ /**
+ * returns the current maximum visible date on the band
+ *
+ * @return the maximum date visible on the band
+ */
+ public long getMaxVisibleDate() {
+ int realClientWidth = timebandContainer.getClientWidth();
+ // if this is not rendered properly yet, then we have no width:
+ if (realClientWidth == 0) {
+ // use the timeline width, perhaps we can take the parent width
+ // instead...
+ // this is important as it it could that the timline doesn't take
+ // the full width
+ realClientWidth = Window.getClientWidth();
+ }
+
+ return TimeConversionUtil.pixelToTime(timebandContainer.getScrollLeft() + realClientWidth, this);
+ }
+
+ /**
+ * @return the minDate, in pixels
+ */
+ public long getMinDate() {
+ return minDate;
+ }
+
+ /**
+ * returns the current minimum visible date on the band
+ *
+ * @return the minimum date visible on the band
+ */
+ public long getMinVisibleDate() {
+ return TimeConversionUtil.pixelToTime(timebandContainer.getScrollLeft(), this);
+ }
+
+ /**
+ * Could this be optimized by organising the events in time order, and on
+ * scroll recording which events have popped off?
+ *
+ * @return the number of visible events in the band
+ */
+ public int getNumberOfVisibleEvents() {
+ int count = 0;
+ for (final TimeEvent te : events.values()) {
+ if (isEventInVisibleSection(te)) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Works out how much of the timeband is to be requested Ideally we should
+ * TODO: this somewhere else.
+ *
+ * @return the visible section of the timeband
+ * @throws IncapableOfCalculatingRequestWindowException thrown if we are not
+ * in a position to calculate what the remaining section is.
+ */
+ public TimeBandVisibleDate getOustandingTimebandPeriod()
+ throws IncapableOfCalculatingRequestWindowException {
+ final long minVisibleDate = getMinVisibleDate();
+ final long maxVisibleDate = getMaxVisibleDate();
+ final long minimumDifference = (long) (unit.getMilliseconds() * outstandingUnitFactor);
+
+ // the new requested bit depends on our request window
+ if (requestWindow == null) {
+ return new TimeBandVisibleDate(id, minVisibleDate, maxVisibleDate);
+ } else {
+ // return only the portion that has changed (probably only one pixel
+ // worth)!
+ // -------|--------$------|-----$--------------------
+ // mvd mrd Mvd Mrd
+ final long minReceivedDate = requestWindow.getMinDate();
+ final long maxReceivedDate = requestWindow.getMaxDate();
+ final boolean shiftedLeft = minVisibleDate < minReceivedDate;
+ final boolean shiftedRight = maxVisibleDate > maxReceivedDate;
+
+ if (!shiftedLeft && !shiftedRight) {
+ return TimeBandVisibleDate.getNoRequest();
+ } else if (shiftedLeft && shiftedRight) {
+ // in this case, it was probably a zoom, and so we need to
+ // request both parts
+ return new TimeBandVisibleDate(id, minVisibleDate, maxVisibleDate);
+ } else if (shiftedLeft) {
+ // window could potentially have jumped, so there may be a gap
+ // between maxVisibleDate and min, so take so check that first:
+ if (maxVisibleDate < minReceivedDate) {
+ // we have issues here, as we're either going to have to
+ // remember about all the already painted stuff. this would
+ // potentially be troublesome
+ // as with units and zooming, we're going to have to
+ // eventually repaint huge amounts of stuff
+ // so reset to 0
+ requestWindow = null;
+
+ // TODO: investigate whether we want to clear the band down!
+ return new TimeBandVisibleDate(id, minVisibleDate, maxVisibleDate);
+ } else {
+ // the max is greater than the minimum so we return
+ if (minReceivedDate - minVisibleDate > minimumDifference) {
+ return new TimeBandVisibleDate(id, minVisibleDate, minReceivedDate);
+ } else {
+ return TimeBandVisibleDate.getNoRequest();
+ }
+ }
+ } else if (shiftedRight) {
+ // same problem as above if
+ if (minVisibleDate > maxReceivedDate) {
+ requestWindow = null;
+ return new TimeBandVisibleDate(id, minVisibleDate, maxVisibleDate);
+ } else {
+ // in particular check that the gap between maxReceivedDate
+ // and maxVisibleDate is enough
+ if (maxVisibleDate - maxReceivedDate > minimumDifference) {
+ return new TimeBandVisibleDate(id, maxReceivedDate, maxVisibleDate);
+ } else {
+ return TimeBandVisibleDate.getNoRequest();
+ }
+ }
+ } else {
+ throw new IncapableOfCalculatingRequestWindowException(minVisibleDate, maxVisibleDate,
+ minReceivedDate, maxReceivedDate);
+ }
+ }
+ }
+
+ /**
+ * @return the outstandingUnitFactor
+ */
+ public double getOutstandingUnitFactor() {
+ return outstandingUnitFactor;
+ }
+
+ /**
+ * @return the pixelsPerUnit
+ */
+ public int getPixelsPerUnit() {
+ return pixelsPerUnit;
+ }
+
+ /**
+ * returns a single event contained on the timeband
+ *
+ * @param eventId event id of the event
+ * @return the TimeEvent
+ */
+ public TimeEvent getSingleEvent(final String eventId) {
+ final Integer key = Integer.parseInt(eventId);
+ return events.get(key);
+ }
+
+ /**
+ * current number of tape tracks on the band. Also remember that one tape
+ * track is allocated at the top of the timeband to allow for dates to be
+ * displayed
+ *
+ * @return the numbers of tracks on the band
+ */
+ public int getSizeTapeTracks() {
+ return tapeTracks.size();
+ }
+
+ /**
+ * @return the unit
+ */
+ public Unit getUnit() {
+ return unit;
+ }
+
+ /**
+ * @return the zoomFactor
+ */
+ public double getZoomFactor() {
+ return zoomFactor;
+ }
+
+ /**
+ * Hides by setting the height of the band to 0
+ */
+ public void hideFromUser() {
+ // set height to 0 by default, and we'll add something later TODO: to
+ // see which bands have got events...
+ new El(timebandContainer).setHeight(0);
+ }
+
+ /**
+ * @return the deletionsDisabled
+ */
+ public boolean isDeletionsDisabled() {
+ return deletionsDisabled;
+ }
+
+ /**
+ * indicates whether the band has been rendered or not
+ *
+ * @return true if the band has been rendered
+ */
+ public boolean isRendered() {
+ return isRendered;
+ }
+
+ /**
+ * @return the showScale
+ */
+ public boolean isShowScale() {
+ return showScale;
+ }
+
+ /**
+ * @return the isUserInterested
+ */
+ public boolean isUserInterested() {
+ return isUserInterested;
+ }
+
+ /**
+ * Does not delete the events but redraws everything else.
+ */
+ public void redrawBand() {
+ tapeTracks.clear();
+
+ // use El to remove all children
+ new El(bandDiv).removeChildren();
+ resetAllEvents();
+
+ timescale.repaint();
+
+ requestWindow = null;
+
+ drawEvents();
+ }
+
+ /**
+ * Resets the timeband and redraws it
+ */
+ public void redrawEmptyBand() {
+ events.clear();
+ redrawBand();
+ }
+
+ /**
+ * true if the band is targetted from user input
+ *
+ * @param isUserInterested identifies whether a user is interested in the
+ * band
+ */
+ public void registerUserInterest(final boolean isUserInterested) {
+ this.isUserInterested = isUserInterested;
+ }
+
+ /**
+ * Removes an event from the band
+ *
+ * @param id the id of the event to be removed.
+ * @throws CannotDeleteEventException An event cannot be removed from a
+ * timeband.
+ */
+ public void removeEvent(final int id) throws CannotDeleteEventException {
+ if (deletionsDisabled) {
+ throw new CannotDeleteEventException("The event you are trying to delete (" + id
+ + ") is on band set on" + "deletionsDisabled = true");
+ }
+
+ events.remove(id);
+ // TODO: refresh the timeline dom
+ }
+
+ /**
+ * resets the band to use the original unit
+ */
+ public void resetOriginalUnit() {
+ setUnit(originalUnit);
+ }
+
+ /**
+ * Resizes bands dependant on how many bands are present.
+ */
+ public void resizeBand() {
+ if (isUserInterested) {
+ // resize the timeband to take account of the number of timetracks
+ new El(timebandContainer).setHeight(tapeTracks.size() * TimelineConstants.TAPE_TRACK_HEIGHT);
+ }
+ }
+
+ /**
+ * Gets the band to scroll to the current date
+ */
+ public void scrollToCurrentDate() {
+ Log.debug("Client width /2 : " + (timebandContainer.getClientWidth() / 2));
+ new El(timebandContainer)
+ .setScrollLeft((int) currentDateX - (timebandContainer.getClientWidth() / 2));
+ displayTimebandLabel();
+ }
+
+ /**
+ * @param bandDiv the bandDiv to set
+ */
+ public final void setBandDiv(final Element bandDiv) {
+ this.bandDiv = bandDiv;
+ }
+
+ /**
+ * resetting the current date...
+ *
+ * @param currentDate the date on which the timeband is rooted
+ */
+ public void setCurrentDate(final long currentDate) {
+ this.currentDate = currentDate;
+
+ // if we're changing the date, then everything on the band is going to
+ // be wrong, so
+ // get rid of it...
+
+ }
+
+ /**
+ * @param currentDateX the currentDateX to set
+ */
+ public void setCurrentDateX(final long currentDateX) {
+ this.currentDateX = currentDateX;
+ }
+
+ /**
+ * @param deletionsDisabled the deletionsDisabled to set
+ */
+ public void setDeletionsDisabled(final boolean deletionsDisabled) {
+ this.deletionsDisabled = deletionsDisabled;
+ }
+
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(final int id) {
+ this.id = id;
+ }
+
+ /**
+ * @param maxDate the maxDate to set
+ */
+ public void setMaxDate(final long maxDate) {
+ this.maxDate = maxDate;
+ }
+
+ /**
+ * @param minDate the minDate to set
+ */
+ public void setMinDate(final long minDate) {
+ this.minDate = minDate;
+ }
+
+ /**
+ * Usuall, the first call ever to set the unit of the timeband. The original
+ * unit gets cached in the originalUnit field For other uses, use @see
+ * {@link Timeband.setUnit} If not set, then it gets set. Otherwise a
+ * warning if produced
+ *
+ * @param unit unit to be associated with the timeband
+ */
+ public void setOriginalUnit(final Unit unit) {
+ if (originalUnit == null) {
+ originalUnit = unit;
+ } else {
+ Log.warn("Original unit is already set. Please use resetOriginalUnit instead");
+ }
+ resetOriginalUnit();
+ }
+
+ /**
+ * @param outstandingUnitFactor the outstandingUnitFactor to set
+ */
+ public void setOutstandingUnitFactor(final double outstandingUnitFactor) {
+ this.outstandingUnitFactor = outstandingUnitFactor;
+ }
+
+ /**
+ * @param pixelsPerUnit the pixelsPerUnit to set
+ */
+ public void setPixelsPerUnit(final int pixelsPerUnit) {
+ this.pixelsPerUnit = pixelsPerUnit;
+ }
+
+ /**
+ * sets the new position of the window, when the user is moving it
+ *
+ * @param previousClientX the previousPosition on the x axis
+ * @param newClientX the new position where it should be moved
+ * @param defaultUnit the default unit which should be used to calculate the
+ * time difference
+ * @param defaultPixelsPerUnit the default number of pixels per unit
+ */
+ public void setScrollLeft(final int previousClientX, final int newClientX, final Unit defaultUnit,
+ final int defaultPixelsPerUnit) {
+ // we scroll, but we calculate the unit/scale factor first
+ // say default is 1 Year
+ // this one is 10 years
+ // unit Factor = 0.1 so we scroll 10 times less pixels
+ final double unitFactor = (double) defaultUnit.getMilliseconds() / (double) unit.getMilliseconds();
+
+ // now say instead unit factor is 1, ie. the same unit, but different
+ // number of pixels
+ // default is 50 pixels per year, this one is 25 pixels a year
+ // so we want to scroll half
+ final double pixelFactor = (double) pixelsPerUnit / (double) defaultPixelsPerUnit;
+ final double xAxisDiff = (previousClientX - newClientX) * (unitFactor * pixelFactor);
+ final int newScrollLeft = (int) (mouseDownScrollLeft + xAxisDiff);
+ this.timebandContainer.setScrollLeft(newScrollLeft);
+ displayTimebandLabel();
+ }
+
+ /**
+ * @param showScale the showScale to set
+ */
+ public void setShowScale(final boolean showScale) {
+ this.showScale = showScale;
+ }
+
+ /**
+ * @param unit the unit to set
+ */
+ public void setUnit(final Unit unit) {
+ this.unit = unit;
+ }
+
+ /**
+ * @param zoomFactor the zoomFactor to set
+ */
+ public void setZoomFactor(final double zoomFactor) {
+ this.zoomFactor = zoomFactor;
+ }
+
+ /**
+ * Zooms in
+ */
+ public void zoomIn() {
+ zoom(1 + zoomFactor);
+ }
+
+ /**
+ * The way zooming works is that we recalculate the positions of all events
+ * on the timeline
+ */
+ public void zoomOut() {
+ // first change the zoom factor, then repaint events, and the timescale
+ // lets just assume a default zoom factor for now
+ // TODO: zoom in factor to be parameterised
+ zoom(1 - zoomFactor);
+
+ }
+
+ /**
+ * Adds an event to the tape track. This ensures that the event has not
+ * already been rendered If so, then it is present somewhere, perhaps not on
+ * this band though. Then, iterates through the tape tracks trying to add
+ * the event (i.e. asking each track whether there is space for the icon and
+ * the text to be added)
+ *
+ * @param event event to be added to the tape track
+ */
+ private void addEventToTapeTrack(final TimeEvent event) {
+ int startIndex = showScale ? 1 : 0; // leaving room for the scale band
+
+ // if event is added already, then exit
+ if (event.isRendered()) {
+ return;
+ }
+
+ while (startIndex < tapeTracks.size()) {
+ // Log.debug("Trying to add " + event.getDescription() +
+ // " to track " + startIndex);
+ // try and add event to track
+ if (tapeTracks.get(startIndex).addEvent(event)) {
+ return;
+ }
+ startIndex++;
+ }
+
+ // Log.debug("Going to create a new tape track");
+
+ // check that the event was added, otherwise add timetrack
+ if (startIndex >= tapeTracks.size()) {
+ // did not manage to add it to tracks. therefore, let's add another
+ // one:
+ final TapeTrack t = addNewTapeTrack();
+ t.addEvent(event);
+ }
+ }
+
+ /**
+ * Adds the timeband label to the band
+ */
+ private void addLabelToBand() {
+ timebandLabel = DOM.createDiv();
+ final El gxtTimebandLabel = new El(timebandLabel);
+ gxtTimebandLabel.setStyleName("step-timeband-label", true);
+ gxtTimebandLabel.setLeft(getElement().getScrollLeft());
+ timebandLabel.setInnerText(description + "(" + id + ")");
+ timebandContainer.appendChild(timebandLabel);
+
+ }
+
+ /**
+ * adds a new tape track to the timeband. The TapeTrack gets rendered at the
+ * same time
+ *
+ * @return the TapeTrack that was added
+ */
+ private TapeTrack addNewTapeTrack() {
+ final TapeTrack t = new TapeTrack();
+ tapeTracks.add(t);
+ t.paint(this);
+ return t;
+ }
+
+ /**
+ * TODO: The idea is to adjust depending on how many pixels constitutes a
+ * unit so that we can easily zoom in and out and have the units repainted
+ * properly
+ */
+ private void adjustUnit() {
+
+ }
+
+ /**
+ * Displays the timeband label on the timeband, with the description of it
+ */
+ private void displayTimebandLabel() {
+ new El(timebandLabel).setLeft(getElement().getScrollLeft());
+ }
+
+ /**
+ * Draws event onto the band
+ */
+ private void drawEvents() {
+ // get the events to paint themselves (they will decide whether or not
+ // to
+ // paint if they are already showing...
+ for (final TimeEvent te : events.values()) {
+ addEventToTapeTrack(te);
+ }
+ }
+
+ /**
+ * Tells the caller whether the event is in the visible section of the div
+ * on the browser.
+ *
+ * @param event the event to be tested
+ * @return true if the event is in the visible section
+ */
+ private boolean isEventInVisibleSection(final TimeEvent event) {
+ final Long eventMinDate = event.getMinDate();
+ final Long eventMaxDate = event.getMaxDate(); // eventMaxDate can be
+ // null
+ final long minVisibleDate = getMinVisibleDate();
+ final long maxVisibleDate = getMaxVisibleDate();
+
+ // output compare option:
+ // DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy G");
+
+ // Log.debug("Comparing ev(" +
+ // dtf.format(new Date(eventMinDate)) + "," +
+ // dtf.format(new Date(eventMaxDate)) + ") " +
+ // "to band(" +
+ // dtf.format(new Date(minVisibleDate)) + "," +
+ // dtf.format(new Date(maxVisibleDate)) + ")");
+
+ if ((eventMinDate >= minVisibleDate && eventMinDate <= maxVisibleDate)
+ || (eventMaxDate != null && eventMaxDate >= minVisibleDate && eventMaxDate <= maxVisibleDate)
+ || (eventMaxDate != null && eventMinDate <= minVisibleDate && eventMaxDate >= maxVisibleDate)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Resets the rendered status on all events
+ */
+ private void resetAllEvents() {
+ for (final TimeEvent te : events.values()) {
+ te.reset();
+ }
+ }
+
+ /**
+ * Zooms out given a ratio
+ *
+ * @param zoomRatio the given ratio to zoom in and out
+ */
+ private void zoom(final double zoomRatio) {
+ // TODO: somehow start with those events in the window (although for
+ // zoomout, won't make a different
+ // first change the scale
+ pixelsPerUnit *= zoomRatio;
+ adjustUnit();
+ redrawBand();
+ }
+
+ /**
+ * adds the band to the DOM
+ */
+ protected void addBandToUI() {
+ final El el = new El(timebandContainer);
+ final El gxtBandDiv = new El(bandDiv);
+
+ // set display options, ie. auto hide
+ // if (autoHide && !hasVisibleEvents()) {
+ // el.setDisplayed(false);
+ // }
+
+ parent.getTimelineContainer().appendChild(timebandContainer);
+ timebandContainer.appendChild(bandDiv);
+ addLabelToBand();
+
+ el.setStyleName("step-timeband-container");
+ gxtBandDiv.setHeight("100%");
+ gxtBandDiv.setTop(0);
+ }
+
+ /**
+ * Repaints the timeband
+ *
+ * @param top
+ */
+ protected void paint() {
+ // Log.debug("Request to paint band id:" + getId() + " Current date: " +
+ // getCurrentDate() + " Desc:" + getDescription());
+ if (!isRendered) {
+ addBandToUI();
+ isRendered = true;
+ }
+
+ // show scale band?
+ if (showScale) {
+ // check if default time track has been added and add if not
+ if (tapeTracks.size() == 0) {
+ addNewTapeTrack();
+ }
+
+ if (timescale == null) {
+ timescale = new TimeScale(this);
+ }
+ timescale.paint();
+ }
+
+ drawEvents();
+
+ if (isUserInterested) {
+ // after adding events, call the resizing function.
+ // It decides whether or not the band needs resizing, so no overhead
+ resizeBand();
+ } else {
+ hideFromUser();
+ }
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeline.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeline.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/Timeline.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,564 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.customware.gwt.presenter.client.EventBus;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.extjs.gxt.ui.client.core.El;
+import com.google.gwt.dom.client.EventTarget;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseEvent;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.Widget;
+import com.tyndalehouse.step.web.client.event.TimebandListUpdateRequiredEvent;
+import com.tyndalehouse.step.web.client.event.TimelineScrollEvent;
+import com.tyndalehouse.step.web.client.event.UserInterestInBandEvent;
+import com.tyndalehouse.step.web.client.eventhandler.UserInterestInBandEventHandler;
+import com.tyndalehouse.step.web.client.toolkit.timeline.components.TimelineConstants;
+import com.tyndalehouse.step.web.client.toolkit.timeline.events.TimelineMouseHandler;
+import com.tyndalehouse.step.web.client.toolkit.timeline.exceptions.IncapableOfCalculatingRequestWindowException;
+import com.tyndalehouse.step.web.client.toolkit.timeline.exceptions.TimeBandNotFoundException;
+import com.tyndalehouse.step.web.client.toolkit.timeline.exceptions.UnknownFiredElement;
+import com.tyndalehouse.step.web.client.toolkit.timeline.helpers.CurrentBandStats;
+import com.tyndalehouse.step.web.shared.common.timeline.TimeBandVisibleDate;
+import com.tyndalehouse.step.web.shared.timeline.Unit;
+
+/**
+ * FEATURE: Add uncertain times from database as dotted events/bands FEATURE:
+ * Add red line down the middle as current Sync line that tells user where bands
+ * are sunk FEATURE: Proper descriptions appearing in hover popups FEATURE: Add
+ * support for timetagging, history links, so that user can copy and paste url
+ * BUG: Fix obvious units that are wrong BUG: Timeline doesn't render properly
+ * when stuff is cached
+ *
+ *
+ * div .step-timeline (step-grab step-letgo) | | - div .step-timeline-container
+ * | | - div .step-timeband-container | | - div .step-timeband | | - div .
+ * step-scale-band
+ *
+ * @author CJBurrell
+ *
+ */
+public class Timeline extends Widget {
+
+ /**
+ * Client X records the last X-axis mouse position
+ */
+ private int clientX;
+
+ /**
+ * Map of hover over popups that describe an event
+ */
+ private final TimeEventDescriptor descriptor;
+
+ /**
+ * keeps track of whether the mouse button is up or down
+ */
+ private boolean downStatus;
+
+ /**
+ * The event bus on which to fire events
+ */
+ private final EventBus eventBus;
+
+ /**
+ * the current height of the timeline module
+ */
+ private int height;
+
+ /**
+ * whether the timeline is displayed horizontally or vertically (vertically
+ * is not currently supported)
+ */
+ private boolean isHorizontal;
+
+ /**
+ * whether the timeline module has been rendered
+ */
+ private boolean isRendered = false;
+
+ /**
+ * The list of timebands
+ */
+ private final List<Timeband> timebands;
+
+ /**
+ * The container for the timeline module, a DOM element wrapping the whole
+ * lot this is for styling and makes it easier
+ */
+ private final Element timelineContainer;
+
+ /**
+ * the timeline div, in which everything gets done.
+ */
+ private final Element timelineDiv;
+
+ /**
+ * The current width of the timeline module when rendered
+ */
+ private int width;
+
+ /**
+ * Default constructor
+ *
+ * @param eventBus the event bus to fire events on
+ */
+ public Timeline(final EventBus eventBus) {
+ this.eventBus = eventBus;
+ timebands = new ArrayList<Timeband>();
+
+ timelineContainer = DOM.createDiv();
+ timelineContainer.setClassName("step-timeline-container");
+
+ timelineDiv = DOM.createDiv();
+ timelineDiv.setClassName("step-timeline");
+ setElement(timelineDiv);
+
+ // set up hover over
+ descriptor = new TimeEventDescriptor(this);
+
+ paint();
+ addEventHandlers(eventBus);
+ disableSelection(getElement());
+ }
+
+ /**
+ * Adds a band to a timeline module
+ *
+ * @param band the timeband to be added
+ */
+ public synchronized void addBand(final Timeband band) {
+ timebands.add(band);
+ band.paint();
+ }
+
+ /**
+ * Both on load and on scroll we are doing an awful lot of looping to
+ * repaint just in case TODO: change this perhaps with a stack of repainting
+ * needed to ensure that we only repaint those timebands that think they
+ * need repainting. for example, we don't need to be repainting the whole
+ * band for one event etc.
+ */
+ public void fireTimelineScrollEvent() {
+ final TimelineScrollEvent tse = new TimelineScrollEvent();
+
+ // calculate only those bits that need requesting! but at the same time
+ // we don't need to wait for the server to redraw timebands
+ for (final Timeband tb : timebands) {
+ try {
+ tb.paint(); // the timeband is rendered, and there are no new
+ // events,
+ // so apart from looping through the events which are already
+ // rendered
+ // we are only repainting the timescale
+
+ final TimeBandVisibleDate tvd = tb.getOustandingTimebandPeriod();
+ Log.debug("firing scroll " + tb.getDescription() + " " + tvd.getMinDate() + ","
+ + tvd.getMaxDate());
+ tse.addTimebandVisibleDate(tvd);
+ } catch (final IncapableOfCalculatingRequestWindowException e) {
+ Log.error("Incapable of calculating request window", e);
+ }
+ }
+
+ // check we have something to fire
+ if (tse.getTimebandVisibleDates().size() != 0) {
+ eventBus.fireEvent(tse);
+ } else {
+ // this is fired after the scroll has got the events,
+ // but in this case we're not event firing
+ // the event, so should update the stats, since the visible view has
+ // changed
+ eventBus.fireEvent(new TimebandListUpdateRequiredEvent(getCurrentBandStats()));
+ }
+ }
+
+ /**
+ * returns a band to the caller based on the band id
+ *
+ * @param bandId the band id of the band to be returned
+ * @return the relevant timeband
+ * @throws TimeBandNotFoundException thrown if bandId is not part of this
+ * timeline module
+ */
+ public Timeband getBand(final int bandId) throws TimeBandNotFoundException {
+ // do a linear search - we're not going to have lots of timebands
+ for (final Timeband t : timebands) {
+ if (t.getId() == bandId) {
+ return t;
+ }
+ }
+
+ throw new TimeBandNotFoundException("Timeband " + bandId + " was not found.");
+ }
+
+ /**
+ * Returns the number of bands to the caller
+ *
+ * @return the number of bands on the timeline module
+ */
+ public int getBandCount() {
+ return timebands.size();
+ }
+
+ /**
+ * returns the list of the timeband. This is rather dangerous, and probably
+ * should be protected
+ *
+ * @return the list of timebands
+ */
+ public List<Timeband> getBands() {
+ return timebands;
+ }
+
+ /**
+ * returns the stats for all timebands to the caller
+ *
+ * @return a list containing lots of @see {@link CurrentBandStats}
+ */
+ public List<CurrentBandStats> getCurrentBandStats() {
+ final List<CurrentBandStats> stats = new ArrayList<CurrentBandStats>();
+ for (final Timeband band : timebands) {
+
+ final CurrentBandStats bandStats = new CurrentBandStats(band.getId(), band.getDescription(), band
+ .getEvents().size(), band.getNumberOfVisibleEvents(), band.isUserInterested());
+ stats.add(bandStats);
+ }
+
+ return stats;
+ }
+
+ /**
+ * @return the height
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * @return the timelineContainer
+ */
+ public Element getTimelineContainer() {
+ return timelineContainer;
+ }
+
+ /**
+ * @return the width
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * handles the mouse event, by alerting all the various bands to capture the
+ * position of the mouse on them
+ *
+ * @param e mouse event
+ */
+ public void handle(final MouseDownEvent e) {
+ downStatus = true;
+ clientX = e.getClientX();
+
+ // capture scrollLeft on every timeband
+ for (final Timeband tb : timebands) {
+ tb.captureScrollLeft(e);
+ }
+
+ // Log.debug("ClientX " + clientX);
+
+ // change cursor to hand grab
+ new El(timelineDiv).setStyleName("step-grab", true);
+
+ // cursor: hand; /* ? */ TODO
+ }
+
+ /**
+ * handles a move of the mouse, Ensures we know what timeband has been fired
+ * then if the mouse is down, then tells timebands to move across else,
+ * perhaps we're mouse hovering over something, and a popup needs to be
+ * shown
+ *
+ * @param e the mouse move event
+ */
+ public void handle(final MouseMoveEvent e) {
+ if (timebands.size() != 0) {
+ Timeband firedBand;
+ try {
+ firedBand = getFiredBand(e);
+ } catch (final UnknownFiredElement e1) {
+ Log.warn("Unknown element was fired");
+ firedBand = timebands.get(0);
+ }
+
+ final Unit unit = firedBand.getUnit();
+ final int pixelsPerUnit = firedBand.getPixelsPerUnit();
+
+ if (downStatus) {
+ // mouse is down so move the scroll bars on each timeband
+ // for each timeband, scroll a certain amount... This amount
+ // though
+ // is relative to the scales
+ // at the same time we want to add some new scroll visible event
+ // to
+ // allow service layer to update
+ // the events shown if necessary on each timeband
+ for (final Timeband tb : timebands) {
+ tb.setScrollLeft(clientX, e.getClientX(), unit, pixelsPerUnit);
+ // Log.debug("About to scroll: " + (clientX -
+ // e.getClientX()));
+ }
+
+ // fire the event and let presenter decide how much of the event
+ // needs to be passed back to the server...
+ // TODO: this needs to be fired also in the case of window
+ // resizing events
+ fireTimelineScrollEvent();
+ } else {
+ handleMouseOverTimeEvent(e);
+ }
+ }
+ // ignore if no timebands, as it is not fully rendered
+ }
+
+ /**
+ * Sets the down status to false, simulating a mouse up, recording whether
+ * the mouse is up or down, to false
+ *
+ * @param event mouse out event
+ */
+ public void handle(final MouseOutEvent event) {
+ downStatus = false;
+ }
+
+ /**
+ * on mouse over event, we call handleMouseOverTimeEvent to work out which
+ * TimeEvent fired the event if at all
+ *
+ * @param e mouse over event
+ */
+ public void handle(final MouseOverEvent e) {
+ handleMouseOverTimeEvent(e);
+ }
+
+ /**
+ * on mouse up, we set the down status to false, and update the mouse icon
+ *
+ * @param e mouse up event
+ */
+ public void handle(final MouseUpEvent e) {
+ downStatus = false;
+ new El(timelineDiv).setStyleName("step-letgo", true);
+ }
+
+ /**
+ * handles the display or remove of the popup An awful lot of events are
+ * going to fired and captured and discarded and one wonders if this is
+ * really the best way to do it
+ *
+ * @param e move over event
+ */
+ public void handleMouseOverTimeEvent(final MouseEvent<?> e) {
+ final EventTarget et = e.getNativeEvent().getEventTarget();
+ final Element targetElement = et.cast();
+
+ // find out if moved over event:
+ // Log.debug("Scanning " + timebands.size() + " timebands");
+ for (final Timeband band : timebands) {
+ // Log.debug("Scanning " + band.getEvents().size());
+ for (final TimeEvent te : band.getEvents().values()) {
+ if (te.getEventDiv().isOrHasChild(targetElement)) {
+ // Log.debug("Found event:" + te.getId() + " " +
+ // te.getDescription());
+ this.descriptor.show(te, e);
+ return;
+ }
+ }
+ }
+
+ // if no events found, then hide description:
+ this.descriptor.hide();
+ }
+
+ /**
+ * @return the isHorizontal
+ */
+ public boolean isHorizontal() {
+ return isHorizontal;
+ }
+
+ /**
+ * call this when you want to force a repaint
+ */
+ public synchronized void paint() {
+ if (!isRendered) {
+ timelineDiv.appendChild(timelineContainer);
+
+ int relativeTop = 0;
+ for (final Timeband tb : timebands) {
+ tb.paint();
+ relativeTop += tb.getSizeTapeTracks() * TimelineConstants.TAPE_TRACK_HEIGHT;
+ }
+
+ // the total relative at this stage is the total height of the
+ // timeline
+ new El(timelineDiv).setHeight(relativeTop);
+ isRendered = true;
+ }
+ }
+
+ /**
+ * Repaints a particular timeband
+ *
+ * @param originDate date at which to start
+ * @param unit unit to be used on the timeband
+ * @param timebandId the timeband id
+ */
+ public void repaint(final Long originDate, final Unit unit, final int timebandId) {
+ // remove all the timebands from the timeline widget
+ // TODO: HERE all we want to do is set the corect timeband with that
+ // unit, not all of them, right?
+ // what if we have several timebands in the origin, is that possible?
+ // events on different timebands with the same scripture references
+
+ // TODO: set other timbands back to their original scales
+
+ for (final Timeband band : timebands) {
+ setUserInterestOnBand(band, timebandId, unit);
+ band.setCurrentDate(originDate);
+ band.setCurrentDateX(TimelineConstants.TIMELINE_WIDTH + timelineDiv.getClientWidth() / 2);
+ band.scrollToCurrentDate();
+ band.redrawEmptyBand();
+ }
+
+ fireTimelineScrollEvent();
+ }
+
+ /**
+ * @param height the height to set
+ */
+ public void setHeight(final int height) {
+ this.height = height;
+ }
+
+ /**
+ * @param isHorizontal the isHorizontal to set
+ */
+ public void setHorizontal(final boolean isHorizontal) {
+ this.isHorizontal = isHorizontal;
+ }
+
+ /**
+ * @param width the width to set
+ */
+ public void setWidth(final int width) {
+ this.width = width;
+ }
+
+ /**
+ * Zooming is done on a band level, so delegate to timebands
+ */
+ public void zoomIn() {
+ for (final Timeband tb : timebands) {
+ tb.zoomIn();
+ }
+ }
+
+ /**
+ * Zooming is done on a band level, so delegate to timebands
+ */
+ public void zoomOut() {
+ for (final Timeband tb : timebands) {
+ tb.zoomOut();
+ }
+ }
+
+ /**
+ * adds event handlers to capture mouse movements, clicks, etc
+ *
+ * @param eventBus event bus on which to register some handlers
+ */
+ // TODO: investigate pushing the handlers in to the handler!!!
+ private void addEventHandlers(final EventBus eventBus) {
+ final TimelineMouseHandler tmh = new TimelineMouseHandler(this);
+ addDomHandler(tmh, MouseMoveEvent.getType());
+ addDomHandler(tmh, MouseUpEvent.getType());
+ addDomHandler(tmh, MouseDownEvent.getType());
+ addDomHandler(tmh, MouseOutEvent.getType());
+ addDomHandler(tmh, MouseOverEvent.getType());
+
+ eventBus.addHandler(UserInterestInBandEvent.TYPE, new UserInterestInBandEventHandler() {
+
+ public void onUserInterestedInBand(final UserInterestInBandEvent userInterestInBandEvent) {
+ try {
+ final Timeband band = getBand(userInterestInBandEvent.getBandId());
+ band.registerUserInterest(userInterestInBandEvent.isOfInterest());
+ band.paint();
+ } catch (final TimeBandNotFoundException e) {
+ Log.warn("The user request a band that no longer exists.");
+ }
+ }
+ });
+
+ // TODO: add window handler
+
+ }
+
+ /**
+ * Disables the user selection on the timeline widget, to ensure the user
+ * gets a good experience
+ *
+ * @param e the DOM element on which to perform these javascript operations
+ */
+ private native void disableSelection(final Element e) /*-{
+ e.ondrag = function() { return false; };
+ e.onselectstart = function() { return false; };
+ e.style.MozUserSelect = "none";
+ }-*/;
+
+ /**
+ * returns the fired timeband band, given a mouse move event
+ *
+ * @param e the mouse band
+ * @return the timeband that was fired
+ * @throws UnknownFiredElement thrown if we do not know which timeband was
+ * fired
+ */
+ private Timeband getFiredBand(final MouseMoveEvent e) throws UnknownFiredElement {
+ final EventTarget et = e.getNativeEvent().getEventTarget();
+ final Element targetElement = et.cast();
+
+ for (final Timeband b : timebands) {
+ if (b.getBandDiv().isOrHasChild(targetElement)) {
+ return b;
+ }
+ }
+
+ throw new UnknownFiredElement();
+ }
+
+ /**
+ * if the band corresponds to the correct timeband id, then set unit,
+ * otherwise revert back to the original state...
+ *
+ * @param band band
+ * @param timebandId timebandId
+ * @param unit unit
+ */
+ private void setUserInterestOnBand(final Timeband band, final int timebandId, final Unit unit) {
+ if (band.getId() == timebandId) {
+ band.setUnit(unit);
+ band.registerUserInterest(true);
+ } else {
+ band.resetOriginalUnit();
+ band.registerUserInterest(false);
+ }
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/Orientation.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/Orientation.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/Orientation.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,21 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.components;
+
+/**
+ * This determines whether to render the timeband horizontally or vertically. At
+ * the moment only HORIZONTAL is supported.
+ *
+ * @author CJBurrell
+ *
+ */
+public enum Orientation {
+ /**
+ * Render the timeband horizontally
+ */
+ HORIZONTAL,
+
+ /**
+ * Render the timeband vertically
+ */
+ VERTICAL,
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimebandRequestWindow.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimebandRequestWindow.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimebandRequestWindow.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,82 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.components;
+
+/**
+ * This window identifies what is already displayed on the timeline Perhaps
+ * later we send this back to the server, and let the server work out which bits
+ * and pieces each timebands are interested in. So still send the full view
+ * coordinates, but send that as well.
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimebandRequestWindow {
+ /** max date requested so far */
+ private long maxDate;
+
+ /** min date requested so far */
+ private long minDate;
+
+ /**
+ * timeband request window, when created takes the intial window (min, max)
+ *
+ * @param initialMin initial minimum, usually the left most visible pixel of
+ * the timeband
+ * @param initialMax initial maximum, usually the right most visible pixel
+ * of the timeband
+ */
+ public TimebandRequestWindow(final long initialMin, final long initialMax) {
+ minDate = initialMin;
+ maxDate = initialMax;
+ }
+
+ /**
+ * Enlarges the minimum window on the left hand-side
+ *
+ * @param minDateRequested the new minDate that the band has received
+ * @param maxDateRequested the new maxDate that the band has received
+ */
+ public void adjustRange(final long minDateRequested, final long maxDateRequested) {
+ // Log.debug("Adjusting minimum of received/requested window");
+
+ // adjust minimum: as long as the minimum is before, but the max within
+ // range, we're fine to adjust
+ // --------------------<-------$-----<-------$------------------
+ // mdr md Mdr MD
+ if (minDateRequested < minDate && maxDateRequested >= minDate) {
+ minDate = minDateRequested;
+ }
+
+ // do the same for the maximum:
+ if (maxDateRequested > maxDate && minDateRequested <= maxDate) {
+ maxDate = maxDateRequested;
+ }
+ }
+
+ /**
+ * @return the maxDate
+ */
+ public long getMaxDate() {
+ return maxDate;
+ }
+
+ /**
+ * @return the minDate
+ */
+ public long getMinDate() {
+ return minDate;
+ }
+
+ /**
+ * @param maxDate the maxDate to set
+ */
+ public void setMaxDate(final long maxDate) {
+ this.maxDate = maxDate;
+ }
+
+ /**
+ * @param minDate the minDate to set
+ */
+ public void setMinDate(final long minDate) {
+ this.minDate = minDate;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimelineConstants.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimelineConstants.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/components/TimelineConstants.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,85 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.components;
+
+/**
+ * Timeline constants to be used in the timeline module
+ *
+ * @author CJBurrell
+ *
+ */
+public final class TimelineConstants {
+
+ /**
+ * This is the setting defining how many pixels represent 1 unit
+ */
+ public static final int DEFAULT_PIXELS_PER_UNIT = 100;
+ /**
+ * for a duration event, the css class
+ */
+ public static final String DURATION = "step-timeline-duration";
+ /**
+ * css class for a label of a duration event
+ */
+ public static final String DURATION_LABEL = "step-time-duration-label";
+ /**
+ * step time event css
+ */
+ public static final String EVENT = "step-time-event";
+ /**
+ * the minimum width of an event
+ */
+ public static final int EVENT_MIN_WIDTH = 2;
+
+ /**
+ * The initial date for the timeline, the date of birth of Jesus
+ */
+ public static final long INITIAL_DATE = -61183987174853L;
+ /**
+ * this describes how much of a unit needs to be visible before calling back
+ * to the server
+ */
+ public static final double MINIMUM_UNIT_PORTION_BEFORE_SERVER_CALL = 0.5;
+ /**
+ * css of a point in time event
+ */
+ public static final String POINT_IN_TIME_EVENT = "step-timeline-pointInTime";
+
+ /**
+ * css for the label of a point in time event label
+ */
+ public static final String POINT_IN_TIME_LABEL = "step-time-point-in-time-label";
+
+ /**
+ * space between the icon and the text
+ */
+ public static final int POINT_IN_TIME_WIDTH_SPACE = 15;
+
+ /**
+ * space between the popup and the mouse
+ */
+ public static final int SPACE_BELOW_POPUP = 20;
+
+ /**
+ * height of each tape track
+ *
+ */
+ public static final int TAPE_TRACK_HEIGHT = 21;
+
+ /**
+ * total width of timeline width, hardcoded at the moment
+ */
+ // TODO: parameterize this depending on the length of the band
+ public static final int TIMELINE_WIDTH = 32000;
+
+ /**
+ * The initial zoom factor. This determines how much of a zoom is applied.
+ * For example a factor of 0.25 changes the scale of 50 pixels per decade to
+ * (1 + 0.25) * 50 = 75 pixels
+ */
+ public static final double ZOOM_FACTOR = 0.25;
+
+ /**
+ * prevent intialisation
+ */
+ private TimelineConstants() {
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/TimelineMouseHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/TimelineMouseHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/events/TimelineMouseHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,58 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.events;
+
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.tyndalehouse.step.web.client.toolkit.timeline.Timeline;
+
+/**
+ * timeline mouse handler to re-delegate events to the timeline component this
+ * is used mainly for the scrolling functionality on the timeline
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimelineMouseHandler implements MouseMoveHandler, MouseUpHandler, MouseDownHandler,
+ MouseOutHandler, MouseOverHandler {
+ /**
+ * The timeline component
+ */
+ private final Timeline timeline;
+
+ /**
+ * constructor takes the timeline component
+ *
+ * @param timeline the timeline component.
+ */
+ public TimelineMouseHandler(final Timeline timeline) {
+ this.timeline = timeline;
+ }
+
+ public void onMouseDown(final MouseDownEvent event) {
+ timeline.handle(event);
+ }
+
+ public void onMouseMove(final MouseMoveEvent event) {
+ timeline.handle(event);
+ }
+
+ public void onMouseOut(final MouseOutEvent event) {
+ timeline.handle(event);
+ }
+
+ public void onMouseOver(final MouseOverEvent event) {
+ timeline.handle(event);
+
+ }
+
+ public void onMouseUp(final MouseUpEvent event) {
+ timeline.handle(event);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/CannotDeleteEventException.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/CannotDeleteEventException.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/CannotDeleteEventException.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,27 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.exceptions;
+
+/**
+ * The request to delete an event has failed. The message should explain why
+ * this has happened.
+ *
+ * @author CJBurrell
+ *
+ */
+public class CannotDeleteEventException extends Exception {
+
+ /**
+ * The default constructor with the explanatory message
+ *
+ * @param message
+ * The message for the exception
+ */
+ public CannotDeleteEventException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Serialisation id
+ */
+ private static final long serialVersionUID = -9221252482310063155L;
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/IncapableOfCalculatingRequestWindowException.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/IncapableOfCalculatingRequestWindowException.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/IncapableOfCalculatingRequestWindowException.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,32 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.exceptions;
+
+/**
+ * The request window is the window of pixels (start/end) that gets send to the
+ * server indicating the client wants to get events that are in that time
+ * section There are certain situations where it is impossible to calculate how
+ * the user has moved, for example when the browser moves so quickly that the
+ * whole screen shifts 1 screen-wide of pixels
+ *
+ * @author CJBurrell
+ */
+public class IncapableOfCalculatingRequestWindowException extends Exception {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 1866493907904681758L;
+
+ /**
+ * The client is unable to calculate which bit to request from the server
+ *
+ * @param minVisibleDate the minimum visible date from the client
+ * @param maxVisibleDate the maximum visible date from the client
+ * @param minReceivedDate the minimum date the client has ever seen
+ * @param maxReceivedDate the maximum date the client has ever seen
+ */
+ public IncapableOfCalculatingRequestWindowException(final long minVisibleDate, final long maxVisibleDate,
+ final long minReceivedDate, final long maxReceivedDate) {
+ super("Unable to calculate request window for: " + minReceivedDate + " / " + maxReceivedDate
+ + ". Visible section is: " + minVisibleDate + " / " + maxVisibleDate);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/TimeBandNotFoundException.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/TimeBandNotFoundException.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/TimeBandNotFoundException.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,25 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.exceptions;
+
+/**
+ * While trying to lookup the timeband, it was not found
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimeBandNotFoundException extends Exception {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 6234571991235670035L;
+
+ /**
+ * Constructor specifying the error message
+ *
+ * @param message message indicating which band was not found
+ */
+ public TimeBandNotFoundException(final String message) {
+ super(message);
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/UnknownFiredElement.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/UnknownFiredElement.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/exceptions/UnknownFiredElement.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,17 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.exceptions;
+
+/**
+ * Thrown if an DOM element contained in the timeline is fired but it is not
+ * recognised by the timeline element
+ *
+ * @author CJBurrell
+ *
+ */
+public class UnknownFiredElement extends Exception {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -726869406002130223L;
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/CurrentBandStats.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/CurrentBandStats.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/CurrentBandStats.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,87 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.helpers;
+
+/**
+ * Contains the current statistics of how many events are present on a
+ * particular timeband This bean is band specific
+ *
+ * @author CJBurrell
+ *
+ */
+public class CurrentBandStats {
+ /**
+ * description of the band to be displayed on the screen
+ */
+ private final String bandDescription;
+
+ /**
+ * timeband id
+ */
+ private final int bandId;
+
+ /**
+ * ticked or not, whether the user is interested in this
+ */
+ private final boolean isUserInterested;
+
+ /**
+ * number of elements on the timeband
+ */
+ private final int numElements;
+
+ /**
+ * number of elements currently visible
+ */
+ private final int numVisibleElements;
+
+ /**
+ *
+ * @param bandId the id of the band
+ * @param numElements the number of events on the band
+ * @param numVisibleElements the number of visible events in the frame
+ * @param bandDescription description to be displayed on the view
+ * @param isUserInterested whether the user is interested in the band
+ */
+ public CurrentBandStats(final int bandId, final String bandDescription, final int numElements,
+ final int numVisibleElements, final boolean isUserInterested) {
+ this.bandId = bandId;
+ this.bandDescription = bandDescription;
+ this.numElements = numElements;
+ this.numVisibleElements = numVisibleElements;
+ this.isUserInterested = isUserInterested;
+ }
+
+ /**
+ * @return the bandDescription
+ */
+ public String getBandDescription() {
+ return bandDescription;
+ }
+
+ /**
+ * @return the bandId
+ */
+ public int getBandId() {
+ return bandId;
+ }
+
+ /**
+ * @return the numElements
+ */
+ public int getNumElements() {
+ return numElements;
+ }
+
+ /**
+ * @return the numVisibleElements
+ */
+ public int getNumVisibleElements() {
+ return numVisibleElements;
+ }
+
+ /**
+ * @return the isUserInterested
+ */
+ public boolean isUserInterested() {
+ return isUserInterested;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/TimeConversionUtil.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/TimeConversionUtil.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/toolkit/timeline/helpers/TimeConversionUtil.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,92 @@
+package com.tyndalehouse.step.web.client.toolkit.timeline.helpers;
+
+import java.util.Date;
+
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.tyndalehouse.step.web.client.toolkit.timeline.Timeband;
+import com.tyndalehouse.step.web.shared.timeline.Unit;
+
+/**
+ * Util class to convert time to date and vice versa
+ *
+ * @author CJBurrell
+ *
+ */
+public final class TimeConversionUtil {
+ /**
+ * converts a pixel position to its date using the format associated to the
+ * unit of the timeband
+ *
+ * @param pixelPosition pixel position to be converted
+ * @param timeband current timeband (this contains the current viewing
+ * location, and unit
+ * @return the date as a formatted string
+ */
+ public static String formatPixelToTime(final long pixelPosition, final Timeband timeband) {
+ return formatTime(pixelToTime(pixelPosition, timeband), timeband);
+ }
+
+ /**
+ * formats the given time using the unit described in the timeband
+ *
+ * @param timeband the timeband containing the current view, unit, etc.
+ * @param eventDate date to be formatted
+ * @return the string representation of the date
+ */
+ public static String formatTime(final long eventDate, final Timeband timeband) {
+ final Date date = new Date(eventDate);
+ final String formatForBand = timeband.getUnit().getFormat();
+ final DateTimeFormat format = DateTimeFormat.getFormat(formatForBand);
+ return format.format(date);
+ }
+
+ /**
+ * This takes a pixel position and returns the equivalent time
+ *
+ * @param pixelPosition the pixel position that we are trying to convert
+ * @param timeband the timeband which contains the relevant information
+ * (current view, unit) to calculate the time from the pixel
+ * position
+ * @return the time of pixelPosition
+ */
+ public static long pixelToTime(final long pixelPosition, final Timeband timeband) {
+ final long currentDateX = timeband.getCurrentDateX();
+ final long currentDate = timeband.getCurrentDate();
+ final Unit unit = timeband.getUnit();
+ final long pixelsPerUnit = timeband.getPixelsPerUnit();
+
+ final long differenceWithOrigin = pixelPosition - currentDateX;
+ final long date = currentDate + (differenceWithOrigin * unit.getMilliseconds() / pixelsPerUnit);
+ return date;
+ }
+
+ /**
+ * A date is always calculated within a time band.
+ *
+ * @param eventDate the date to be converted
+ * @param currentTimeband reference timeband (including current view, unit,
+ * etc).
+ * @return the pixel position on the timeband for the passed in time
+ */
+ public static int timeToPixel(final long eventDate, final Timeband currentTimeband) {
+ // here's what we start from
+ final long millisecondPerUnit = currentTimeband.getUnit().getMilliseconds();
+ final long pixelsPerUnit = currentTimeband.getPixelsPerUnit();
+ final long currentOriginDate = currentTimeband.getCurrentDate();
+ final long currentOriginXPixel = currentTimeband.getCurrentDateX();
+
+ // what's one pixel in milliseconds?
+ final double onePixelInMs = (double) millisecondPerUnit / pixelsPerUnit;
+
+ // calculate difference with current position on timeband
+ final long differenceWithEvent = eventDate - currentOriginDate;
+ final long pixelValueOnBand = currentOriginXPixel + (long) (differenceWithEvent / onePixelInMs);
+ return (int) pixelValueOnBand;
+ }
+
+ /**
+ * making the constructor invisible to outsiders
+ */
+ private TimeConversionUtil() {
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/HistoryModuleView.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/HistoryModuleView.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/HistoryModuleView.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,87 @@
+package com.tyndalehouse.step.web.client.view;
+
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.tyndalehouse.step.web.client.presenter.HistoryModulePresenter;
+import com.tyndalehouse.step.web.client.toolkit.HtmlList;
+import com.tyndalehouse.step.web.client.toolkit.HtmlList.ListType;
+
+/**
+ * The history module TODO: revamp this completely
+ *
+ * @author cjburrell
+ *
+ */
+public class HistoryModuleView extends Composite implements HistoryModulePresenter.Display {
+
+ /**
+ * an article
+ */
+ private final HTML article;
+
+ /**
+ * A contents page to choose from
+ */
+ private final HtmlList contentsTable;
+
+ /**
+ * default constructor
+ */
+ public HistoryModuleView() {
+ final VerticalPanel vp = new VerticalPanel();
+ initWidget(vp);
+ article = new HTML();
+
+ article.setHTML("Abija Aviyam: \"Father of the sea\" or \"my father "
+ + "is the sea\" or \"my father is Yah\") was the fourth king "
+ + "of the House of David and the second of the Kingdom of "
+ + "Judah. He was the son of Rehoboam, the grandson of Solomon "
+ + "and the great-grandson of David. The Chronicler refers to "
+ + "him as \"Abijah (Hebrew, \"my father is The LORD\"). "
+ + "William F. Albright has dated his reign to 915 BC - 913 "
+ + "BC, while E. R. Thiele offers the dates 914/913 - 911/910 BC. "
+ + "[1] As explained in the Rehoboam article, Thiele's chronology for "
+ + "the first kings of Judah contained an internal inconsistency "
+ + "that later scholars corrected by dating these kings "
+ + "one year earlier, so that Abijah's dates are taken as 915/914 "
+ + "to 912/911 BC in the present article. The Hebrew Bible gives "
+ + "his reign length as three years. His mother's name was Maacah, "
+ + "or Micaiah, the granddaughter of the infamous Abishalom (Absalom). "
+ + "Abijah married fourteen wives, and had 22 sons and 16 daughters. " + "[2]");
+
+ // contents at the top
+ contentsTable = new HtmlList(ListType.UNORDERED);
+ contentsTable.addItem("Abijah, Yah is my father", null);
+ contentsTable.addItem("Abijam, father of the sea", null);
+ contentsTable.addItem("Abilene, the father of mourning", null);
+
+ vp.add(contentsTable);
+ vp.add(article);
+ }
+
+ public Widget asWidget() {
+ return this;
+ }
+
+ /**
+ * Sets the current article
+ *
+ * @param articleText the text of the article to be viewed
+ */
+ public void setArticle(final String articleText) {
+ article.setHTML(articleText);
+ }
+
+ public void startProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stopProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ModuleSelectorView.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ModuleSelectorView.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ModuleSelectorView.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,133 @@
+package com.tyndalehouse.step.web.client.view;
+
+import java.util.List;
+
+import com.google.gwt.event.dom.client.HasChangeHandlers;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.tyndalehouse.step.web.client.presenter.ModuleSelectorPresenter;
+import com.tyndalehouse.step.web.client.toolkit.HasSource;
+import com.tyndalehouse.step.web.client.toolkit.SimpleListBox;
+
+/**
+ * The module selector view, displaying three levels of study
+ * <p />
+ * The module: History, Geography, etc. <br />
+ * <p />
+ * The sub-module: Genealogies,
+ * <p />
+ *
+ * The depth: the depth at which people want to study (scholarly, light etc.)
+ *
+ * @author cjburrell
+ *
+ */
+public class ModuleSelectorView extends Composite implements ModuleSelectorPresenter.Display {
+ /**
+ * a list of modules
+ */
+ private final SimpleListBox module;
+
+ /**
+ * a list of depths
+ */
+ private final SimpleListBox moduleDepth;
+
+ /**
+ * a list of sub modules, correlated to the list of modules
+ */
+ private final SimpleListBox subModule;
+
+ /**
+ * The default constructor
+ */
+ public ModuleSelectorView() {
+ final FlowPanel p = new FlowPanel();
+ initWidget(p);
+
+ module = new SimpleListBox();
+ moduleDepth = new SimpleListBox();
+ subModule = new SimpleListBox();
+
+ p.add(module);
+ p.add(moduleDepth);
+ p.add(subModule);
+ }
+
+ public String getSelectedModule() {
+ // check that the module has been populated already!
+ if (module.getItemCount() == 0) {
+ return null;
+ }
+
+ return module.getValue(module.getSelectedIndex());
+ }
+
+ public void setSelectedModule(final String value) {
+ // simple linear search
+ for (int ii = 0; ii < module.getItemCount(); ii++) {
+ if (value.equals(module.getValue(ii))) {
+ module.setSelectedIndex(ii);
+ return;
+ }
+ }
+ }
+
+
+ public String getSelectedSubModule() {
+ if (subModule.getItemCount() == 0) {
+ return null;
+ }
+ return subModule.getValue(subModule.getSelectedIndex());
+ }
+
+ public Widget asWidget() {
+ return this;
+ }
+
+ public HasChangeHandlers getModuleChangeHandlers() {
+ return module;
+ }
+
+ public HasChangeHandlers getModuleDepthChangeHandlers() {
+ return moduleDepth;
+ }
+
+ public HasSource<List<String>> getModuleDepthSource() {
+ return moduleDepth;
+ }
+
+ public HasSource<List<String>> getModuleSource() {
+ return module;
+ }
+
+ public String getSelectedDepth() {
+ if (moduleDepth.getItemCount() == 0) {
+ return null;
+ }
+ return moduleDepth.getValue(moduleDepth.getSelectedIndex());
+ }
+
+
+
+ public HasChangeHandlers getSubModuleChangeHandlers() {
+ return subModule;
+ }
+
+ public HasSource<List<String>> getSubModuleSource() {
+ return subModule;
+ }
+
+
+ public void startProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stopProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ScriptureSelectorView.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ScriptureSelectorView.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ScriptureSelectorView.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,95 @@
+package com.tyndalehouse.step.web.client.view;
+
+import java.util.Collection;
+
+import com.allen_sauer.gwt.log.client.Log;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HasValue;
+import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
+import com.google.gwt.user.client.ui.SuggestBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.tyndalehouse.step.web.client.presenter.ScriptureSelectorPresenter;
+
+/**
+ * This view provides the user with a way to select a portion of scripture. It
+ * therefore contains a textbox and a button to fire the event. The textbox is
+ * an auto-complete textbox
+ *
+ * @author cjburrell
+ */
+public class ScriptureSelectorView extends Composite implements ScriptureSelectorPresenter.Display {
+ /**
+ * the source of the auto comlete textbox
+ */
+ private final MultiWordSuggestOracle oracle;
+
+ /**
+ * the auto complete text box
+ */
+ private final SuggestBox reference;
+
+ /**
+ * the button fired to search
+ */
+ private final Button search;
+
+ /**
+ * the default constructor to render the view
+ */
+ public ScriptureSelectorView() {
+ final FlowPanel p = new FlowPanel();
+ initWidget(p);
+
+ oracle = new MultiWordSuggestOracle();
+ reference = new SuggestBox(oracle);
+ p.add(reference);
+
+ // TODO: localise this
+ search = new Button("Lookup");
+ p.add(search);
+
+ Log.debug("== Scripture Selector View initialiased");
+ }
+
+ public void addSuggestion(final String suggestion) {
+ oracle.add(suggestion);
+ }
+
+ public void addSuggestions(final Collection<String> suggestions) {
+ oracle.addAll(suggestions);
+
+ }
+
+ public Widget asWidget() {
+ return this;
+ }
+
+ /**
+ * @return the unvalidated biblical reference that is currently in the
+ * textbox
+ */
+ public HasValue<String> getReference() {
+ return reference;
+ }
+
+ /**
+ * @return the search button on which to append listeners
+ */
+ public HasClickHandlers getSearch() {
+ return search;
+ }
+
+ public void startProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stopProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ScriptureView.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ScriptureView.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/ScriptureView.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,207 @@
+package com.tyndalehouse.step.web.client.view;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedMap;
+
+import net.customware.gwt.presenter.client.EventBus;
+
+import com.google.gwt.event.dom.client.HasChangeHandlers;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.InlineLabel;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.presenter.ScripturePresenter;
+import com.tyndalehouse.step.web.client.toolkit.HasSource;
+import com.tyndalehouse.step.web.client.toolkit.SourceListBox;
+import com.tyndalehouse.step.web.client.toolkit.scripture.ScriptureDisplayConstants;
+import com.tyndalehouse.step.web.client.toolkit.scripture.VerseLabel;
+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.Verse;
+import com.tyndalehouse.step.web.shared.scripture.VerseContent;
+import com.tyndalehouse.step.web.shared.scripture.Word;
+
+/**
+ * This view aims to show Scripture to the user. In order to do this, the user
+ * can select a version from a dropdown. The
+ *
+ * TODO: remove the eventBus from the view.
+ *
+ * @author cjburrell
+ *
+ */
+public class ScriptureView extends Composite implements ScripturePresenter.Display {
+
+ /**
+ * the auto list of bible versions
+ */
+ private final SourceListBox bibleVersions;
+
+ // TODO: to be removed into the presenter
+ /**
+ * the default event bus
+ */
+ private final EventBus eventBus;
+
+ /**
+ * a list of VerseLabel (wrappers of bible text) that are currently being
+ * displayed and contain lemmas
+ */
+ private final List<VerseLabel> lemmaWords;
+
+ /**
+ * a list of VerseLabel (wrappers of bible text) that are currently being
+ * displayed and contain morphs
+ */
+ private final List<VerseLabel> morphs;
+
+ /**
+ * a logical display of scripture, in that events can be attached to each of
+ * the elements on this panel
+ */
+ private final Panel scriptureHolder;
+
+ /**
+ * a simple display of scripture as text
+ */
+ private final HTML scriptureHTML;
+
+ /**
+ * The default constructor
+ *
+ * @param eventBus eventBus - //TODO: remove this
+ */
+ @Inject
+ public ScriptureView(final EventBus eventBus) {
+ this.eventBus = eventBus;
+ final VerticalPanel vp = new VerticalPanel();
+ scriptureHolder = new FlowPanel();
+ lemmaWords = new ArrayList<VerseLabel>();
+ morphs = new ArrayList<VerseLabel>();
+
+ initWidget(vp);
+
+ bibleVersions = new SourceListBox();
+ bibleVersions.setStylePrimaryName("bibleVersionsDropDown");
+
+ // adding the dropdown with the bible versions
+ vp.add(bibleVersions);
+
+ // adding the html display of scripture
+ // TODO : Localise this here.
+ scriptureHTML = new HTML("Please lookup a reference");
+ vp.add(scriptureHTML);
+ vp.add(scriptureHolder);
+ }
+
+ public Widget asWidget() {
+ return this;
+ }
+
+ public HasChangeHandlers getChangeHandlers() {
+ return bibleVersions;
+ }
+
+ public String getSelectedBibleVersion() {
+ return bibleVersions.getValue(bibleVersions.getSelectedIndex());
+ }
+
+ public HasSource<SortedMap<String, String>> getSource() {
+ return bibleVersions;
+ }
+
+ public void highlight(final List<String> lemmaList) {
+ for (final VerseLabel vl : lemmaWords) {
+ for (final String l : lemmaList) {
+ if (vl.getLemma().contains(l)) {
+ vl.setStyleName(ScriptureDisplayConstants.EMPHASISE);
+ } else {
+ vl.removeStyleName(ScriptureDisplayConstants.EMPHASISE);
+ }
+ }
+ }
+ }
+
+ public void setPassage(final Passage passage) {
+ final List<VerseContent> verseContent = passage.getVerseContent();
+
+ // clear current text:
+ scriptureHolder.clear();
+
+ for (final VerseContent v : verseContent) {
+ if (v instanceof Title) {
+ doTitle((Title) v);
+ } else if (v instanceof Verse) {
+ doVerse((Verse) v);
+ }
+ }
+
+ }
+
+ // TODO: probably remove the following function, and ensure the service is
+ // removed at the same time
+ public void setPassage(final String text) {
+ scriptureHTML.setHTML(text);
+ }
+
+ public void startProcessing() {
+ }
+
+ public void stopProcessing() {
+ // TODO: to be completed
+ }
+
+ /**
+ * Create an element to display a title
+ *
+ * @param v the logical representation of a title
+ */
+ private void doTitle(final Title v) {
+ final InlineLabel il = new InlineLabel(v.getText());
+ scriptureHolder.add(il);
+ }
+
+ /**
+ * Create a display for the verse
+ *
+ * @param v the logical representation of the verse
+ */
+ private void doVerse(final Verse v) {
+ VerseLabel vl;
+
+ for (final TextualElement text : v.getVerseContent()) {
+ // check that text is not nullable
+ if (text.getText() != null) {
+ vl = new VerseLabel(text.getText(), eventBus);
+ scriptureHolder.add(vl);
+
+ // then do specifics
+ if (text instanceof Word) {
+ final Word w = (Word) text;
+ // if there's an alternative, then we ensure that we set
+ // that up
+ // eventually UI design will mean changes here
+ vl.setAlternativeWord(w.getAlternativeWord());
+
+ final List<String> lemma = w.getLemma();
+ if (lemma != null) {
+ lemmaWords.add(vl);
+ vl.setLemmas(lemma);
+ }
+
+ final List<String> morph = w.getMorph();
+ if (morph != null) {
+ vl.setMorphs(morph);
+ morphs.add(vl);
+ }
+ }
+ }
+ }
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/StepView.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/StepView.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/StepView.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,116 @@
+package com.tyndalehouse.step.web.client.view;
+
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.DockPanel;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.presenter.HistoryModulePresenter;
+import com.tyndalehouse.step.web.client.presenter.ModuleSelectorPresenter;
+import com.tyndalehouse.step.web.client.presenter.ScripturePresenter;
+import com.tyndalehouse.step.web.client.presenter.ScriptureSelectorPresenter;
+import com.tyndalehouse.step.web.client.presenter.StepPresenter;
+import com.tyndalehouse.step.web.client.presenter.TimebandListPresenter;
+import com.tyndalehouse.step.web.client.presenter.TimelinePresenter;
+
+/**
+ * This View sets up the many different views and the layout of the Step
+ * Application
+ *
+ * @author cjburrell
+ *
+ */
+public class StepView extends Composite implements StepPresenter.Display {
+
+ /**
+ * This is the panel on which you display scripture side by side.
+ */
+ private final DockPanel dp;
+
+ // TODO: i should be able to pass in the ScriptureSelectorPresenter as
+ // opposed to the display directly
+ // we want one that is attached. that would remove the need for
+
+ /**
+ *
+ * Default constructor inputting most presenters, which initialises the
+ * views via Gin
+ *
+ * @param scriptureSelector a view allowing the user to key in a biblical
+ * reference
+ * @param scripture a view showing scripture
+ * @param scripture2 a second view showing scripture
+ * @param moduleSelector a view allowing the user to select his module of
+ * interest (history, geography, etc.)
+ * @param module the view display the various different modules (history,
+ * geography, etc.)
+ * @param timelinePresenter a view allowing the user to show
+ * @param timebandListPresenter a view showing the current numbers of events
+ * displayed on the timeline
+ * <p>
+ * TODO: experiment if these can be passed in using just the
+ * View, but their interface definition for e.g.
+ * ScripturePresenter.Display
+ */
+ @Inject
+ public StepView(final ScriptureSelectorPresenter scriptureSelector,
+ final ScripturePresenter scripture, final ScripturePresenter scripture2,
+ final ModuleSelectorPresenter moduleSelector, final HistoryModulePresenter module,
+ final TimelinePresenter timelinePresenter, final TimebandListPresenter timebandListPresenter) {
+
+ final FlowPanel flow = new FlowPanel();
+
+ dp = new DockPanel();
+ flow.add(dp);
+ initWidget(flow);
+
+ final HorizontalPanel northPanel = new HorizontalPanel();
+
+ dp.add(northPanel, DockPanel.NORTH);
+ northPanel.add(scriptureSelector.getDisplay().asWidget());
+ northPanel.add(moduleSelector.getDisplay().asWidget());
+
+ // scripturePanels = new HorizontalPanel();
+ // dp.add(scripturePanels, DockPanel.WEST);
+ addScriptureDisplay(scripture);
+ addScriptureDisplay(scripture2);
+
+ // starts here hardcoded, each of the scripture panel takes 25%, but
+ // eventually, they
+ // should try and work this out for themselves
+ // TODO: see above
+ scripture.getDisplay().asWidget();
+ scripture2.getDisplay().asWidget();
+
+ dp.add(module.getDisplay().asWidget(), DockPanel.CENTER);
+ flow.add(timelinePresenter.getDisplay().asWidget());
+
+ // for the moment, adding it to the flow
+ dp.add(timebandListPresenter.getDisplay().asWidget(), DockPanel.SOUTH);
+ }
+
+ /**
+ * adds a scripture display component to the page
+ *
+ * @param scripture scripture "view"
+ */
+ public void addScriptureDisplay(final ScripturePresenter scripture) {
+ dp.add(scripture.getDisplay().asWidget(), DockPanel.WEST);
+ // scripturePanels.add(scripture.getDisplay().asWidget());
+ }
+
+ public Widget asWidget() {
+ return this;
+ }
+
+ public void startProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stopProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/TimebandListView.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/TimebandListView.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/TimebandListView.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,99 @@
+package com.tyndalehouse.step.web.client.view;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.customware.gwt.presenter.client.EventBus;
+
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.event.UserInterestInBandEvent;
+import com.tyndalehouse.step.web.client.presenter.TimebandListPresenter;
+import com.tyndalehouse.step.web.client.toolkit.timeline.helpers.CurrentBandStats;
+
+/**
+ * The timeband list view is a list of timebands. The list includes numbers of
+ * events currently on the timeband and the number of events that could be
+ * shown, in the visible section, of the timeband should the user express
+ * interest
+ *
+ * @author cjburrell
+ *
+ */
+public class TimebandListView extends Composite implements TimebandListPresenter.Display {
+ /**
+ * the map of checkboxes displayed on the page
+ */
+ private final Map<Integer, CheckBox> checkboxes = new HashMap<Integer, CheckBox>();
+
+ /**
+ * TODO: remove this event bus
+ */
+ private final EventBus eventBus;
+
+ /**
+ * the vertical panel on which the checkboxes are added
+ */
+ private final VerticalPanel fp = new VerticalPanel();
+
+ /**
+ * The default constructor
+ *
+ * @param eventBus TODO: TO BE REMOVED
+ */
+ @Inject
+ public TimebandListView(final EventBus eventBus) {
+ this.eventBus = eventBus;
+ initWidget(fp);
+ }
+
+ public Widget asWidget() {
+ return this;
+ }
+
+ public void startProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+
+ public void stopProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * method called to update the list of timebands with the latest statistics
+ *
+ * @param stats is a list of current numbers of events (total/visible) on
+ * each timeband
+ */
+ // TODO: should the event adding somehow be moved into the presenter?
+ public void updateList(final List<CurrentBandStats> stats) {
+ for (final CurrentBandStats band : stats) {
+ CheckBox cb = checkboxes.get(band.getBandId());
+ if (cb == null) {
+ cb = new CheckBox();
+ fp.add(cb);
+ cb.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
+ public void onValueChange(final ValueChangeEvent<Boolean> event) {
+ eventBus.fireEvent(new UserInterestInBandEvent(band.getBandId(), event.getValue()));
+ }
+
+ });
+ }
+
+ final int numEventsInBand = band.getNumVisibleElements();
+ cb.setText(band.getBandDescription() + " (" + numEventsInBand + ")");
+ cb.setTitle("Click here to show " + numEventsInBand + " more events.");
+ cb.setValue(band.isUserInterested(), false);
+ checkboxes.put(band.getBandId(), cb);
+ }
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/TimelineView.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/TimelineView.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/client/view/TimelineView.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,104 @@
+package com.tyndalehouse.step.web.client.view;
+
+import net.customware.gwt.presenter.client.EventBus;
+
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.inject.Inject;
+import com.tyndalehouse.step.web.client.presenter.TimelinePresenter;
+import com.tyndalehouse.step.web.client.toolkit.timeline.Timeline;
+
+/**
+ * the timeline view is a wrapper around the whole timeline component used for
+ * displaying events stored in the database. These events can be point-in-time
+ * or in duration.
+ *
+ * A timeline is split into a timebands, which are then split in to time tracks.
+ * The events are added to a timetrack
+ *
+ * @author cjburrell
+ *
+ */
+public class TimelineView extends Composite implements TimelinePresenter.Display {
+
+ /**
+ * The timeline component
+ */
+ private final Timeline timeline;
+
+ /**
+ * The zoom in button
+ */
+ private final Button zoomIn;
+
+ /**
+ * The zoom out button
+ */
+ private final Button zoomOut;
+
+ /**
+ * Default constructor TODO: remove eventBus
+ *
+ * @param eventBus remove event bus from here
+ */
+ @Inject
+ public TimelineView(final EventBus eventBus) {
+ // to do a custom timeline for testing
+ // TODO: change to a provider, lookup Gin/Guice manual to do this...
+ timeline = new Timeline(eventBus);
+
+ final VerticalPanel vp = new VerticalPanel();
+ final FlowPanel fp = new FlowPanel();
+ vp.add(fp);
+ vp.setWidth("100%");
+
+ zoomIn = new Button("+");
+ zoomOut = new Button("-");
+ zoomIn.setStyleName("step-timeline-control");
+ zoomOut.setStyleName("step-timeline-control");
+
+ fp.add(zoomIn);
+ fp.add(zoomOut);
+ vp.add(timeline);
+ initWidget(vp);
+ }
+
+ public Widget asWidget() {
+ return this;
+ }
+
+ /**
+ * @return the timeline
+ */
+ public Timeline getTimeline() {
+ return timeline;
+ }
+
+ /**
+ * @return A click handler on which to register an event for zooming in
+ */
+ public HasClickHandlers getZoomIn() {
+ return zoomIn;
+ }
+
+ /**
+ * @return A click handler on which to register an event for zooming out
+ */
+ public HasClickHandlers getZoomOut() {
+ return zoomOut;
+ }
+
+ public void startProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stopProcessing() {
+ // TODO Auto-generated method stub
+
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/AbstractStepHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/AbstractStepHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/AbstractStepHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,44 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/common/ConfigNotLoadedException.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/ConfigNotLoadedException.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/ConfigNotLoadedException.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -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-app/src/main/java/com/tyndalehouse/step/web/server/common/ConfigProvider.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/ConfigProvider.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/ConfigProvider.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,85 @@
+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 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 {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ URL url = loader.getResource("com/tyndalehouse/step/web/server/config/environment.properties");
+ try {
+ p.load(url.openStream());
+ } catch (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 (pr == null) {
+ pr = new ConfigProvider();
+ }
+
+ String value = System.getProperty(name);
+ if(value == null) {
+ value = 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-app/src/main/java/com/tyndalehouse/step/web/server/common/JSwordConstants.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/JSwordConstants.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/common/JSwordConstants.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,50 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/MalformedStepQueryException.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/MalformedStepQueryException.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/MalformedStepQueryException.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,39 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/Query.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/Query.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/Query.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,20 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/QueryImpl.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/QueryImpl.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/QueryImpl.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,50 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/ResultSetProcessor.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/ResultSetProcessor.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/ResultSetProcessor.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,43 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQuery.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQuery.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQuery.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,158 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunner.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunner.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunner.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,35 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunnerImpl.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunnerImpl.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/StepQueryRunnerImpl.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,356 @@
+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() {
+ 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 = 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(HASH)) != -1) {
+ final int endingHash = q.indexOf(HASH, openingHash + 1);
+ final String paramName = q.substring(openingHash + 1, endingHash);
+ query.addArgument(paramName);
+ q.replace(openingHash, endingHash + 1, 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(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 = queries.get(query);
+ // check whether query is in cache
+ if (stepQuery == null) {
+ stepQuery = readQueryFromFile(query);
+ }
+
+ // now check if datasource is null
+ if (datasource == null) {
+ 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(CACHE_QUERY_PROPERTY)) {
+ 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-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/UnableToRunQueryException.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/UnableToRunQueryException.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/framework/UnableToRunQueryException.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,56 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimeBandVisibleDateProcessor.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimeBandVisibleDateProcessor.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimeBandVisibleDateProcessor.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,134 @@
+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 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(MIN_DATE, minDate);
+ params.put(MAX_DATE, maxDate);
+ params.put(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
+ List<TimelineEventBean> events = new ArrayList<TimelineEventBean>();
+ while (rs.next()) {
+ Long toDate = rs.getObject(TO_DATE) == null ? null : rs.getLong(TO_DATE);
+ TimelineEventBean teb = new TimelineEventBean(rs.getInt(EVENT_ID), rs.getLong(FROM_DATE),
+ toDate,
+ rs.getString(FROM_PRECISION), rs.getString(TO_PRECISION),
+ rs.getString(NAME), rs.getInt(TIMEBAND_ID), rs.getInt(IMPORTANCE_ID),
+ rs.getString(CERTAINTY), rs.getInt(EVENT_TYPE_ID));
+ events.add(teb);
+ }
+ return events;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginDbBean.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginDbBean.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginDbBean.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,75 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginProcessor.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginProcessor.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineOriginProcessor.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,77 @@
+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(QRY_START, qryStart);
+ params.put(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(ORIGIN));
+ bean.setUnit(rs.getString(UNIT));
+ bean.setTimebandId(rs.getInt(TIMEBAND));
+ origins.add(bean);
+ }
+ return origins;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineSetupDataProcessor.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineSetupDataProcessor.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/db/timeline/TimelineSetupDataProcessor.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -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(TIMEBAND_ID));
+ bean.setTimelineDescription(rs.getString(TIMEBAND_DESCRIPTION));
+ bean.setUnit(rs.getString(TIMEBAND_UNIT));
+ timelines.add(bean);
+ }
+ return timelines;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/CustomDispatchServiceServlet.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/CustomDispatchServiceServlet.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/CustomDispatchServiceServlet.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,47 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/guice/DispatchServletModule.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/DispatchServletModule.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/DispatchServletModule.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -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-app/src/main/java/com/tyndalehouse/step/web/server/guice/LogProvider.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/LogProvider.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/LogProvider.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -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 logger;
+ }
+
+ /**
+ * The instantiated log to be returned
+ *
+ * @return the Log file to be used
+ */
+ public Log get() {
+ return logger;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/MyGuiceServletConfig.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/MyGuiceServletConfig.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/MyGuiceServletConfig.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -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-app/src/main/java/com/tyndalehouse/step/web/server/guice/ServerModule.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/ServerModule.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/guice/ServerModule.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -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-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetAvailableBibleVersionsHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetAvailableBibleVersionsHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetAvailableBibleVersionsHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,63 @@
+package com.tyndalehouse.step.web.server.handler;
+
+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;
+
+/**
+ * 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>();
+ for (final Book b : books) {
+ if (b.getBookCategory() == BookCategory.BIBLE) {
+ map.put(b.getInitials(), b.getName());
+ }
+ }
+ return new GetAvailableBibleVersionsResult(map);
+ }
+
+ public void rollback(final GetAvailableBibleVersionsCommand arg0,
+ final GetAvailableBibleVersionsResult arg1, final ExecutionContext arg2)
+ throws ActionException {
+ logger.error("Rolling back GetAvailableBibleVersions");
+
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetBibleBooksHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetBibleBooksHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetBibleBooksHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,70 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetCurrentBibleTextHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetCurrentBibleTextHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetCurrentBibleTextHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,514 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetDictionaryDefinitionHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetDictionaryDefinitionHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetDictionaryDefinitionHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,175 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetEventsForDateRangeHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetEventsForDateRangeHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetEventsForDateRangeHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,104 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetLocationsHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetLocationsHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetLocationsHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,51 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineOriginForScriptureHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineOriginForScriptureHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineOriginForScriptureHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,121 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineUISetupHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineUISetupHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/GetTimelineUISetupHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,66 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/handler/InstallJswordModuleHandler.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/InstallJswordModuleHandler.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/InstallJswordModuleHandler.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,150 @@
+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(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(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(PROXY_HOST);
+ final String proxyPort = System.getProperty(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-app/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/StrongMorphMap.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/StrongMorphMap.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/handler/util/passage/StrongMorphMap.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,119 @@
+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-app/src/main/java/com/tyndalehouse/step/web/server/jsword/ConfigurableHTMLConverter.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/ConfigurableHTMLConverter.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/ConfigurableHTMLConverter.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,170 @@
+/**
+ * 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 font;
+ }
+
+ /**
+ * Accessor for the stylesheet we are transforming using
+ *
+ * @return the resource name
+ */
+ public static String getResourceName() {
+ return 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/" + 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-app/src/main/java/com/tyndalehouse/step/web/server/jsword/XSLTProperty.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/XSLTProperty.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/server/jsword/XSLTProperty.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,321 @@
+/**
+ * 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 = { STRONGS_NUMBERS, MORPH, START_VERSE_ON_NEWLINE,
+ VERSE_NUMBERS, CV, BCV, NO_VERSE_NUMBERS, TINY_VERSE_NUMBERS, HEADINGS, NOTES, XREF, BASE_URL,
+ DIRECTION, FONT, 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 = 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 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 < VALUES.length; i++) {
+ final XSLTProperty o = 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 < VALUES.length; i++) {
+ 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 VALUES[obj];
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/BooksRequiredType.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/BooksRequiredType.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/BooksRequiredType.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,14 @@
+package com.tyndalehouse.step.web.shared.command;
+
+/**
+ * Describing what kind of book to be displayed
+ *
+ * @author CJBurrell
+ *
+ */
+public enum BooksRequiredType {
+ /**
+ * only retrieve bibles
+ */
+ BIBLE,
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetAvailableBibleVersionsCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetAvailableBibleVersionsCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetAvailableBibleVersionsCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,46 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.result.GetAvailableBibleVersionsResult;
+
+/**
+ * Commmand to get available set of books, that are installed on the server
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetAvailableBibleVersionsCommand implements Action<GetAvailableBibleVersionsResult> {
+ /**
+ * serial id.
+ */
+ private static final long serialVersionUID = 5781027650600417430L;
+
+ // TODO: later change that to list modules, bibles, etc.
+ /**
+ * Describes which types of modules are required to be returned.
+ */
+ private BooksRequiredType booksRequired = BooksRequiredType.BIBLE;
+
+ /**
+ * Default constructor needs to be available for GWT it seems.
+ */
+ public GetAvailableBibleVersionsCommand() {
+
+ }
+
+ /**
+ * @return the booksRequired
+ */
+ public BooksRequiredType getBooksRequired() {
+ return booksRequired;
+ }
+
+ /**
+ * @param booksRequired the booksRequired to set
+ */
+ public void setBooksRequired(final BooksRequiredType booksRequired) {
+ this.booksRequired = booksRequired;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetBibleBooksCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetBibleBooksCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetBibleBooksCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,40 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.result.GetBibleBooksCommandResult;
+
+/**
+ * This is currently based on the KJV and ensures that all bible books are
+ * returned to the UI.
+ *
+ * @author CJBurrell
+ *
+ */
+
+public class GetBibleBooksCommand implements Action<GetBibleBooksCommandResult> {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 2749008090105331922L;
+
+ /**
+ * Initials of version to use to lookup bible
+ */
+ private String initials;
+
+ /**
+ * @return the initials
+ */
+ public final String getInitials() {
+ return initials;
+ }
+
+ /**
+ * @param initials the initials to set
+ */
+ public final void setInitials(final String initials) {
+ this.initials = initials;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetCurrentBibleTextCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetCurrentBibleTextCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetCurrentBibleTextCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,107 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.common.scripturelookup.BibleTextLookupType;
+import com.tyndalehouse.step.web.shared.result.GetCurrentBibleTextResult;
+
+/**
+ * Contains the details of a request for biblical text. Such details include
+ * whether to use a plain text, a standard XSLT, or a logical form
+ * <p>
+ * For logical form (represented in Bean form) we allow the use of interlinears
+ * as well.
+ * <p>
+ * A classic interlinear is where the original text is the master copy of the
+ * text, and the translated (English, French, etc.) text is lined up underneath
+ * <p>
+ * A reverse interlinear is where the the English/French text is on top, and the
+ * original (Hebrew or Greek) is lined up underneath.
+ *
+ * @author cjburrell
+ *
+ */
+public class GetCurrentBibleTextCommand implements Action<GetCurrentBibleTextResult> {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -6828956918275592036L;
+
+ /**
+ * the biblical reference, for e.g. Gen 1:1
+ */
+ private String reference;
+
+ /**
+ * type of lookup to make
+ */
+ private BibleTextLookupType typeOfLookup;
+
+ // TODO: add validation to the handler/client to ensure that
+ // version/interlinear matches correctly
+ /**
+ * the version of the bible to use.
+ */
+ private String version;
+
+ /**
+ * default constructor TODO: can this be made private? I think so
+ */
+ public GetCurrentBibleTextCommand() {
+
+ }
+
+ /**
+ * constructor for a version,reference combo
+ *
+ * @param version version to be used in the lookup (intials)
+ * @param reference reference to be used in the lookup (for e.g. Gen 1:1)
+ */
+ public GetCurrentBibleTextCommand(final String version, final String reference) {
+ this.version = version;
+ this.reference = reference;
+ }
+
+ /**
+ * @return the biblical reference (Gen 1:1-5 for example)
+ */
+ public String getReference() {
+ return reference;
+ }
+
+ /**
+ * @return the typeOfLookup
+ */
+ public final BibleTextLookupType getTypeOfLookup() {
+ return typeOfLookup;
+ }
+
+ /**
+ * @return the initials of the version to be used in the lookup
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * @param reference the reference to set
+ */
+ public void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ /**
+ * @param typeOfLookup the typeOfLookup to set
+ */
+ public final void setTypeOfLookup(final BibleTextLookupType typeOfLookup) {
+ this.typeOfLookup = typeOfLookup;
+ }
+
+ /**
+ * @param version the version to set
+ */
+ public void setVersion(final String version) {
+ this.version = version;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetDictionaryDefinitionCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetDictionaryDefinitionCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetDictionaryDefinitionCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,46 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import java.util.List;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.result.GetDictionaryDefinitionResult;
+
+/**
+ * dictionary definition command, contains the references to lookup
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetDictionaryDefinitionCommand implements Action<GetDictionaryDefinitionResult> {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -6139208624046856543L;
+
+ /**
+ * references to be looked up
+ */
+ private List<String> lookupReferencce;
+
+ /**
+ * the public constructor
+ */
+ public GetDictionaryDefinitionCommand() {
+
+ }
+
+ /**
+ * @return the lookupReferencce
+ */
+ public List<String> getLookupReferencce() {
+ return lookupReferencce;
+ }
+
+ /**
+ * @param lookupReferences the list lookupReferencce to set
+ */
+ public void setLookupReference(final List<String> lookupReferences) {
+ this.lookupReferencce = lookupReferences;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetEventsForDateRangeCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetEventsForDateRangeCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetEventsForDateRangeCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,78 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import java.util.List;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.common.timeline.TimeBandVisibleDate;
+import com.tyndalehouse.step.web.shared.result.GetEventsForDateRangeResult;
+
+/**
+ * Contains the details of a request for events within a particular date range.
+ * This contains a list of @see {@link TimeBandVisibleDate}, which records the
+ * portion of time to be requested from the server
+ *
+ * @author cjburrell
+ *
+ */
+public class GetEventsForDateRangeCommand implements Action<GetEventsForDateRangeResult> {
+ /**
+ * default uid
+ */
+ private static final long serialVersionUID = 5781027650600417430L;
+
+ /**
+ * whether to retrieve durations (this is a DEBUG flag really)
+ */
+ private boolean showDuration = true;
+
+ /**
+ * the list of timebands and the times that are currently showing
+ */
+ private List<TimeBandVisibleDate> visbleDates;
+
+ /**
+ * Used for serialization
+ */
+ public GetEventsForDateRangeCommand() {
+
+ }
+
+ /**
+ * default constructor that should be used
+ *
+ * @param visbleDates list of date ranges encapsulated in a
+ * TimeBandVisibleDate object
+ */
+ public GetEventsForDateRangeCommand(final List<TimeBandVisibleDate> visbleDates) {
+ this.visbleDates = visbleDates;
+ }
+
+ /**
+ * @return the visbleDates
+ */
+ public List<TimeBandVisibleDate> getVisbleDates() {
+ return visbleDates;
+ }
+
+ /**
+ * @return the showDuration
+ */
+ public boolean isShowDuration() {
+ return showDuration;
+ }
+
+ /**
+ * @param showDuration the showDuration to set
+ */
+ public void setShowDuration(final boolean showDuration) {
+ this.showDuration = showDuration;
+ }
+
+ /**
+ * @param visbleDates the visbleDates to set
+ */
+ public void setVisbleDates(final List<TimeBandVisibleDate> visbleDates) {
+ this.visbleDates = visbleDates;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetLocationsCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetLocationsCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetLocationsCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,21 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.result.GetLocationsResult;
+
+/**
+ * This command captures the input to the handler to query the server for all
+ * locations pertaining to a particular passage
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetLocationsCommand implements Action<GetLocationsResult> {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -4636855791737543490L;
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetTimelineOriginForScriptureCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetTimelineOriginForScriptureCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetTimelineOriginForScriptureCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,54 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.result.GetTimelineOriginForScriptureResult;
+
+/**
+ * The command to retrieve the best event given a verse range
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetTimelineOriginForScriptureCommand implements Action<GetTimelineOriginForScriptureResult> {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6454957611866927920L;
+ /**
+ * default uid
+ */
+
+ private String scriptureReference;
+
+ /**
+ * default constructor that should be used
+ *
+ * @param scriptureReference the biblical reference/range to be looked up
+ */
+ public GetTimelineOriginForScriptureCommand(final String scriptureReference) {
+ this.scriptureReference = scriptureReference;
+ }
+
+ /**
+ * Used for serialization
+ */
+ @SuppressWarnings("unused")
+ private GetTimelineOriginForScriptureCommand() {
+
+ }
+
+ /**
+ * @return the scriptureReference
+ */
+ public String getScriptureReference() {
+ return scriptureReference;
+ }
+
+ /**
+ * @param scriptureReference the scriptureReference to set
+ */
+ public void setScriptureReference(final String scriptureReference) {
+ this.scriptureReference = scriptureReference;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetTimelineUISetupCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetTimelineUISetupCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/GetTimelineUISetupCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,27 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.result.GetTimelineUISetupResult;
+
+/**
+ * command to request all the initial information useful to set up a timeline
+ * component, including the list of timebands, their recommended units, etc.
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetTimelineUISetupCommand implements Action<GetTimelineUISetupResult> {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 7813083800240239846L;
+
+ /**
+ * public constructor
+ */
+ public GetTimelineUISetupCommand() {
+
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/InstallJswordModuleCommand.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/InstallJswordModuleCommand.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/command/InstallJswordModuleCommand.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,45 @@
+package com.tyndalehouse.step.web.shared.command;
+
+import net.customware.gwt.dispatch.shared.Action;
+
+import com.tyndalehouse.step.web.shared.result.InstallJswordModuleResult;
+
+/**
+ * Requests the server (or local server) to install a bible version
+ *
+ * @author CJBurrell
+ *
+ */
+public class InstallJswordModuleCommand implements Action<InstallJswordModuleResult> {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 3416377875572322721L;
+
+ /**
+ * the initials to be used to check/install the book
+ */
+ private String initials;
+
+ /**
+ * the install jsword module command constructor
+ */
+ public InstallJswordModuleCommand() {
+
+ }
+
+ /**
+ * @return the initials of module to be installed
+ */
+ public String getInitials() {
+ return initials;
+ }
+
+ /**
+ * @param initials the initials of the module to set
+ */
+ public void setInitials(final String initials) {
+ this.initials = initials;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/GeoLocation.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/GeoLocation.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/GeoLocation.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,140 @@
+package com.tyndalehouse.step.web.shared.common.maps;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Serialisable POJO containing all the data pertaining to displaying the
+ * location on the screen
+ *
+ * @author CJBurrell
+ *
+ */
+public class GeoLocation implements Serializable {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -2429722523530262993L;
+
+ /**
+ * description of the location
+ */
+ private String description;
+
+ /**
+ * value of the latitude
+ */
+ private long latitude;
+
+ /**
+ * List of lat longs
+ */
+ private List<LatLong> latlongs;
+
+ /**
+ * type of location, for e.g. a city, a memorial, a fountain, etc.
+ */
+ private GeoLocationType locationType;
+
+ /**
+ * value of the longitude
+ */
+ private long longitude;
+
+ /**
+ * Name of the place, for e.g. Golgotha
+ */
+ private String placeName;
+
+ /**
+ * default constructor
+ */
+ public GeoLocation() {
+ latlongs = new ArrayList<LatLong>();
+ }
+
+ /**
+ * @return the description
+ */
+ public final String getDescription() {
+ return description;
+ }
+
+ /**
+ * @return the latitude
+ */
+ public final long getLatitude() {
+ return latitude;
+ }
+
+ /**
+ * @return the latlongs
+ */
+ public final List<LatLong> getLatlongs() {
+ return latlongs;
+ }
+
+ /**
+ * @return the locationType
+ */
+ public final GeoLocationType getLocationType() {
+ return locationType;
+ }
+
+ /**
+ * @return the longitude
+ */
+ public final long getLongitude() {
+ return longitude;
+ }
+
+ /**
+ * @return the placeName
+ */
+ public final String getPlaceName() {
+ return placeName;
+ }
+
+ /**
+ * @param description the description to set
+ */
+ public final void setDescription(final String description) {
+ this.description = description;
+ }
+
+ /**
+ * @param latitude the latitude to set
+ */
+ public final void setLatitude(final long latitude) {
+ this.latitude = latitude;
+ }
+
+ /**
+ * @param latlongs the latlongs to set
+ */
+ public final void setLatlongs(final List<LatLong> latlongs) {
+ this.latlongs = latlongs;
+ }
+
+ /**
+ * @param locationType the locationType to set
+ */
+ public final void setLocationType(final GeoLocationType locationType) {
+ this.locationType = locationType;
+ }
+
+ /**
+ * @param longitude the longitude to set
+ */
+ public final void setLongitude(final long longitude) {
+ this.longitude = longitude;
+ }
+
+ /**
+ * @param placeName the placeName to set
+ */
+ public final void setPlaceName(final String placeName) {
+ this.placeName = placeName;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/GeoLocationType.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/GeoLocationType.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/GeoLocationType.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,18 @@
+package com.tyndalehouse.step.web.shared.common.maps;
+
+/**
+ * Type of location, indicating whether the location is a city, a wall, a
+ * region, etc.
+ *
+ * @author CJBurrell
+ *
+ */
+public enum GeoLocationType {
+ /** CITY */
+ CITY,
+ /** A FOUNTAIN */
+ FOUNTAIN,
+ /** A REGION */
+ REGION,
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/LatLong.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/LatLong.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/maps/LatLong.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,47 @@
+package com.tyndalehouse.step.web.shared.common.maps;
+
+/**
+ * LatLong POJO containg the latitude and longitude of a point on a map
+ *
+ * @author CJBurrell
+ *
+ */
+public class LatLong {
+ /**
+ * latitude of the point
+ */
+ private long latitude;
+
+ /**
+ * longitude of the point
+ */
+ private long longitude;
+
+ /**
+ * @return the latitude
+ */
+ public final long getLatitude() {
+ return latitude;
+ }
+
+ /**
+ * @return the longitude
+ */
+ public final long getLongitude() {
+ return longitude;
+ }
+
+ /**
+ * @param latitude the latitude to set
+ */
+ public final void setLatitude(final long latitude) {
+ this.latitude = latitude;
+ }
+
+ /**
+ * @param longitude the longitude to set
+ */
+ public final void setLongitude(final long longitude) {
+ this.longitude = longitude;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/scripturelookup/BibleTextLookupType.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/scripturelookup/BibleTextLookupType.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/scripturelookup/BibleTextLookupType.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,20 @@
+package com.tyndalehouse.step.web.shared.common.scripturelookup;
+
+/**
+ * This enum indicates what kind of lookup is required from the server
+ *
+ * @author CJBurrell
+ *
+ */
+public enum BibleTextLookupType {
+ /** a classic interlinear is required */
+ CLASSIC_INTERLINEAR,
+ /** a logical form, POJO form of the text is required */
+ LOGICAL,
+ /** only the text is required */
+ PLAIN_TEXT,
+ /** a reverse interlinear is required */
+ REVERSE_INTERLINEAR,
+ /** the text, using a default xslt is required */
+ XSLT,
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimeBandVisibleDate.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimeBandVisibleDate.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimeBandVisibleDate.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,136 @@
+package com.tyndalehouse.step.web.shared.common.timeline;
+
+import java.io.Serializable;
+
+/**
+ * This object acts as a container of the current display window on an ether.
+ * timebandId identifies the timeband and is associated with a minimum and a
+ * maximum date which are generally used to request things off the database.
+ *
+ * TODO: harmonize capital letters to be TimebandVisibleDate
+ *
+ * @author cjburrell
+ *
+ */
+public class TimeBandVisibleDate implements Serializable {
+
+ /**
+ * default serial id
+ */
+ private static final long serialVersionUID = -7384255321830177509L;
+
+ /**
+ * max date visible on the timeband
+ */
+ private long maxDate;
+
+ /**
+ * min date visible on the time band
+ */
+ private long minDate;
+
+ /**
+ * true indicates no request is required on the server
+ */
+ private boolean noRequest;
+
+ /**
+ * time band id
+ */
+ private int timebandId;
+
+ /**
+ * so that
+ *
+ * @param timebandId the timebandId referred to in the module
+ * @param minDate minDate in the range of dates to ask the server
+ * @param maxDate maxDate in the range of dates to the ask the server
+ */
+ public TimeBandVisibleDate(final int timebandId, final long minDate, final long maxDate) {
+ this.timebandId = timebandId;
+ this.minDate = minDate;
+ this.maxDate = maxDate;
+ noRequest = false;
+ }
+
+ /**
+ * removing default constructor from view of other callers. Only accessible
+ * through reflection, and therefore GWT
+ */
+ private TimeBandVisibleDate() {
+ }
+
+ /**
+ * returns a TimeBandVisibleDate object tagged to indicate no request is
+ * required on the server
+ *
+ * @return a marked TimeBandVisibleDate object, marked with a flag saying no
+ * request is required
+ */
+ public static TimeBandVisibleDate getNoRequest() {
+ final TimeBandVisibleDate tvd = new TimeBandVisibleDate();
+ tvd.setNoRequest(true);
+ return tvd;
+ }
+
+ /**
+ * @return the maxDate
+ */
+ public long getMaxDate() {
+ return maxDate;
+ }
+
+ /**
+ * @return the minDate
+ */
+ public long getMinDate() {
+ return minDate;
+ }
+
+ /**
+ * @return the timebandId
+ */
+ public int getTimebandId() {
+ return timebandId;
+ }
+
+ /**
+ * NoRequest determines whether the values in here should be sent back.
+ * Perhaps we've got everything we need already, so we don't need to send
+ * anything back to the server
+ *
+ * @return the noRequest
+ */
+ public boolean isNoRequest() {
+ return noRequest;
+ }
+
+ /**
+ * @param maxDate the maxDate to set
+ */
+ public void setMaxDate(final long maxDate) {
+ this.maxDate = maxDate;
+ }
+
+ /**
+ * @param minDate the minDate to set
+ */
+ public void setMinDate(final long minDate) {
+ this.minDate = minDate;
+ }
+
+ /**
+ * @param noRequest the noRequest to set
+ */
+ public void setNoRequest(final boolean noRequest) {
+ this.noRequest = noRequest;
+ }
+
+ /**
+ * @param timebandId the timebandId to set
+ */
+ public void setTimebandId(final int timebandId) {
+ this.timebandId = timebandId;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimelineBean.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimelineBean.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimelineBean.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,130 @@
+package com.tyndalehouse.step.web.shared.common.timeline;
+
+import java.io.Serializable;
+
+/**
+ * Timeline bean represents the different timelines on which events can be
+ * found... TODO: should this be renamed timeband?
+ *
+ * @author CJBurrell
+ *
+ */
+public class TimelineBean implements Serializable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1734142151232501392L;
+
+ /**
+ * Timeline description from the server layer
+ */
+ private String timelineDescription;
+
+ /**
+ * timeline id sent across the wire
+ */
+ private int timelineId;
+
+ /**
+ * unit to be used when first display the timeband
+ */
+ private String unit;
+
+ /**
+ * default constructor made public
+ */
+ public TimelineBean() {
+
+ }
+
+ /**
+ * @return the timelineDescription
+ */
+ public String getTimelineDescription() {
+ return timelineDescription;
+ }
+
+ /**
+ * @return the timelineId
+ */
+ public int getTimelineId() {
+ return timelineId;
+ }
+
+ /**
+ * @return the unit
+ */
+ public String getUnit() {
+ return unit;
+ }
+
+ /**
+ * @param timelineDescription the timelineDescription to set
+ */
+ public void setTimelineDescription(final String timelineDescription) {
+ this.timelineDescription = timelineDescription;
+ }
+
+ /**
+ * @param timelineId the timelineId to set
+ */
+ public void setTimelineId(final int timelineId) {
+ this.timelineId = timelineId;
+ }
+
+ /**
+ * sets the unit field
+ *
+ * @param unit the unit to be set
+ */
+ public void setUnit(final String unit) {
+ this.unit = unit;
+
+ }
+
+ // /**
+ // * @return the minDate
+ // */
+ // public long getMinDate() {
+ // return minDate;
+ // }
+ //
+ // /**
+ // * @param minDate the minDate to set
+ // */
+ // public void setMinDate(long minDate) {
+ // this.minDate = minDate;
+ // }
+ //
+ // /**
+ // * @return the maxDate
+ // */
+ // public long getMaxDate() {
+ // return maxDate;
+ // }
+ //
+ // /**
+ // * @param maxDate the maxDate to set
+ // */
+ // public void setMaxDate(long maxDate) {
+ // this.maxDate = maxDate;
+ // }
+
+ // /**
+ // * @return the timelineCode
+ // */
+ // public String getTimelineCode() {
+ // return timelineCode;
+ // }
+ //
+ // public void setEventCount(int eventCount) {
+ // this.eventCount = eventCount;
+ // }
+ //
+ // /**
+ // * @return the eventCount
+ // */
+ // public int getEventCount() {
+ // return eventCount;
+ // }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimelineEventBean.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimelineEventBean.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/common/timeline/TimelineEventBean.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,235 @@
+package com.tyndalehouse.step.web.shared.common.timeline;
+
+import java.io.Serializable;
+
+/**
+ * An Time Event bean, containing all the relevant fields passed from the server
+ * to the client. For e.g. the description of the event, its id, the dates, etc.
+ *
+ * @author cjburrell
+ *
+ */
+public class TimelineEventBean implements Serializable {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -7664806988001700477L;
+
+ /**
+ * The certainty of dating, as provided in input CSV files
+ */
+ private String certainty;
+
+ /**
+ * the event id
+ */
+ private int eventId;
+
+ /**
+ * the type of the event, where we distinguish battles, from births, etc.
+ * (TODO: still to be done)
+ */
+ private int eventTypeId;
+
+ /**
+ * the from date
+ */
+ private Long fromDate;
+
+ /**
+ * how precise the date is, whether to the day, month, etc. see schema
+ * definition for details
+ */
+ private String fromPrecision;
+
+ /**
+ * Name/Description of the event
+ */
+ private String name;
+
+ /**
+ * The timeband/timeline on which the event should be displayed
+ */
+ private int timelineId;
+
+ /**
+ * the to-date in the case of a duration
+ */
+ private Long toDate;
+
+ /**
+ * the precision of the "to-date", whether to the day, month, etc. see
+ * schema definition for details
+ */
+ private String toPrecision;
+
+ /**
+ * making public
+ */
+ public TimelineEventBean() {
+
+ }
+
+ /**
+ * a constructor to set up everything in one go
+ *
+ * @param eventId the event id from the database
+ * @param fromDate the from date, at which the event starts/is
+ * @param toDate the to date, if the date is a duratio
+ * @param fromPrecision how precise the from date is (see schema for more
+ * details)
+ * @param toPrecision how precise the to date is (see schema for more
+ * details)
+ * @param name the description of the event
+ * @param timelineId the timeband on which to be located
+ * @param importanceId the importance id as defined in the input files
+ * @param certainty the certainty as defined in the input files
+ * @param eventTypeId the event type, describing different types, and
+ * therefore different representations of the event on the UI
+ *
+ */
+ // CHECKSTYLE:OFF
+ public TimelineEventBean(final int eventId, final Long fromDate, final Long toDate,
+ final String fromPrecision, final String toPrecision, final String name, final int timelineId,
+ final int importanceId, final String certainty, final int eventTypeId) {
+ // CHECKSTYLE:ON
+ this.eventId = eventId;
+ this.fromDate = fromDate;
+ this.toDate = toDate;
+ this.fromPrecision = fromPrecision;
+ this.toPrecision = toPrecision;
+ this.timelineId = timelineId;
+ this.certainty = certainty;
+ this.eventTypeId = eventTypeId;
+ this.name = name;
+ }
+
+ /**
+ * @return the certainty
+ */
+ public String getCertainty() {
+ return certainty;
+ }
+
+ /**
+ * @return the eventId
+ */
+ public int getEventId() {
+ return eventId;
+ }
+
+ /**
+ * @return the eventTypeId
+ */
+ public int getEventTypeId() {
+ return eventTypeId;
+ }
+
+ /**
+ * @return the fromDate
+ */
+ public Long getFromDate() {
+ return fromDate;
+ }
+
+ /**
+ * @return the fromPrecision
+ */
+ public String getFromPrecision() {
+ return fromPrecision;
+ }
+
+ /**
+ * returns the name/description of the event
+ *
+ * @return the description of the event
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the timelineId
+ */
+ public int getTimelineId() {
+ return timelineId;
+ }
+
+ /**
+ * @return the toDate
+ */
+ public Long getToDate() {
+ return toDate;
+ }
+
+ /**
+ * @return the toPrecision
+ */
+ public String getToPrecision() {
+ return toPrecision;
+ }
+
+ /**
+ * @param certainty the certainty to set
+ */
+ public void setCertainty(final String certainty) {
+ this.certainty = certainty;
+ }
+
+ /**
+ * @param eventId the eventId to set
+ */
+ public void setEventId(final int eventId) {
+ this.eventId = eventId;
+ }
+
+ /**
+ * @param eventTypeId the eventTypeId to set
+ */
+ public void setEventTypeId(final int eventTypeId) {
+ this.eventTypeId = eventTypeId;
+ }
+
+ /**
+ * @param fromDate the fromDate to set
+ */
+ public void setFromDate(final Long fromDate) {
+ this.fromDate = fromDate;
+ }
+
+ /**
+ * @param fromPrecision the fromPrecision to set
+ */
+ public void setFromPrecision(final String fromPrecision) {
+ this.fromPrecision = fromPrecision;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ /**
+ * @param timelineId the timelineId to set
+ */
+ public void setTimelineId(final int timelineId) {
+ this.timelineId = timelineId;
+ }
+
+ /**
+ * @param toDate the toDate to set
+ */
+ public void setToDate(final Long toDate) {
+ this.toDate = toDate;
+ }
+
+ /**
+ * @param toPrecision the toPrecision to set
+ */
+ public void setToPrecision(final String toPrecision) {
+ this.toPrecision = toPrecision;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetAvailableBibleVersionsResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetAvailableBibleVersionsResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetAvailableBibleVersionsResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,54 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import java.util.Collections;
+import java.util.SortedMap;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+/**
+ * This is in response to a @see
+ * {@link com.tyndalehouse.step.web.share.command.GetAvailableBibleVersionsCommand}
+ * In essence, this contains a sorted map of books to be displayed on the UI.
+ * The intials are the key into JSword and should be used at all times when sent
+ * back to the server.
+ *
+ * @author cjburrell
+ *
+ */
+public class GetAvailableBibleVersionsResult implements Result {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 1441380470741483969L;
+
+ /**
+ * a map keyed from the initials (link into JSword) to the name of the book
+ */
+ private SortedMap<String, String> books;
+
+ /**
+ * constructor passing in the map of available bible versions
+ *
+ * @param map map containing combinations of (key, book name)
+ */
+ public GetAvailableBibleVersionsResult(final SortedMap<String, String> map) {
+ this.books = map;
+ }
+
+ /**
+ * used for reflection
+ */
+ @SuppressWarnings("unused")
+ private GetAvailableBibleVersionsResult() {
+
+ }
+
+ /**
+ * the map of available books
+ *
+ * @return the map of available books
+ */
+ public SortedMap<String, String> getBooks() {
+ return Collections.unmodifiableSortedMap(books);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetBibleBooksCommandResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetBibleBooksCommandResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetBibleBooksCommandResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,52 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+/**
+ * Result from the GetBibleBooksCommand which contains the list of books
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetBibleBooksCommandResult implements Result {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -26170538247007172L;
+
+ /**
+ * the list of books
+ */
+ private List<String> books;
+
+ /**
+ * the list of bible books provided to the constructor
+ *
+ * @param books the list of books
+ */
+ public GetBibleBooksCommandResult(final List<String> books) {
+ this.books = books;
+ }
+
+ /**
+ * this constructor is used for reflection and must be present
+ */
+ @SuppressWarnings("unused")
+ private GetBibleBooksCommandResult() {
+
+ }
+
+ /**
+ * returns a list of books
+ *
+ * @return the list of books
+ */
+ public Collection<String> getBooks() {
+ return Collections.unmodifiableList(books);
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetCurrentBibleTextResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetCurrentBibleTextResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetCurrentBibleTextResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,83 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+import com.tyndalehouse.step.web.shared.scripture.Passage;
+
+/**
+ * Result from a command, representing a biblical text
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetCurrentBibleTextResult implements Result {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5781394877510591218L;
+
+ /**
+ * the passage in logical form
+ */
+ private Passage passage;
+
+ /**
+ * the passage text
+ */
+ private String passageText;
+
+ /**
+ * The xslted text
+ */
+ private String xsltedText;
+
+ /**
+ * returns the logical form passage
+ *
+ * @return the logical form of the passage
+ */
+ public Passage getPassage() {
+ return passage;
+ }
+
+ /**
+ * returns the passage text
+ *
+ * @return the passage text
+ */
+ public String getPassageText() {
+ return passageText;
+ }
+
+ /**
+ * @return the xsltedText
+ */
+ public String getXsltedText() {
+ return xsltedText;
+ }
+
+ /**
+ * sets the logical form of the passage
+ *
+ * @param p passage
+ */
+ public void setPassage(final Passage p) {
+ this.passage = p;
+ }
+
+ /**
+ * @param passageText the passageText to set
+ */
+ public void setPassageText(final String passageText) {
+ this.passageText = passageText;
+ }
+
+ /**
+ * @param xsltedText the xsltedText to set
+ */
+ public void setXsltedText(final String xsltedText) {
+ this.xsltedText = xsltedText;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetDictionaryDefinitionResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetDictionaryDefinitionResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetDictionaryDefinitionResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,53 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+/**
+ * The dictionary definition that was looked up from the
+ * GetDictionaryDefinitionCommand
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetDictionaryDefinitionResult implements Result {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 3121326970467885008L;
+
+ /**
+ * the xslted definition of the definition that was looked up
+ */
+ private String xsltedDefinition;
+
+ /**
+ * Default constructor
+ */
+ public GetDictionaryDefinitionResult() {
+
+ }
+
+ /**
+ * @return the xsltedDefinition
+ */
+ public String getXsltedDefinition() {
+ return xsltedDefinition;
+ }
+
+ /**
+ * sets the definition
+ *
+ * @param xsltedDefinition the definition to be set
+ */
+ public void setDefinition(final String xsltedDefinition) {
+ this.xsltedDefinition = xsltedDefinition;
+ }
+
+ /**
+ * @param xsltedDefinition the xsltedDefinition to set
+ */
+ public void setXsltedDefinition(final String xsltedDefinition) {
+ this.xsltedDefinition = xsltedDefinition;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetEventsForDateRangeResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetEventsForDateRangeResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetEventsForDateRangeResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,56 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineEventBean;
+
+/**
+ * Result containing all events requested within a particular date range.
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetEventsForDateRangeResult implements Result {
+
+ /**
+ * default serial id
+ */
+ private static final long serialVersionUID = 7118668612721569823L;
+
+ /** list of events */
+ private List<TimelineEventBean> events = new ArrayList<TimelineEventBean>();
+
+ /**
+ * public constructor
+ */
+ public GetEventsForDateRangeResult() {
+
+ }
+
+ /**
+ * Adds a new Event in Tim to the response
+ *
+ * @param teb the event to add to the response
+ */
+ public void add(final TimelineEventBean teb) {
+ getEvents().add(teb);
+
+ }
+
+ /**
+ * @return a list of events within a specified date range
+ */
+ public List<TimelineEventBean> getEvents() {
+ return events;
+ }
+
+ /**
+ * @param events the events to set
+ */
+ public void setEvents(final List<TimelineEventBean> events) {
+ this.events = events;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetLocationsResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetLocationsResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetLocationsResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,50 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+import com.tyndalehouse.step.web.shared.common.maps.GeoLocation;
+
+/**
+ * This object contains the result from a geographical location, containing
+ * enough data to display a marker on the screen, and a hover over.
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetLocationsResult implements Result {
+
+ /**
+ * serial id for serialisation
+ */
+ private static final long serialVersionUID = 1516648078862839012L;
+
+ /**
+ * list of locations
+ */
+ private List<GeoLocation> locations;
+
+ /**
+ * default constructor
+ */
+ public GetLocationsResult() {
+ locations = new ArrayList<GeoLocation>();
+ }
+
+ /**
+ * @return the locations
+ */
+ public final List<GeoLocation> getLocations() {
+ return locations;
+ }
+
+ /**
+ * @param locations the locations to set
+ */
+ public final void setLocations(final List<GeoLocation> locations) {
+ this.locations = locations;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetTimelineOriginForScriptureResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetTimelineOriginForScriptureResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetTimelineOriginForScriptureResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,131 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+import com.tyndalehouse.step.web.shared.timeline.Unit;
+
+/**
+ * Result from querying the server for the best event to use as the origin of
+ * the timeline. This event is the one that best suits the verse range provided
+ * by the user
+ *
+ * @author CJBurrell
+ *
+ */
+public class GetTimelineOriginForScriptureResult implements Result {
+ /**
+ * generated serial version id
+ */
+ private static final long serialVersionUID = 4256230588330550554L;
+
+ /**
+ * whether no data was returned, because no events matched the biblical
+ * reference
+ */
+ private boolean isEmpty;
+
+ /**
+ * the date of the recommended
+ */
+ private Long originDate;
+
+ /**
+ * the suggested timescale the UI should use
+ */
+ private Unit suggestedTimeScale;
+
+ /**
+ * the timeband id on which this date should be used
+ */
+ private int timebandId;
+
+ /**
+ * public constructor for this result object
+ *
+ * @param isEmpty true if no data was found
+ */
+ public GetTimelineOriginForScriptureResult(final boolean isEmpty) {
+ this.isEmpty = isEmpty;
+ }
+
+ /**
+ * another constructor to provide the correct origin information, including
+ *
+ * @param originDate the date at which the timeline should be positioned
+ * @param unit the unit that should be used for this timeband
+ * @param timebandId the timeband id
+ */
+ public GetTimelineOriginForScriptureResult(final Long originDate, final Unit unit, final int timebandId) {
+ this.originDate = originDate;
+ this.suggestedTimeScale = unit;
+ this.timebandId = timebandId;
+ isEmpty = false;
+ }
+
+ /**
+ * private constructor, used by GWT serialisation
+ */
+ @SuppressWarnings("unused")
+ private GetTimelineOriginForScriptureResult() {
+
+ }
+
+ /**
+ * @return the originDate
+ */
+ public Long getOriginDate() {
+ return originDate;
+ }
+
+ /**
+ * @return the suggestedTimeScale
+ */
+ public Unit getSuggestedTimeScale() {
+ return suggestedTimeScale;
+ }
+
+ /**
+ * gets the timeband id
+ *
+ * @return timebandId
+ */
+ public int getTimebandId() {
+ return timebandId;
+ }
+
+ /**
+ * @return the isEmpty
+ */
+ public boolean isEmpty() {
+ return isEmpty;
+ }
+
+ /**
+ * @param isEmpty the isEmpty to set
+ */
+ public void setEmpty(final boolean isEmpty) {
+ this.isEmpty = isEmpty;
+ }
+
+ /**
+ * @param originDate the originDate to set
+ */
+ public void setOriginDate(final Long originDate) {
+ this.originDate = originDate;
+ }
+
+ /**
+ * @param unit the suggestedTimeScale to set
+ */
+ public void setSuggestedTimeScale(final Unit unit) {
+ this.suggestedTimeScale = unit;
+ }
+
+ /**
+ * @param timebandId the timebandId to set
+ */
+ public void setTimebandId(final int timebandId) {
+ this.timebandId = timebandId;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetTimelineUISetupResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetTimelineUISetupResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/GetTimelineUISetupResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,53 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import java.util.List;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+import com.tyndalehouse.step.web.shared.common.timeline.TimelineBean;
+
+/**
+ * Response from a @see
+ * {@link com.tyndalehouse.step.web.shared.command.GetTimelineUISetupCommand}
+ * This contains details on how to set up each timeband, their units, etc.
+ *
+ * @author cjburrell
+ *
+ */
+public class GetTimelineUISetupResult implements Result {
+
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -566447989637280143L;
+
+ /**
+ * A list of timebands
+ */
+ private List<TimelineBean> tlb;
+
+ /**
+ * Default constructor made public
+ */
+ public GetTimelineUISetupResult() {
+
+ }
+
+ /**
+ * returns a list of timebands
+ *
+ * @return a list of timeband beans
+ */
+ public List<TimelineBean> getTimelines() {
+ return tlb;
+ }
+
+ /**
+ * sets the list. made available for reflection
+ *
+ * @param tlb the list of timeline beans
+ */
+ public void setTimelines(final List<TimelineBean> tlb) {
+ this.tlb = tlb;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/InstallJswordModuleResult.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/InstallJswordModuleResult.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/result/InstallJswordModuleResult.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,54 @@
+package com.tyndalehouse.step.web.shared.result;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+/**
+ * Response from a @see
+ * {@link com.tyndalehouse.step.web.shared.command.InstallJswordModuleCommand}
+ * indicating whether the installation was succesful
+ *
+ * @author cjburrell
+ *
+ */
+public class InstallJswordModuleResult implements Result {
+ /**
+ * generated serial id
+ */
+ private static final long serialVersionUID = -5063510082176727310L;
+
+ /**
+ * true if installation was successful
+ */
+ private boolean successful;
+
+ /**
+ * Default constructor made public
+ */
+ public InstallJswordModuleResult() {
+
+ }
+
+ /**
+ * Constructor with the success flag passed in
+ *
+ * @param successful true to indicate success
+ */
+ public InstallJswordModuleResult(final boolean successful) {
+ this.successful = successful;
+
+ }
+
+ /**
+ * @return the successful
+ */
+ public boolean isSuccessful() {
+ return successful;
+ }
+
+ /**
+ * @param successful the successful to set
+ */
+ public void setSuccessful(final boolean successful) {
+ this.successful = successful;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Milestone.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Milestone.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Milestone.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,61 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+import java.io.Serializable;
+
+/**
+ * A marker in the OSIS xml to indicate a break in the normal flow of text.
+ * Usually editors layouts, I believe.
+ *
+ * @author cjburrell
+ *
+ */
+public class Milestone extends Text implements TextualElement, Serializable {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 6444472622836494795L;
+
+ /**
+ * optional marker
+ */
+ private String marker;
+
+ /**
+ * Type of milestone, see OSIS details for clarifications
+ */
+ private String type;
+
+ /**
+ * Default constructor made public
+ */
+ public Milestone() {
+ }
+
+ /**
+ * @return the marker
+ */
+ public String getMarker() {
+ return marker;
+ }
+
+ /**
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * @param marker the marker to set
+ */
+ public void setMarker(final String marker) {
+ this.marker = marker;
+ }
+
+ /**
+ * @param type the type to set
+ */
+ public void setType(final String type) {
+ this.type = type;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Note.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Note.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Note.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,42 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+import java.io.Serializable;
+
+/**
+ * A logical representation of some OSIS xml. This bean is serialised and passed
+ * over the wire
+ *
+ * @author cjburrell
+ *
+ */
+public class Note extends Text implements TextualElement, Serializable {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 4592986819523938392L;
+
+ /**
+ * The type of note
+ */
+ private String type;
+
+ /**
+ * Default constructor made public
+ */
+ public Note() {
+ }
+
+ /**
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * @param type the type to set
+ */
+ public void setType(final String type) {
+ this.type = type;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/OSISConstants.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/OSISConstants.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/OSISConstants.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,43 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+/**
+ * Some constants not defined in JSword
+ *
+ * @author cjburrell
+ *
+ */
+public final class OSISConstants {
+ /**
+ * A marker in the text, for formatting purposes: TODO: check this and the
+ * other two with online people
+ */
+ public static final String MARKER = "marker";
+
+ /**
+ * A milestone, between two portions of scripture
+ */
+ public static final String MILESTONE = "milestone";
+
+ /**
+ * A decision by the translator to make a change?
+ */
+ public static final String TRANS_CHANGE = "transChange";
+
+ // public static final String LEMMA = "lemma";
+ // public static final String MORPH = "morph";
+ // public static final Object NOTE = "note";
+ // public static final String OSISID = "osisID";
+ // public static final String TITLE = "title";
+
+ // public static final String TYPE = "type";
+ // public static final String VERSE = "verse";
+ // public static final String WORD = "w";
+
+ /**
+ * Making the constructor private
+ */
+ private OSISConstants() {
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Passage.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Passage.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Passage.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,74 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Logical form of a passage
+ *
+ * @author CJBurrell
+ *
+ */
+public class Passage implements TextualElement, Serializable {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -3926440372519158967L;
+
+ /**
+ * List of verses/title throughout the passage
+ */
+ private List<VerseContent> verseContent;
+
+ /**
+ * making the constructor public and initialising list
+ */
+ public Passage() {
+ verseContent = new ArrayList<VerseContent>();
+ }
+
+ /**
+ * Adding a passage element, such as a {@link Verse} or a {@link Title}
+ *
+ * @param vc a verse or a title
+ */
+ public void addPassageElement(final VerseContent vc) {
+ verseContent.add(vc);
+ }
+
+ /**
+ * returns the text representation of a passage. This is NOT performance
+ * optimized and therefore should not be used more than once.
+ * Non-optimization is due to the fact that we won't to reduce traffic over
+ * the wire
+ *
+ *TODO: this could be further optimized by not relying on strings in
+ * versecontent being returned as strings
+ *
+ * @return the passage in a string form.
+ */
+ public String getText() {
+ final StringBuffer text = new StringBuffer(1024);
+ for (final VerseContent vc : verseContent) {
+ if (!(vc instanceof Title)) {
+ text.append(vc.getText());
+ }
+ }
+ return text.toString();
+ }
+
+ /**
+ * @return the verseContent list of a combination of verses and titles
+ */
+ public List<VerseContent> getVerseContent() {
+ return verseContent;
+ }
+
+ /**
+ * @param verseContent the verseContent to set
+ */
+ public void setVerseContent(final List<VerseContent> verseContent) {
+ this.verseContent = verseContent;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Text.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Text.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Text.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,51 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+import java.io.Serializable;
+
+/**
+ * The Text class, a wrapper for String
+ *
+ * @author CJBurrell
+ *
+ */
+public class Text implements TextualElement, Serializable {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -7068301858306124428L;
+
+ /**
+ * the string representing the portion of scripture for each OSIS element
+ */
+ private String text;
+
+ /**
+ * A simple text, default constructor made public
+ */
+ public Text() {
+ }
+
+ /**
+ * Initialising a text with a String
+ *
+ * @param text text is the string representation of the #text element
+ */
+ public Text(final String text) {
+ this.text = text;
+ }
+
+ /**
+ * @return the text
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * @param text the text to set
+ */
+ public void setText(final String text) {
+ this.text = text;
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/TextualElement.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/TextualElement.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/TextualElement.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,18 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+/**
+ * Interface being applied to anything that can contains text (directly or
+ * indirectly)
+ *
+ * @author CJBurrell
+ *
+ */
+public interface TextualElement {
+
+ /**
+ * returns the text
+ *
+ * @return text to be returned
+ */
+ String getText();
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Title.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Title.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Title.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,43 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+/**
+ * Title element in the OSIS as a POJO
+ *
+ * @author CJBurrell
+ *
+ */
+public class Title extends Text implements VerseContent {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -4362500737203594954L;
+
+ /**
+ * Type of title as defined in OSIS spec
+ */
+ private String type;
+
+ /**
+ * Making default constructor public
+ */
+ public Title() {
+ }
+
+ /**
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * type of title
+ *
+ * @param type title
+ */
+ public void setType(final String type) {
+ this.type = type;
+
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/TransChange.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/TransChange.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/TransChange.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,41 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+import java.io.Serializable;
+
+/**
+ * TODO: check OSIS details and update documentation
+ *
+ * @author cjburrell
+ *
+ */
+public class TransChange extends Text implements TextualElement, Serializable {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = 4557607388014222750L;
+
+ /**
+ * Type of trans change
+ */
+ private String type;
+
+ /**
+ * Default constructor made public
+ */
+ public TransChange() {
+ }
+
+ /**
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * @param type the type to set
+ */
+ public void setType(final String type) {
+ this.type = type;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Verse.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Verse.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Verse.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,92 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Logical representation of a verse from the OSIS
+ *
+ * @author CJBurrell
+ *
+ */
+public class Verse implements VerseContent, Serializable {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -7000973434382091156L;
+
+ /**
+ * the OSIS key, for e.g. gen 1:1
+ */
+ private String osisID;
+
+ /**
+ * list of textual elements that are contained in this verse
+ */
+ private List<TextualElement> verseContent;
+
+ /**
+ * public constructor to create a logical form of a verse
+ */
+ public Verse() {
+ verseContent = new ArrayList<TextualElement>();
+ }
+
+ /**
+ * adds a textual element to the verse
+ *
+ * @param te textual element
+ */
+ public void addTextualElement(final TextualElement te) {
+ this.verseContent.add(te);
+ }
+
+ /**
+ * @return the osisID
+ */
+ public String getOsisID() {
+ return osisID;
+ }
+
+ /**
+ * This method is not optimized for performance. It iterates through the
+ * list each time it is required. The reason it is not optimized, is that it
+ * should not be used except to display the text once.
+ *
+ * Not storing the result of the concatenation enables us to have shorted
+ * messages going across the wire
+ *
+ * @return the concatenated text
+ */
+ public String getText() {
+ final StringBuilder sb = new StringBuilder(128);
+ for (final TextualElement te : verseContent) {
+ if (!(te instanceof Note)) {
+ sb.append(te.getText());
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * @return the text
+ */
+ public List<TextualElement> getVerseContent() {
+ return verseContent;
+ }
+
+ /**
+ * @param osisID the osisID to set
+ */
+ public void setOsisID(final String osisID) {
+ this.osisID = osisID;
+ }
+
+ /**
+ * @param text the text to set
+ */
+ public void setVerseContent(final List<TextualElement> text) {
+ this.verseContent = text;
+ }
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/VerseContent.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/VerseContent.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/VerseContent.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,12 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+/**
+ * This interfaces marks a verse or a title which are direct children of a
+ * passage
+ *
+ * @author CJBurrell
+ *
+ */
+public interface VerseContent extends TextualElement {
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Word.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Word.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/scripture/Word.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,137 @@
+package com.tyndalehouse.step.web.shared.scripture;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A Word is a portion of a verse from the Bible. It can be several words or
+ * just one. In some versions it is associated with a list of lemmas (strong
+ * numbers which link to the Strong Hebrew or Greek Dictionary), as well as a
+ * morphological code (morph) which is a coded form of the morphology of the
+ * word/set of words (i.e. grammar form and usage in the sentence)
+ *
+ * @author cjburrell
+ *
+ */
+public class Word extends Text implements TextualElement, Serializable {
+ /**
+ * serial id
+ */
+ private static final long serialVersionUID = -5750252359953024623L;
+
+ /**
+ * An alternative word, such as a different language
+ */
+ private String alternativeWord;
+
+ // TODO: FIX: this is a bug, we can have several lemmas or morphologies for
+ // one translated word
+ /**
+ * a list of lemmas referring to a portion of text
+ */
+ private List<String> lemma;
+
+ /**
+ * A list of morphs referring to a portion of text. A morph is a coded
+ * string indicating the grammar and form of the original word
+ */
+ private List<String> morph;
+
+ /**
+ * default constructor initialises internal lists
+ */
+ public Word() {
+ lemma = new ArrayList<String>();
+ morph = new ArrayList<String>();
+ }
+
+ /**
+ * Adds a new lemma to the Word
+ *
+ * @param newLemma the lemma to set
+ */
+ public void addLemma(final String newLemma) {
+ lemma.add(newLemma);
+ }
+
+ /**
+ * Adds an array of lemmas to the Word
+ *
+ * @param lemmas a list of lemmas
+ */
+ public void addLemmas(final String[] lemmas) {
+ for (final String l : lemmas) {
+ this.lemma.add(l);
+ }
+ }
+
+ /**
+ * Adds an array of morphs to the Word
+ *
+ * @param morphs array of morphs to be associated with the Word (portion of
+ * a verse)
+ */
+ public void addMorphs(final String[] morphs) {
+ for (final String m : morphs) {
+ this.morph.add(m);
+ }
+
+ }
+
+ /**
+ * @return the alternativeWord
+ */
+ public String getAlternativeWord() {
+ return alternativeWord;
+ }
+
+ /**
+ * @return the lemma
+ */
+ public List<String> getLemma() {
+ return lemma;
+ }
+
+ /**
+ * @return the morph
+ */
+ public List<String> getMorph() {
+ return morph;
+ }
+
+ /**
+ * sets an alternative word (such as a hebrew original word)
+ *
+ * @param alternativeWord a word equivalent, different language. For e.g.
+ * Hebrew word
+ *
+ */
+ public void setAlternativeWord(final String alternativeWord) {
+ this.alternativeWord = alternativeWord;
+ }
+
+ /**
+ * @param lemma the lemma to set
+ */
+ public void setLemma(final List<String> lemma) {
+ this.lemma = lemma;
+ }
+
+ /**
+ * @param morph the morph to set
+ */
+ public void setMorph(final List<String> morph) {
+ this.morph = morph;
+ }
+
+ /**
+ * Adding a morph to the Word
+ *
+ * @param newMorph the morph to set
+ */
+ public void setMorph(final String newMorph) {
+ morph.add(newMorph);
+ }
+
+}
Added: trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/timeline/Unit.java
===================================================================
--- trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/timeline/Unit.java (rev 0)
+++ trunk/step-web-app/src/main/java/com/tyndalehouse/step/web/shared/timeline/Unit.java 2010-04-14 22:11:51 UTC (rev 120)
@@ -0,0 +1,100 @@
+package com.tyndalehouse.step.web.shared.timeline;
+
+/**
+ * Unit as used both on the server and on the ui This makes the correspondance
+ * between dates in milliseconds and their actual real dates
+ *
+ * @author CJBurrell
+ *
+ */
+public enum Unit {
+ /**
+ * century
+ */
+ CENTURY(10L * 10L * 365L * 24 * 3600 * 1000L, "yyyy G"),
+ /**
+ * day
+ */
+ DAY(24L * 3600L * 1000L, "dd MMM yyyy G"),
+ /**
+ * decade
+ */
+ DECADE(10L * 365L * 24 * 3600 * 1000L, "yyyy G"),
+ /**
+ * hour
+ */
+ HOUR(3600L * 1000L),
+ /**
+ * 1000 years
+ */
+ MILLENIUM(10L * 10L * 10L * 365L * 24 * 3600 * 1000L, "yyyy G"),
+ /**
+ * a minute
+ */
+ MINUTE(60L * 1000L),
+ /**
+ * a month
+ */
+ // CHECKSTYLE:OFF
+ MONTH((365L * 24L * 3600L * 1000L) / 12, "MMM yyyy G"),
+ // CHECKSTYLE:ON
+ /**
+ * a second
+ */
+ SECOND(1000L),
+ /**
+ * a week
+ *
+ */
+ WEEK(7L * 24L * 3600L * 1000L, "dd MMM yyyy G"),
+ /**
+ * a year
+ */
+ YEAR(365L * 24 * 3600 * 1000L, "yyyy G");
+
+ /**
+ * format to be applied when displaying
+ */
+ private final String format;
+ /**
+ * length of unit in milliseconds
+ */
+ private final long milliseconds;
+
+ /**
+ * constructor to create a unit, with a default format of dd MMM YYYY G
+ *
+ * @param milliseconds length of unit in milliseconds
+ */
+ Unit(final long milliseconds) {
+ this(milliseconds, "dd MMM YYYY G");
+ }
+
+ /**
+ * creates a unit enum
+ *
+ * @param milliseconds length of unit in milliseconds
+ * @param format format to be applied if different to default one of dd MMM
+ * YYYY G
+ */
+ Unit(final long milliseconds, final String format) {
+ this.format = format;
+ this.milliseconds = milliseconds;
+ }
+
+ /**
+ * returns the format to be used for the unit
+ *
+ * @return the format format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * @return the value In Milliseconds of the length of the unit
+ */
+ public long getMilliseconds() {
+ return milliseconds;
+ }
+}
More information about the Tynstep-svn
mailing list