[Tynstep-svn] r227 - in trunk/step: step-core step-core/src/main/java/com/tyndalehouse/step/core/data/common step-core/src/main/java/com/tyndalehouse/step/core/data/create step-core/src/main/java/com/tyndalehouse/step/core/data/entities step-core/src/main/java/com/tyndalehouse/step/core/guice/providers step-core/src/main/java/com/tyndalehouse/step/core/service step-core/src/main/java/com/tyndalehouse/step/core/service/impl step-core/src/main/java/com/tyndalehouse/step/core/utils step-core/src/main/resources step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline step-core/src/test/java/com/tyndalehouse/step/core/data/common step-core/src/test/java/com/tyndalehouse/step/core/data/entities step-core/src/test/java/com/tyndalehouse/step/core/service/impl step-parent step-web/src/main/java/com/tyndalehouse/step/guice step-web/src/main/java/com/tyndalehouse/step/models step-web/src/main/java/com/tyndalehouse/step/models/timeline step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl step-web/src/main/java/com/tyndalehouse/step/rest/controllers step-web/src/main/java/com/tyndalehouse/step/rest/framework step-web/src/main/webapp step-web/src/main/webapp/css step-web/src/main/webapp/js step-web/src/main/webapp/tempdev step-web/src/test/java/com/tyndalehouse/step/rest/controllers step-web/src/test/java/com/tyndalehouse/step/rest/framework
ChrisBurrell at crosswire.org
ChrisBurrell at crosswire.org
Tue May 10 00:02:46 MST 2011
Author: ChrisBurrell
Date: 2011-05-10 00:02:46 -0700 (Tue, 10 May 2011)
New Revision: 227
Added:
trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImplTest.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/
trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/DigestableTimeline.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/TimelineTranslator.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/
trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileEvent.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineImpl.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineTranslatorImpl.java
trunk/step/step-web/src/main/webapp/tempdev/
trunk/step/step-web/src/main/webapp/tempdev/events.json
Modified:
trunk/step/step-core/pom.xml
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/common/PartialDate.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/create/TimelineModuleLoader.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/entities/TimelineEvent.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/entities/User.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/DatabaseConfigProvider.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/DefaultInstallersProvider.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/TestData.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/TimelineService.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/UserDataService.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImpl.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/impl/UserDataServiceImpl.java
trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/PassageReferenceUtils.java
trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_ExileAndReturn.csv
trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_Global.csv
trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_Monarchy.csv
trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_PatriarchsToJudges.csv
trunk/step/step-core/src/main/resources/step.core.properties
trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/data/common/PartialDateTest.java
trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/data/entities/UserTest.java
trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/FavouritesServiceImplTest.java
trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/UserDataServiceImplTest.java
trunk/step/step-parent/pom.xml
trunk/step/step-web/src/main/java/com/tyndalehouse/step/guice/WebContextModule.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/FrontController.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/TimelineController.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/UserController.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/framework/ResponseCache.java
trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/framework/StepRequest.java
trunk/step/step-web/src/main/webapp/css/initial-layout.css
trunk/step/step-web/src/main/webapp/index.html
trunk/step/step-web/src/main/webapp/js/init.js
trunk/step/step-web/src/main/webapp/js/timeline.js
trunk/step/step-web/src/main/webapp/js/ui_hooks.js
trunk/step/step-web/src/main/webapp/panemenu.html
trunk/step/step-web/src/test/java/com/tyndalehouse/step/rest/controllers/FrontControllerTest.java
trunk/step/step-web/src/test/java/com/tyndalehouse/step/rest/framework/StepRequestTest.java
Log:
initial timeline sketches
Modified: trunk/step/step-core/pom.xml
===================================================================
--- trunk/step/step-core/pom.xml 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/pom.xml 2011-05-10 07:02:46 UTC (rev 227)
@@ -100,10 +100,10 @@
<artifactId>commons-collections</artifactId>
</dependency>
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- </dependency>
+<!-- <dependency>-->
+<!-- <groupId>commons-codec</groupId>-->
+<!-- <artifactId>commons-codec</artifactId>-->
+<!-- </dependency>-->
<!-- we don't always need this - depends on what version -->
<dependency>
@@ -142,6 +142,12 @@
<type>pom</type>
</dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+
+
<!-- transitive dependencies not picked up by jsword -->
<dependency>
<groupId>javatar</groupId>
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/common/PartialDate.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/common/PartialDate.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/common/PartialDate.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -5,9 +5,9 @@
import static org.apache.commons.lang.StringUtils.split;
import java.util.Calendar;
-import java.util.GregorianCalendar;
import org.apache.commons.lang.StringUtils;
+import org.joda.time.LocalDateTime;
import com.tyndalehouse.step.core.exceptions.StepInternalException;
@@ -32,7 +32,7 @@
/**
* The date to be represented (whether fully accurate or not)
*/
- private final Calendar c;
+ private final LocalDateTime localDateTime;
/**
* The precision specifier which tells us just quite how accurate the date is (year, month, day)
@@ -44,12 +44,12 @@
/**
* Public constructor to give us a partial date.
*
- * @param c date partial reprentation of a date
+ * @param ldt date partial representation of a date
* @param precision precision indicating how much of the date can be trusted day/month/year or month/year
* or just year
*/
- public PartialDate(final Calendar c, final PrecisionType precision) {
- this.c = c;
+ public PartialDate(final LocalDateTime ldt, final PrecisionType precision) {
+ this.localDateTime = ldt;
this.precision = precision;
}
@@ -86,7 +86,9 @@
*/
private static PartialDate getPartialDateFromArray(final String[] parts, final boolean negativeDate) {
final Calendar c = Calendar.getInstance();
+ final LocalDateTime translatedTime;
PrecisionType p;
+ final int multiplier = negativeDate ? -1 : 1;
try {
// length of field determines how much of the date has been specified
@@ -95,15 +97,17 @@
throw new StepInternalException("There weren't enough parts to this date");
case YEAR:
// only the year is specified, so use 1st of Jan Year
- c.set(parseInt(parts[0]), 1, 1);
+ translatedTime = new LocalDateTime(multiplier * parseInt(parts[0]), 1, 1, 0, 0);
p = PrecisionType.YEAR;
break;
case YEAR_AND_MONTH:
- c.set(parseInt(parts[0]), parseInt(parts[1]), 1);
+ translatedTime = new LocalDateTime(multiplier * parseInt(parts[0]), parseInt(parts[1]),
+ 1, 0, 0);
p = PrecisionType.MONTH;
break;
case YEAR_MONTH_AND_DAY:
- c.set(parseInt(parts[0]), parseInt(parts[1]), parseInt(parts[2]));
+ translatedTime = new LocalDateTime(multiplier * parseInt(parts[0]), parseInt(parts[1]),
+ parseInt(parts[2]), 0, 0);
p = PrecisionType.DAY;
break;
default:
@@ -113,19 +117,14 @@
throw new StepInternalException("Could not parse date into year, month or day.", nfe);
}
- c.set(Calendar.HOUR_OF_DAY, 0);
- c.set(Calendar.MINUTE, 0);
- if (negativeDate) {
- c.set(Calendar.ERA, GregorianCalendar.BC);
- }
- return new PartialDate(c, p);
+ return new PartialDate(translatedTime, p);
}
/**
* @return gets the internal date
*/
- public Calendar getDate() {
- return this.c;
+ public LocalDateTime getDate() {
+ return this.localDateTime;
}
/**
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/create/TimelineModuleLoader.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/create/TimelineModuleLoader.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/create/TimelineModuleLoader.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -153,12 +153,12 @@
event.setHotSpot(hotspots.get(data.getData(ii, HOTSPOT_COLUMN_NAME)));
event.setSummary(data.getData(ii, "Name"));
if (from.getPrecision() != PrecisionType.NONE) {
- event.setFromDate(from.getDate().getTimeInMillis());
+ event.setFromDate(from.getDate());
event.setFromPrecision(from.getPrecision());
}
if (to.getPrecision() != PrecisionType.NONE) {
- event.setToDate(to.getDate().getTimeInMillis());
+ event.setToDate(to.getDate());
event.setToPrecision(to.getPrecision());
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/entities/TimelineEvent.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/entities/TimelineEvent.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/entities/TimelineEvent.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -8,6 +8,8 @@
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
+import org.joda.time.LocalDateTime;
+
import com.avaje.ebean.annotation.CacheStrategy;
import com.tyndalehouse.step.core.data.common.PrecisionType;
@@ -26,10 +28,10 @@
private String summary;
@Column(nullable = true)
- private long fromDate;
+ private LocalDateTime fromDate;
@Column(nullable = true)
- private long toDate;
+ private LocalDateTime toDate;
@Column(nullable = true)
private PrecisionType fromPrecision;
@@ -57,28 +59,28 @@
/**
* @return the fromDate
*/
- public long getFromDate() {
+ public LocalDateTime getFromDate() {
return this.fromDate;
}
/**
* @param fromDate the fromDate to set
*/
- public void setFromDate(final long fromDate) {
+ public void setFromDate(final LocalDateTime fromDate) {
this.fromDate = fromDate;
}
/**
* @return the toDate
*/
- public long getToDate() {
+ public LocalDateTime getToDate() {
return this.toDate;
}
/**
* @param toDate the toDate to set
*/
- public void setToDate(final long toDate) {
+ public void setToDate(final LocalDateTime toDate) {
this.toDate = toDate;
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/entities/User.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/entities/User.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/data/entities/User.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -26,10 +26,13 @@
@Column
private String name;
- @Column
- private String password;
+ @Column(nullable = false)
+ private byte[] password;
- @Column
+ @Column(nullable = false)
+ private byte[] salt;
+
+ @Column(nullable = false)
private String emailAddress;
@Column
@@ -52,15 +55,15 @@
/**
* @return the password
*/
- public String getPassword() {
+ public byte[] getPassword() {
return this.password;
}
/**
* @param password the password to set
*/
- public void setPassword(final String password) {
- this.password = password;
+ public void setPassword(final byte[] password) {
+ this.password = password.clone();
}
/**
@@ -104,4 +107,18 @@
public void setCountry(final String country) {
this.country = country;
}
+
+ /**
+ * @return the salt
+ */
+ public byte[] getSalt() {
+ return this.salt;
+ }
+
+ /**
+ * @param salt the salt to set
+ */
+ public void setSalt(final byte[] salt) {
+ this.salt = salt.clone();
+ }
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/DatabaseConfigProvider.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/DatabaseConfigProvider.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/DatabaseConfigProvider.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -52,10 +52,10 @@
@Inject
public DatabaseConfigProvider(@Named("app.db.driver") final String driverClassName,
@Named("app.db.url") final String url, @Named("app.db.username") final String username,
- @Named("app.db.password") final String password,
- @Named("app.db.maxActive") final String maxActive, @Named("app.db.maxIdle") final String maxIdle,
- @Named("app.db.maxOpenStatement") final String maxOpenStatements,
- @Named("app.db.poolableStatements") final String poolableStatements,
+ @Named("app.db.password") final String password, @Named("app.db.maxActive") final int maxActive,
+ @Named("app.db.maxIdle") final int maxIdle,
+ @Named("app.db.maxOpenStatement") final int maxOpenStatements,
+ @Named("app.db.poolableStatements") final boolean poolableStatements,
@Named("app.db.validationQuery") final String validationQuery) {
this.driverClassName = driverClassName;
this.url = url;
@@ -63,11 +63,10 @@
this.password = password;
this.validationQuery = validationQuery;
- // TODO: add exception handling when i know how
- this.maxActive = Integer.parseInt(maxActive);
- this.maxIdle = Integer.parseInt(maxIdle);
- this.maxOpenStatements = Integer.parseInt(maxOpenStatements);
- this.poolStatements = Boolean.parseBoolean(poolableStatements);
+ this.maxActive = maxActive;
+ this.maxIdle = maxIdle;
+ this.maxOpenStatements = maxOpenStatements;
+ this.poolStatements = poolableStatements;
}
// CHECKSTYLE:ON
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/DefaultInstallersProvider.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/DefaultInstallersProvider.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/DefaultInstallersProvider.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -57,7 +57,6 @@
final Integer p = Integer.parseInt(proxyPort);
installer.setProxyPort(p.intValue());
} catch (final NumberFormatException e) {
- // TODO: work out how this should be thrown
throw new StepInternalException("Unable to parse port number " + proxyPort, e);
}
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/TestData.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/TestData.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/guice/providers/TestData.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -4,15 +4,16 @@
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.codec.digest.DigestUtils;
-
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.Transaction;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import com.tyndalehouse.step.core.data.create.Loader;
import com.tyndalehouse.step.core.data.entities.Bookmark;
import com.tyndalehouse.step.core.data.entities.History;
import com.tyndalehouse.step.core.data.entities.User;
+import com.tyndalehouse.step.core.service.UserDataService;
/**
* Provides test data if necessary
@@ -23,16 +24,26 @@
@Singleton
public class TestData {
private final EbeanServer ebean;
+ private final UserDataService userService;
+ private final int numCryptoIterations;
/**
* @param ebean the ebean server to persist objects with
+ * @param userService the user service to create a user
+ * @param numCryptoIterations the number of iterations to perform - we need since we hook in to the user
+ * data service from a different viewpoint
+ * @param loader the loader that should be called upon installation mainly
*/
@Inject
- public TestData(final EbeanServer ebean) {
+ public TestData(final EbeanServer ebean, final UserDataService userService,
+ @Named("app.security.numIterations") final int numCryptoIterations, final Loader loader) {
this.ebean = ebean;
+ this.userService = userService;
+ this.numCryptoIterations = numCryptoIterations;
final User u = getUser();
createBookmarks(u);
createHistory(u);
+ loader.init();
}
/**
@@ -75,15 +86,17 @@
}
/**
- * creates a user
- *
- * @return the user to be created
+ * @return a test user
*/
private User getUser() {
final User u = new User();
u.setEmailAddress("t at t.c");
u.setName("Mr Test");
- u.setPassword(new String(DigestUtils.sha512("password")));
+ final byte[] salt = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+ u.setPassword(this.userService.getHash(this.numCryptoIterations, "password", salt));
+ u.setSalt(salt);
+
+ // this.ebean.save(u);
return u;
}
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/TimelineService.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/TimelineService.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/TimelineService.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -2,7 +2,10 @@
import java.util.List;
+import org.joda.time.LocalDateTime;
+
import com.tyndalehouse.step.core.data.entities.Timeband;
+import com.tyndalehouse.step.core.data.entities.TimelineEvent;
/**
* The timeline service gives access to all the data relating to the timeline the events, the configuration,
@@ -23,4 +26,12 @@
*/
List<Timeband> getTimelineConfiguration();
+ /**
+ * Returns events that fall within a certain time period
+ *
+ * @param from from date
+ * @param to to date
+ * @return a list of timeline events contained between the two dates
+ */
+ List<TimelineEvent> getTimelineEvents(LocalDateTime from, LocalDateTime to);
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/UserDataService.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/UserDataService.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/UserDataService.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -50,4 +50,14 @@
* @return the logged in user if the user is logged in
*/
User getLoggedInUser();
+
+ /**
+ * From a password, a number of iterations and a salt, returns the corresponding digest
+ *
+ * @param iterationNb int The number of iterations of the algorithm
+ * @param password String The password to encrypt
+ * @param salt byte[] The salt
+ * @return The digested password
+ */
+ byte[] getHash(int iterationNb, String password, byte[] salt);
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImpl.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImpl.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImpl.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -2,10 +2,14 @@
import java.util.List;
+import org.joda.time.LocalDateTime;
+
import com.avaje.ebean.EbeanServer;
+import com.avaje.ebean.Query;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.tyndalehouse.step.core.data.entities.Timeband;
+import com.tyndalehouse.step.core.data.entities.TimelineEvent;
import com.tyndalehouse.step.core.service.TimelineService;
/**
@@ -25,23 +29,28 @@
this.ebean = ebean;
}
- // private final Loader loader;
-
- // /**
- // * Constructing a timeband dao
- // *
- // * @param timebandDao the data access object that can be used to access the timeband
- // */
- // @Inject
- // public TimelineServiceImpl(final TimebandDao timebandDao, final HotSpotDao hotSpotDao, final Loader
- // loader) {
- // // this.timebandDao = timebandDao;
- // // this.hotSpotDao = hotSpotDao;
- // this.loader = loader;
- // }
-
@Override
public List<Timeband> getTimelineConfiguration() {
return this.ebean.createQuery(Timeband.class).fetch("hotspots").findList();
}
+
+ @Override
+ public List<TimelineEvent> getTimelineEvents(final LocalDateTime from, final LocalDateTime to) {
+ // fromDate < to and toDate > from is the standard coverage method where we find the overlapping
+ // events
+ // however "toDate" can be null, therefore we need to cater for that
+
+ // which gives us
+ // fromDate < to and ((toDate != null and toDate > from) or (toDate == null and fromDate > from ))
+
+ // in other words the event starts before the requested period ends, but finishes after the end
+
+ final String eventsQuery = "find timelineEvent where fromDate <= :to and "
+ + "((toDate is not null and toDate >= :from) or (toDate is null and fromDate >= :from))";
+
+ final Query<TimelineEvent> query = this.ebean.createQuery(TimelineEvent.class, eventsQuery);
+ query.setParameter("from", from);
+ query.setParameter("to", to);
+ return query.findList();
+ }
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/impl/UserDataServiceImpl.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/impl/UserDataServiceImpl.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/service/impl/UserDataServiceImpl.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -2,6 +2,11 @@
import static com.avaje.ebean.Expr.eq;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -9,6 +14,7 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import com.google.inject.name.Named;
import com.tyndalehouse.step.core.data.entities.Session;
import com.tyndalehouse.step.core.data.entities.User;
import com.tyndalehouse.step.core.exceptions.StepInternalException;
@@ -24,7 +30,14 @@
*/
@Singleton
public class UserDataServiceImpl implements UserDataService {
+ private static final String USER_ID_FIELD = "id";
+ private static final String UNABLE_TO_LOGIN_MESSAGE = "Unable to login with username/password provided";
private static final Logger LOG = LoggerFactory.getLogger(UserDataServiceImpl.class);
+ private final int numCryptoIterations;
+ private final int saltLength;
+ private final String inputEncoding;
+ private final String hashingAlgorithm;
+ private final String saltingRandomAlgorithm;
private final Provider<Session> sessionProvider;
private final EbeanServer ebean;
@@ -33,11 +46,27 @@
*
* @param ebean the ebean server to persist and load data
* @param sessionProvider the session provider
+ * @param numCryptoIterations the number of iterations that should be performed when encrypting
+ * @param inputEncoding the encoding of the input password
+ * @param hashingAlgorithm what algorithm to use for hashing the password
+ * @param saltingRandomAlgorithm what algorithm to use for salting
+ * @param saltLength the length of the salt that should be obtained in bytes (e.g 8 for 64-bit)
*/
@Inject
- public UserDataServiceImpl(final EbeanServer ebean, final Provider<Session> sessionProvider) {
+ public UserDataServiceImpl(final EbeanServer ebean, final Provider<Session> sessionProvider,
+ @Named("app.security.numIterations") final int numCryptoIterations,
+ @Named("app.security.inputEncoding") final String inputEncoding,
+ @Named("app.security.hashingAlgorithm") final String hashingAlgorithm,
+ @Named("app.security.saltingAlgorithm") final String saltingRandomAlgorithm,
+ @Named("app.security.saltLength") final int saltLength) {
this.ebean = ebean;
this.sessionProvider = sessionProvider;
+ this.numCryptoIterations = numCryptoIterations;
+ this.inputEncoding = inputEncoding;
+ this.hashingAlgorithm = hashingAlgorithm;
+ this.saltingRandomAlgorithm = saltingRandomAlgorithm;
+ this.saltLength = saltLength;
+
}
@Override
@@ -54,11 +83,15 @@
}
// it is easy enough to register, just create a user and save to the database
+ // however we salt the password as we do...
+ final byte[] salt = getRandomSalt();
+
final User u = new User();
u.setEmailAddress(emailAddress);
u.setName(name);
u.setCountry(country);
- u.setPassword(password);
+ u.setPassword(getHash(this.numCryptoIterations, password, salt));
+ u.setSalt(salt);
this.ebean.save(u);
@@ -83,15 +116,32 @@
LOG.debug("Logging [{}] in to the system", emailAddress);
// logging in basically means associating the user with the session
- final User user = this.ebean.find(User.class).select("id, name").where()
- .and(eq("emailAddress", emailAddress), eq("password", password)).findUnique();
+ final User user = this.ebean.find(User.class).select("id, name, salt").where()
+ .eq("emailAddress", emailAddress).findUnique();
- // couldn't authenticate?
if (user == null) {
- throw new StepInternalException("Unable to login with username/password provided");
+ throw new StepInternalException(UNABLE_TO_LOGIN_MESSAGE);
}
- return login(user);
+ // compute salt and check password leaving password in DB (we could optimise, but
+ // that would require removing the encrypted password from the database (?)
+ final byte[] salt = user.getSalt();
+
+ final int matchingPasswords = this.ebean
+ .find(User.class)
+ .select(USER_ID_FIELD)
+ .where()
+ .and(eq(USER_ID_FIELD, user.getId()),
+ eq("password", getHash(this.numCryptoIterations, password, salt))).findRowCount();
+
+ // couldn't authenticate?
+ if (matchingPasswords != 1) {
+ throw new StepInternalException(UNABLE_TO_LOGIN_MESSAGE);
+ }
+
+ // WORKAROUND: ideally we want to be able to specify/annotate fields that should not be serialised
+ return login(this.ebean.find(User.class).select("id, name").where().eq(USER_ID_FIELD, user.getId())
+ .findUnique());
}
/**
@@ -114,4 +164,41 @@
// simply delete the session from the db
this.ebean.delete(this.sessionProvider.get());
}
+
+ /**
+ * @return a securely generated random salt
+ */
+ private byte[] getRandomSalt() {
+ SecureRandom random;
+ try {
+ random = SecureRandom.getInstance(this.saltingRandomAlgorithm);
+ final byte[] bSalt = new byte[this.saltLength];
+ random.nextBytes(bSalt);
+ return bSalt;
+ } catch (final NoSuchAlgorithmException e) {
+ throw new StepInternalException("Can't generate salt", e);
+ }
+ }
+
+ @Override
+ public byte[] getHash(final int iterationNb, final String password, final byte[] salt) {
+ MessageDigest digest;
+ byte[] input = null;
+ try {
+ digest = MessageDigest.getInstance(this.hashingAlgorithm);
+ digest.reset();
+ digest.update(salt);
+ input = digest.digest(password.getBytes(this.inputEncoding));
+ for (int i = 0; i < iterationNb; i++) {
+ digest.reset();
+ input = digest.digest(input);
+ }
+ } catch (final NoSuchAlgorithmException e) {
+ throw new StepInternalException("Unable to find encryption algorithm", e);
+ } catch (final UnsupportedEncodingException e) {
+ throw new StepInternalException("Unable carry out encryption", e);
+ }
+
+ return input;
+ }
}
Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/PassageReferenceUtils.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/PassageReferenceUtils.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/PassageReferenceUtils.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -63,7 +63,7 @@
LOG.trace("Found reference [{}] to [{}]", valueOf(startVerseId), valueOf(endVerseId));
final ScriptureReference sr = new ScriptureReference();
- // TODO: fix this:
+ // TODO: fix the broken references in csv files
sr.setTarget(target);
sr.setStartVerseId(startVerseId);
Modified: trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_ExileAndReturn.csv
===================================================================
--- trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_ExileAndReturn.csv 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_ExileAndReturn.csv 2011-05-10 07:02:46 UTC (rev 227)
@@ -22,7 +22,7 @@
"E_EzNe20","Nehemiah arrives in Jerusalem","-445-04-28",,,,"T_Return",,,"T_Return","Event","Aug 7","Neh.2.11",
"E_EzNe21","Nehemiah inspects the walls","-445-05-02",,,,"T_Return",,,"T_Return","Event","night of Aug 10","Neh.2.12-16",
"E_EzNe22","Rebuilding of the walls of Jerusalem","-445-05-03","-445-06-25",,,"T_Return",,,"T_Return","Event","Aug 11-Oct 2","Neh.2.17-6.19","End date given, plus length of 52 days. (Not sure which months were 30 days, which 29, so may be one or two days off.)"
-"E_EzNe23","Appointing of gatekeepers, singers and Levites","-445-06-26","-445-06-29",,,"T_Return",,,"T_Return","Event","Oct 3-Oct 6","Neh.6.20-7.72",
+"E_EzNe23","Appointing of gatekeepers, singers and Levites","-445-06-26","-445-06-29",,,"T_Return",,,"T_Return","Event","Oct 3-Oct 6","Neh.7.1-73",
"E_EzNe24","Ezra reads the Law","-445-07-01","-445-07-08",,,"T_Return",,,"T_Return","Event","Oct 7-Oct 14","Neh.7.73-8.18",
"E_EzNe25","The Israelites confess their sins","-445-07-24",,,,"T_Return",,,"T_Return","Event",,"Neh.9-10",
"E_EzNe26","Resettlement in Jerusalem","-445","-444",,,"T_Return",,,"T_Return","Event",,"Neh.11-12.26","No end time. Months seem reasonable"
Modified: trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_Global.csv
===================================================================
--- trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_Global.csv 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_Global.csv 2011-05-10 07:02:46 UTC (rev 227)
@@ -1,5 +1,5 @@
"ID","Name","From","To","From2","To2","Importance","Certainty","Flags","Timeline","Type","Description","Refs","Notes"
-"T_All","All","-3800","2000","-4112","2000",,,,"T_All","Timeline","Container for everything",,"All refs very approximate"
+"T_All","All","-3800","2000","-4112","2000",,,,"-","Timeline","Container for everything",,"All refs very approximate"
"T_Bible","Bible ","-3800","400","-4112","400","T_All",,,"T_All","Timeline","All OT dates need sorting out",,
"T_Patriarchs","Patriarchs","-4000","-1547","-4112","-1859","T_All",,,"T_Bible","Timeline",,"Gen.*",
"T_AdamToAbraham","Adam to Abraham","-4000","-1854","-4000","-1854","T_Patriarchs",,,"T_Patriarchs","Timeline",,"Gen.1-11",
Modified: trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_Monarchy.csv
===================================================================
--- trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_Monarchy.csv 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_Monarchy.csv 2011-05-10 07:02:46 UTC (rev 227)
@@ -109,7 +109,7 @@
"E_MON105","Amaziah","-796","-767",,,"T_JudahMonarchy",,,"T_JudahMonarchy","Event",,"2Kgs.14.1-22;2Chr.25.1-28",
"E_MON106","Azariah","-767","-739",,,"T_JudahMonarchy",,,"T_JudahMonarchy","Reign","Also Uzziah. Co-regent 790-767","2Kgs.15.1-7;2Chr.26.1-23",
"E_MON107","Jotham","-739","-732",,,"T_JudahMonarchy",,,"T_JudahMonarchy","Reign","Co-regent 750-739","2Kgs.15.32-38;2Chr.27.1-9",
-"E_MON108","Ahaz","-732","-715-01",,,"T_JudahMonarchy",,,"T_JudahMonarchy","Reign","Co-regent 736-732","2Kgs.16.1-20;2Chr.28-1.27",
+"E_MON108","Ahaz","-732","-715-01",,,"T_JudahMonarchy",,,"T_JudahMonarchy","Reign","Co-regent 736-732","2Kgs.16.1-20;2Chr.28.1-27",
"E_MON109","Hezekiah","-715-01","-687",,,"T_JudahMonarchy",,,"T_JudahMonarchy","Reign",,"2Kgs.18.1-20.21;2Chr.29.1-32.33",
"E_MON110","Hezekiah reconsecrates the Temple and re-establishes Passover","-715-01","-715-03",,,"T_JudahMonarchy",,,"T_JudahMonarchy","Event",,"2Chr.29.3-31.20",
"E_MON111","Sennacherib attacks Judah","-701-06",,,,"T_JudahMonarchy","EM",,"T_JudahMonarchy","Event",,"2Kgs.18.13-19.37;2Chr.32.1-23",
Modified: trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_PatriarchsToJudges.csv
===================================================================
--- trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_PatriarchsToJudges.csv 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/data/create/timeline/TL_PatriarchsToJudges.csv 2011-05-10 07:02:46 UTC (rev 227)
@@ -1,7 +1,7 @@
"ID","Name","From","To","From2","To2","Importance","Certainty","Flags","Timeline","Type","Description","Refs","Notes"
"E_PAT1","Birth of Abraham","-1854",,"-2166",,"T_Abraham","20",,"T_Abraham","Event",,"Gen.11.27",
"E_PAT2","Call of Abraham; Abraham goes from Haran to Canaan","-1779",,"-2091",,"T_Abraham","20",,"T_Abraham","Event",,"Gen.12.1-9",
-"E_PAT3","Birth of Ishmael","-1768",,"-2080",,"T_Abraham","20",,"T_Abraham","Event",,"Gen.16.15-17",
+"E_PAT3","Birth of Ishmael","-1768",,"-2080",,"T_Abraham","20",,"T_Abraham","Event",,"Gen.16.15-16",
"E_PAT4","Birth of Isaac","-1754",,"-2066",,"T_Abraham","20",,"T_Abraham","Event",,"Gen.21.1-5",
"E_PAT5","Mount Moriah","-1739",,"-2051",,"T_Abraham","20",,"T_Abraham","Event",,"Gen.22",
"E_PAT6","Isaac marries Rebekah","-1714",,"-2026",,"T_Abraham","20",,"T_Abraham","Event",,"Gen.24",
@@ -54,7 +54,7 @@
"E_PAT53","Joseph, the cupbearer and the baker","-1576",,"-1888",,"T_Jacob","20","EY","T_Jacob","Event",,"Gen.40",
"E_PAT54","Joseph's brothers visit Egypt","-1566",,"-1878",,"T_Jacob","20",,"T_Jacob","Event",,"Gen.42",
"E_PAT55","Joseph's brothers visit Egypt a second time ","-1565",,"-1877",,"T_Jacob","20",,"T_Jacob","Event",,"Gen.43-45",
-"E_PAT56","Joseph buries Jacob","-1547-07",,"-1859-07",,"T_Jacob","20Y",,"T_Jacob","Event",,"Gen.50-1-21",
+"E_PAT56","Joseph buries Jacob","-1547-07",,"-1859-07",,"T_Jacob","20Y",,"T_Jacob","Event",,"Gen.50.1-21",
"E_PAT57","Adam","-3800","-2870","-4112","-3182","T_AdamToAbraham","100",,"T_AdamToAbraham","Event",,"Gen.1.26-28; Gen.2.15-3.24; Gen.5.1-5",
"E_PAT58","Seth","-3670","-2758","-3982","-3070","T_AdamToAbraham","100",,"T_AdamToAbraham","Event",,"Gen.5.6-8",
"E_PAT59","Enosh","-3565","-2660","-3877","-2972","T_AdamToAbraham","100",,"T_AdamToAbraham","Event",,"Gen.5.9-11",
@@ -124,10 +124,10 @@
"E_PAT125","At Elim","-1250-02-01","-1250-02-08","-1446-02-01","-1446-02-08","T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.15.27",
"E_PAT126","Giving of Manna","-1250-02-15","-1250-02-21","-1446-02-15","-1446-02-21","T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.16",
"E_PAT127","Water from the Rock at Rephidim","-1250-02-22",,"-1446-02-22",,"T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.17.1-7",
-"E_PAT128","Israel defeats Amalek","-1250-02-24",,"-1446-02-24",,"T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.17-8-16",
+"E_PAT128","Israel defeats Amalek","-1250-02-24",,"-1446-02-24",,"T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.17.8-16",
"E_PAT129","Jethro visits Moses","-1250-02-25","-1250-02-28","-1446-02-25","-1446-02-28","T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.18",
"E_PAT130","Israel arrive at Mount Sinai","-1250-03-01",,"-1446-03-01",,"T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.19.1-15",
-"E_PAT131","Giving of the Ten Commandments","-1250-03-03",,"-1446-03-03",,"T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.19-16-20.21",
+"E_PAT131","Giving of the Ten Commandments","-1250-03-03",,"-1446-03-03",,"T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.19.16-20.21",
"E_PAT132","Moses given the Law","-1250-03-04",,"-1446-03-04",,"T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.20.22-23.33",
"E_PAT133","The seventy elders worship God","-1250-03-05",,"-1446-03-05",,"T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.24.1-14",
"E_PAT134","Moses on the mountain for 40 days","-1250-03-06","-1250-04-15","-1446-03-06","-1446-04-15","T_Wilderness","10Y",,"T_Wilderness","Event",,"Exod.24.15-31.18",
Modified: trunk/step/step-core/src/main/resources/step.core.properties
===================================================================
--- trunk/step/step-core/src/main/resources/step.core.properties 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/main/resources/step.core.properties 2011-05-10 07:02:46 UTC (rev 227)
@@ -1,5 +1,5 @@
# Front controller properties
-cache.enabled=true
+frontcontroller.cache.enabled=false
#list of installers in the format: host,package,catalog
installer.1=www.crosswire.org,/ftpmirror/pub/sword/packages/rawzip,/ftpmirror/pub/sword/raw
@@ -34,4 +34,15 @@
app.cache.session.timeToLive=300
app.cache.session.timeToIdle=300
+#caches entire responses
+app.cache.responses.maxElements=500
+app.cache.timeBeforeExpiration=3600
+#####################
+# Security settings
+#####################
+app.security.numIterations=1500
+app.security.inputEncoding=UTF-8
+app.security.hashingAlgorithm=SHA-1
+app.security.saltingAlgorithm=SHA1PRNG
+app.security.saltLength=8
Modified: trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/data/common/PartialDateTest.java
===================================================================
--- trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/data/common/PartialDateTest.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/data/common/PartialDateTest.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -2,7 +2,6 @@
import static org.junit.Assert.assertEquals;
-import java.util.Calendar;
import java.util.GregorianCalendar;
import org.junit.Test;
@@ -36,8 +35,8 @@
@Test
public void testYearAD() {
final PartialDate pd = PartialDate.parseDate("1");
- assertEquals(pd.getDate().get(Calendar.YEAR), 1);
- assertEquals(pd.getDate().get(Calendar.ERA), GregorianCalendar.AD);
+ assertEquals(pd.getDate().getYear(), 1);
+ assertEquals(pd.getDate().getEra(), GregorianCalendar.AD);
assertEquals(pd.getPrecision(), PrecisionType.YEAR);
}
@@ -45,8 +44,8 @@
@Test
public void testYearBC() {
final PartialDate pd = PartialDate.parseDate("-1");
- assertEquals(pd.getDate().get(Calendar.YEAR), 1);
- assertEquals(pd.getDate().get(Calendar.ERA), GregorianCalendar.BC);
+ assertEquals(pd.getDate().getYear(), -1);
+ assertEquals(pd.getDate().getEra(), GregorianCalendar.BC);
assertEquals(pd.getPrecision(), PrecisionType.YEAR);
}
@@ -54,9 +53,9 @@
@Test
public void testYearMonthBC() {
final PartialDate pd = PartialDate.parseDate("-3-7");
- assertEquals(pd.getDate().get(Calendar.YEAR), 3);
- assertEquals(pd.getDate().get(Calendar.MONTH), 7);
- assertEquals(pd.getDate().get(Calendar.ERA), GregorianCalendar.BC);
+ assertEquals(pd.getDate().getYear(), -3);
+ assertEquals(pd.getDate().getMonthOfYear(), 7);
+ assertEquals(pd.getDate().getEra(), GregorianCalendar.BC);
assertEquals(pd.getPrecision(), PrecisionType.MONTH);
}
@@ -64,11 +63,11 @@
@Test
public void testYearMonthDay() {
final PartialDate pd = PartialDate.parseDate("3-07-25");
- assertEquals(pd.getDate().get(Calendar.YEAR), 3);
- assertEquals(pd.getDate().get(Calendar.MONTH), 7);
- assertEquals(pd.getDate().get(Calendar.DAY_OF_MONTH), 25);
+ assertEquals(pd.getDate().getYear(), 3);
+ assertEquals(pd.getDate().getMonthOfYear(), 7);
+ assertEquals(pd.getDate().getDayOfMonth(), 25);
- assertEquals(pd.getDate().get(Calendar.ERA), GregorianCalendar.AD);
+ assertEquals(pd.getDate().getEra(), GregorianCalendar.AD);
assertEquals(pd.getPrecision(), PrecisionType.DAY);
}
Modified: trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/data/entities/UserTest.java
===================================================================
--- trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/data/entities/UserTest.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/data/entities/UserTest.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -22,8 +22,8 @@
final User u = new User();
u.setEmailAddress("chrisburrell at test.com");
u.setName("Chris");
- u.setPassword("password");
-
+ u.setPassword("password".getBytes());
+ u.setSalt(new byte[0]);
getEbean().save(u);
final User r = Ebean.find(User.class, u.getId());
assertEquals(u.getEmailAddress(), r.getEmailAddress());
Modified: trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/FavouritesServiceImplTest.java
===================================================================
--- trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/FavouritesServiceImplTest.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/FavouritesServiceImplTest.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -48,6 +48,8 @@
this.favouritesService = new FavouritesServiceImpl(getEbean(), this.serverSession);
this.u = new User();
this.u.setEmailAddress("b at b.com");
+ this.u.setSalt(new byte[0]);
+ this.u.setPassword(new byte[0]);
final Session s = new Session();
s.setUser(this.u);
Added: trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImplTest.java
===================================================================
--- trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImplTest.java (rev 0)
+++ trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImplTest.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -0,0 +1,173 @@
+package com.tyndalehouse.step.core.service.impl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.tyndalehouse.step.core.data.DataDrivenTestExtension;
+import com.tyndalehouse.step.core.service.TimelineService;
+
+/**
+ * tests the timeline service
+ *
+ * @author Chris
+ *
+ */
+ at RunWith(MockitoJUnitRunner.class)
+public class TimelineServiceImplTest extends DataDrivenTestExtension {
+ private static final Logger LOG = LoggerFactory.getLogger(FavouritesServiceImpl.class);
+ private TimelineService ts;
+
+ /**
+ * sets up a few things to be able to test properly
+ */
+ @Before
+ public void setUp() {
+ this.ts = new TimelineServiceImpl(getEbean());
+ }
+
+ // /**
+ // * tests that the syntax of the query is correct
+ // */
+ // @Test
+ // public void testGetEventsInPeriodInRangePointInTime() {
+ // final TimelineEvent inRange = createEventAndPersist(1000, "A");
+ // final List<TimelineEvent> timelineEvents = this.ts.getTimelineEvents(new LocalDateTime(0),
+ // new LocalDateTime(2000));
+ //
+ // LOG.debug("Event 1: [{}]", timelineEvents.get(0).getSummary());
+ // LOG.debug("Event 2: [{}]", timelineEvents.get(1).getSummary());
+ //
+ // assertEquals(timelineEvents.size(), 1);
+ // assertEquals(timelineEvents.get(0).getSummary(), inRange.getSummary());
+ // }
+ //
+ // /**
+ // * tests that out of range events before/after do not get retrieved
+ // */
+ // @Test
+ // public void testGetEventsInPeriodOutOfRangePointInTime() {
+ // createEventAndPersist(1000, "A");
+ // createEventAndPersist(2001, "B");
+ // final List<TimelineEvent> timelineEvents = this.ts.getTimelineEvents(new LocalDateTime(1001),
+ // new LocalDateTime(2000));
+ //
+ // assertEquals(timelineEvents.size(), 0);
+ // }
+ //
+ // /**
+ // * tests that out of range events before/after do not get retrieved
+ // */
+ // @Test
+ // public void testGetEventsInPeriodOverlapStartDuration() {
+ // final TimelineEvent inRange = createEvent(500, 1100, "A");
+ // final List<TimelineEvent> timelineEvents = this.ts.getTimelineEvents(new LocalDateTime(1000),
+ // new LocalDateTime(2000));
+ //
+ // assertEquals(timelineEvents.size(), 1);
+ // assertEquals(timelineEvents.get(0).getSummary(), inRange.getSummary());
+ // }
+ //
+ // /**
+ // * tests that out of range events before/after do not get retrieved
+ // */
+ // @Test
+ // public void testGetEventsInPeriodOverlapEndDuration() {
+ // final TimelineEvent inRange = createEvent(1500, 2100, "A");
+ // final List<TimelineEvent> timelineEvents = this.ts.getTimelineEvents(new LocalDateTime(1000),
+ // new LocalDateTime(2000));
+ //
+ // assertEquals(timelineEvents.size(), 1);
+ // assertEquals(timelineEvents.get(0).getSummary(), inRange.getSummary());
+ // }
+ //
+ // /**
+ // * tests that out of range events before/after do not get retrieved
+ // */
+ // @Test
+ // public void testGetEventsInPeriodContainedDuration() {
+ // final TimelineEvent inRange = createEvent(1500, 1700, "A");
+ // final List<TimelineEvent> timelineEvents = this.ts.getTimelineEvents(new LocalDateTime(1000),
+ // new LocalDateTime(2000));
+ //
+ // assertEquals(timelineEvents.size(), 1);
+ // assertEquals(timelineEvents.get(0).getSummary(), inRange.getSummary());
+ // }
+ //
+ // /**
+ // * tests that out of range events before/after do not get retrieved
+ // */
+ // @Test
+ // public void testGetEventsInPeriodOverflowDuration() {
+ // final TimelineEvent inRange = createEvent(200, 2100, "A");
+ // final List<TimelineEvent> timelineEvents = this.ts.getTimelineEvents(new LocalDateTime(1000),
+ // new LocalDateTime(2000));
+ //
+ // assertEquals(timelineEvents.size(), 1);
+ // assertEquals(timelineEvents.get(0).getSummary(), inRange.getSummary());
+ // }
+ //
+ // /**
+ // * tests that out of range events before/after do not get retrieved
+ // */
+ // @Test
+ // public void testGetEventsOutOfRangeDuration() {
+ // createEvent(200, 700, "A");
+ // createEvent(2200, 2700, "B");
+ // final List<TimelineEvent> timelineEvents = this.ts.getTimelineEvents(new LocalDateTime(1000),
+ // new LocalDateTime(2000));
+ //
+ // assertEquals(timelineEvents.size(), 0);
+ //
+ // }
+ //
+ // /**
+ // * creates a duration event
+ // *
+ // * @param startTime start of event
+ // * @param endTime end of event
+ // * @param summary summary of event
+ // * @return a single timeline event
+ // */
+ // private TimelineEvent createEvent(final int startTime, final int endTime, final String summary) {
+ // final TimelineEvent te = createEvent(startTime, summary);
+ // te.setToDate(new LocalDateTime(endTime));
+ // getEbean().save(te);
+ // return te;
+ // }
+ //
+ // /**
+ // * a helper method to create an event
+ // *
+ // * @param startTime the time of creation
+ // * @param summary the summary
+ // * @return the event that was creates and persisted
+ // */
+ // private TimelineEvent createEventAndPersist(final int startTime, final String summary) {
+ // final TimelineEvent te = createEvent(startTime, summary);
+ // getEbean().save(te);
+ // return te;
+ // }
+ //
+ // /**
+ // * creates the event without persisting
+ // *
+ // * @param startTime the start time of the event
+ // * @param summary the summary
+ // * @return the event created
+ // */
+ // private TimelineEvent createEvent(final int startTime, final String summary) {
+ // final TimelineEvent te = new TimelineEvent();
+ // te.setFromDate(new LocalDateTime(startTime));
+ // te.setSummary(summary);
+ // return te;
+ // }
+
+ @Test
+ public void temporaryTest() {
+
+ }
+}
Property changes on: trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/TimelineServiceImplTest.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/UserDataServiceImplTest.java
===================================================================
--- trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/UserDataServiceImplTest.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/impl/UserDataServiceImplTest.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -25,6 +25,7 @@
*/
@RunWith(MockitoJUnitRunner.class)
public class UserDataServiceImplTest extends DataDrivenTestExtension {
+ private static final int TEST_NUM_ENCRYPT_ITERATIONS = 1;
@Mock
private Provider<Session> serverSessionProvider;
@Mock
@@ -37,7 +38,8 @@
@Before
public void setUp() {
// MockitoAnnotations.initMocks(this);
- this.userService = new UserDataServiceImpl(super.getEbean(), this.serverSessionProvider);
+ this.userService = new UserDataServiceImpl(super.getEbean(), this.serverSessionProvider,
+ TEST_NUM_ENCRYPT_ITERATIONS, "UTF-8", "SHA-1", "SHA1PRNG", 8);
}
/**
@@ -64,7 +66,6 @@
assertEquals(user.getEmailAddress(), testEmail);
assertEquals(user.getName(), testName);
assertEquals(user.getCountry(), testCountry);
- assertEquals(user.getPassword(), testPassword);
}
/**
@@ -97,8 +98,8 @@
}
/**
- * we check that login in creates a row in the session table mapped to a user
- *
+ * we check that login in creates a row in the session table mapped to a user we also check that the hash
+ * creating the user is used on retrieval of the user
*/
@Test
public void testLoginPass() {
@@ -114,7 +115,9 @@
// save the user in a database
final User u = new User();
u.setEmailAddress(email);
- u.setPassword(password);
+ final byte[] salt = "abcdefg".getBytes();
+ u.setSalt(salt);
+ u.setPassword(this.userService.getHash(TEST_NUM_ENCRYPT_ITERATIONS, password, salt));
u.setName(testName);
getEbean().save(u);
Modified: trunk/step/step-parent/pom.xml
===================================================================
--- trunk/step/step-parent/pom.xml 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-parent/pom.xml 2011-05-10 07:02:46 UTC (rev 227)
@@ -306,6 +306,12 @@
<version>${ehcache.version}</version>
<type>pom</type>
</dependency>
+
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ <version>1.6.2</version>
+ </dependency>
</dependencies>
</dependencyManagement>
Modified: trunk/step/step-web/src/main/java/com/tyndalehouse/step/guice/WebContextModule.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/guice/WebContextModule.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/guice/WebContextModule.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -3,6 +3,8 @@
import com.google.inject.AbstractModule;
import com.tyndalehouse.step.core.models.ClientSession;
import com.tyndalehouse.step.guice.providers.ClientSessionProvider;
+import com.tyndalehouse.step.models.timeline.TimelineTranslator;
+import com.tyndalehouse.step.models.timeline.impl.SimileTimelineTranslatorImpl;
/**
* This module serves to inject data that is specific to the servlet layer. The purpose of it is therefore to
@@ -17,5 +19,6 @@
protected void configure() {
// this provider is helpful for getting the request at runtime
bind(ClientSession.class).toProvider(ClientSessionProvider.class);
+ bind(TimelineTranslator.class).to(SimileTimelineTranslatorImpl.class);
}
}
Added: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/DigestableTimeline.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/DigestableTimeline.java (rev 0)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/DigestableTimeline.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -0,0 +1,11 @@
+package com.tyndalehouse.step.models.timeline;
+
+/**
+ * Marks a structure that a UI can understand
+ *
+ * @author Chris
+ *
+ */
+public interface DigestableTimeline {
+
+}
Property changes on: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/DigestableTimeline.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/TimelineTranslator.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/TimelineTranslator.java (rev 0)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/TimelineTranslator.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -0,0 +1,23 @@
+package com.tyndalehouse.step.models.timeline;
+
+import java.util.List;
+
+import com.tyndalehouse.step.core.data.entities.TimelineEvent;
+
+/**
+ * A translator is able to convert timeline data into a form that is acceptable by the client
+ *
+ * @author Chris
+ *
+ */
+public interface TimelineTranslator {
+
+ /**
+ * translates a list of events to a digestable form of a timeline
+ *
+ * @param events a list of events
+ * @return the wrapped up form of the timeline
+ */
+ DigestableTimeline toDigestableTimeline(final List<TimelineEvent> events);
+
+}
Property changes on: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/TimelineTranslator.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileEvent.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileEvent.java (rev 0)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileEvent.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -0,0 +1,124 @@
+package com.tyndalehouse.step.models.timeline.impl;
+
+/**
+ * This represents the following fragment:
+ *
+ * <pre>
+ * {'start': '-1262',
+ * 'title': 'Barfusserkirche',
+ * 'description': 'by Lyonel Feininger, American/German Painter, 1871-1956',
+ * 'image': 'http://images.allposters.com/images/AWI/NR096_b.jpg',
+ * 'link': 'http://www.allposters.com/-sp/Barfusserkirche-1924-Posters_i1116895_.htm'
+ * },
+ * </pre>
+ *
+ * @author Chris
+ *
+ */
+public class SimileEvent {
+ private String start;
+ private String end;
+ private boolean duration;
+ private String title;
+ private String description;
+ private String image; // ? should be url? TODO
+ private String link; // ? should be url
+
+ /**
+ * @return the start
+ */
+ public String getStart() {
+ return this.start;
+ }
+
+ /**
+ * @param start the start to set
+ */
+ public void setStart(final String start) {
+ this.start = start;
+ }
+
+ /**
+ * @return the title
+ */
+ public String getTitle() {
+ return this.title;
+ }
+
+ /**
+ * @param title the title to set
+ */
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ /**
+ * @return the image
+ */
+ public String getImage() {
+ return this.image;
+ }
+
+ /**
+ * @param image the image to set
+ */
+ public void setImage(final String image) {
+ this.image = image;
+ }
+
+ /**
+ * @return the link
+ */
+ public String getLink() {
+ return this.link;
+ }
+
+ /**
+ * @param link the link to set
+ */
+ public void setLink(final String link) {
+ this.link = link;
+ }
+
+ /**
+ * @return the end
+ */
+ public String getEnd() {
+ return this.end;
+ }
+
+ /**
+ * @param end the end to set
+ */
+ public void setEnd(final String end) {
+ this.end = end;
+ }
+
+ /**
+ * @return the duration
+ */
+ public boolean isDuration() {
+ return this.duration;
+ }
+
+ /**
+ * @param duration the duration to set
+ */
+ public void setDuration(final boolean duration) {
+ this.duration = duration;
+ }
+}
Property changes on: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileEvent.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineImpl.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineImpl.java (rev 0)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineImpl.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -0,0 +1,62 @@
+package com.tyndalehouse.step.models.timeline.impl;
+
+import java.util.List;
+
+import com.google.inject.Singleton;
+import com.tyndalehouse.step.models.timeline.DigestableTimeline;
+
+/**
+ * This is a wrapper around the input expected by the simile timeline
+ *
+ * <pre>
+ * 'dateTimeFormat': 'iso8601',
+ * 'wikiURL': "http://simile.mit.edu/shelf/",
+ * 'wikiSection': "Simile Cubism Timeline",
+ *
+ * 'events' : [
+ * {'start': '-1262',
+ * 'title': 'Barfusserkirche',
+ * 'description': 'by Lyonel Feininger, American/German Painter, 1871-1956',
+ * 'image': 'http://images.allposters.com/images/AWI/NR096_b.jpg',
+ * 'link': 'http://www.allposters.com/-sp/Barfusserkirche-1924-Posters_i1116895_.htm'
+ * },
+ * ]
+ * }
+ * </pre>
+ *
+ * @author Chris
+ *
+ */
+ at Singleton
+public class SimileTimelineImpl implements DigestableTimeline {
+ private String dateTimeFormat;
+ private List<SimileEvent> events;
+
+ /**
+ * @return the dateTimeFormat
+ */
+ public String getDateTimeFormat() {
+ return this.dateTimeFormat;
+ }
+
+ /**
+ * @param dateTimeFormat the dateTimeFormat to set
+ */
+ public void setDateTimeFormat(final String dateTimeFormat) {
+ this.dateTimeFormat = dateTimeFormat;
+ }
+
+ /**
+ * @return the events
+ */
+ public List<SimileEvent> getEvents() {
+ return this.events;
+ }
+
+ /**
+ * @param events the events to set
+ */
+ public void setEvents(final List<SimileEvent> events) {
+ this.events = events;
+ }
+}
Property changes on: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineImpl.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineTranslatorImpl.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineTranslatorImpl.java (rev 0)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineTranslatorImpl.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -0,0 +1,48 @@
+package com.tyndalehouse.step.models.timeline.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.joda.time.LocalDateTime;
+
+import com.tyndalehouse.step.core.data.entities.TimelineEvent;
+import com.tyndalehouse.step.models.timeline.DigestableTimeline;
+import com.tyndalehouse.step.models.timeline.TimelineTranslator;
+
+/**
+ * provides a way of
+ *
+ * @author Chris
+ *
+ */
+public class SimileTimelineTranslatorImpl implements TimelineTranslator {
+ private static final String SIMILE_DEFAULT_TIME_FORMAT = "iso8601";
+
+ @Override
+ public DigestableTimeline toDigestableTimeline(final List<TimelineEvent> events) {
+ final SimileTimelineImpl timeline = new SimileTimelineImpl();
+
+ timeline.setDateTimeFormat(SIMILE_DEFAULT_TIME_FORMAT);
+
+ final List<SimileEvent> eventList = new ArrayList<SimileEvent>();
+ for (final TimelineEvent te : events) {
+ final SimileEvent e = new SimileEvent();
+ e.setTitle(te.getSummary());
+ e.setDescription(te.getSummary());
+ e.setStart(te.getFromDate().toString());
+
+ final LocalDateTime toDate = te.getToDate();
+ if (toDate != null) {
+ e.setEnd(te.getToDate().toString());
+ e.setDuration(true);
+ } else {
+ e.setDuration(false);
+ }
+
+ eventList.add(e);
+ }
+
+ timeline.setEvents(eventList);
+ return timeline;
+ }
+}
Property changes on: trunk/step/step-web/src/main/java/com/tyndalehouse/step/models/timeline/impl/SimileTimelineTranslatorImpl.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/FrontController.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/FrontController.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/FrontController.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -1,12 +1,8 @@
package com.tyndalehouse.step.rest.controllers;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
-import java.net.URLDecoder;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServlet;
@@ -42,16 +38,13 @@
*/
@Singleton
public class FrontController extends HttpServlet {
+ private static final Logger LOGGER = LoggerFactory.getLogger(FrontController.class);
private static final String ENTITIES_PACKAGE = "com.tyndalehouse.step.core.data.entities";
private static final String AVAJE_PACKAGE = "com.avaje";
-
private static final String UTF_8_ENCODING = "UTF-8";
- private static final Logger LOGGER = LoggerFactory.getLogger(FrontController.class);
private static final char PACKAGE_SEPARATOR = '.';
private static final long serialVersionUID = 7898656504631346047L;
private static final String CONTROLLER_SUFFIX = "Controller";
- // TODO: EH cache here too?
- private final Map<String, String> contextPath = new HashMap<String, String>();
private final transient Injector guiceInjector;
// TODO: but also check thread safety and whether we should share this object
private final transient ObjectMapper jsonMapper = new ObjectMapper();
@@ -68,7 +61,6 @@
/**
* creates the front controller which will dispatch all the requests
* <p />
- * TODO: rename all ebeans to DB
*
* @param guiceInjector the injector used to call the relevant controllers
* @param isCacheEnabled indicates whether responses should be cached for fast retrieval
@@ -78,7 +70,7 @@
*/
@Inject
public FrontController(final Injector guiceInjector,
- @Named("cache.enabled") final Boolean isCacheEnabled, final EbeanServer ebean,
+ @Named("frontcontroller.cache.enabled") final Boolean isCacheEnabled, final EbeanServer ebean,
final ClientErrorResolver errorResolver, final ResponseCache responseCache) {
this.guiceInjector = guiceInjector;
this.responseCache = responseCache;
@@ -97,7 +89,7 @@
try {
// cache miss?
if (jsonEncoded == null || jsonEncoded.length == 0) {
- sr = parseRequest(request);
+ sr = new StepRequest(request, UTF_8_ENCODING);
if (jsonEncoded == null) {
LOGGER.debug("The cache was missed so invoking method now...");
jsonEncoded = invokeMethod(sr);
@@ -176,6 +168,8 @@
* @return the encoded form of the JSON response
*/
byte[] getEncodedJsonResponse(final Object responseValue) {
+ LOGGER.debug("Encoding the following response [{}]", responseValue);
+
try {
String response;
// we have normal objects and avaje ebean objects which have been intercepted
@@ -205,33 +199,8 @@
}
/**
- * Returns the step request object containing the relevant information about the STEP Request
+ * caches the results for future use
*
- * @param request the HTTP request
- * @return the StepRequest encapsulating key data
- */
- StepRequest parseRequest(final HttpServletRequest request) {
- final String requestURI = request.getRequestURI();
-
- LOGGER.debug("Parsing {}", requestURI);
-
- final int requestStart = getPath(request).length() + 1;
- final int endOfControllerName = requestURI.indexOf('/', requestStart);
- final int startOfMethodName = endOfControllerName + 1;
- final String controllerName = requestURI.substring(requestStart, endOfControllerName);
- final int endOfMethodNameSlash = requestURI.indexOf('/', startOfMethodName);
- final String methodName = requestURI.substring(startOfMethodName,
- endOfMethodNameSlash == -1 ? requestURI.length() : endOfMethodNameSlash);
- final int endOfMethodName = startOfMethodName + methodName.length();
-
- LOGGER.debug("Request parsed as controller: [{}], method [{}]", controllerName, methodName);
- return new StepRequest(requestURI, controllerName, methodName, getArgs(requestURI,
- endOfMethodName + 1));
- }
-
- /**
- * TODO: caches the results for future use
- *
* @param jsonEncoded json encoding of the response
* @param sr the processed request URI containg the the cache key
* @param controllerMethod the method so that we can inspect whether an annotation is present
@@ -266,6 +235,7 @@
*/
void handleError(final HttpServletResponse response, final Throwable e, final StepRequest sr) {
String requestId = null;
+ LOGGER.debug("Handling error...");
try {
requestId = sr == null ? "Failed to parse request?" : sr.getCacheKey().getResultsKey();
if (e != null) {
@@ -364,54 +334,4 @@
return classes;
}
-
- /**
- * gets the arguments out of the requestURI String
- *
- * @param requestURI the request URI string
- * @param parameterStart the location at which the parameters start
- * @return a list of arguments
- */
- String[] getArgs(final String requestURI, final int parameterStart) {
- final List<String> arguments = new ArrayList<String>();
- int argStart = parameterStart;
- int nextArgStop = requestURI.indexOf('/', argStart);
- try {
- while (nextArgStop != -1) {
- arguments.add(URLDecoder.decode(requestURI.substring(argStart, nextArgStop), UTF_8_ENCODING));
- argStart = nextArgStop + 1;
- nextArgStop = requestURI.indexOf('/', argStart);
- }
- } catch (final UnsupportedEncodingException e) {
- throw new StepInternalException(e.getMessage(), e);
- }
-
- // add the last argument
- if (argStart < requestURI.length()) {
- try {
- arguments.add(URLDecoder.decode(requestURI.substring(argStart), UTF_8_ENCODING));
- } catch (final UnsupportedEncodingException e) {
- throw new StepInternalException("Unable to decode last argument", e);
- }
- }
- return arguments.toArray(new String[arguments.size()]);
- }
-
- /**
- * Retrieves the path from the request
- *
- * @param req the request
- * @return the concatenated request
- */
- String getPath(final HttpServletRequest req) {
- final String servletPath = req.getServletPath();
- String path = this.contextPath.get(servletPath);
-
- if (path == null) {
- path = super.getServletContext().getContextPath() + servletPath;
- this.contextPath.put(servletPath, path);
- }
- return path;
- }
-
}
Modified: trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/TimelineController.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/TimelineController.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/TimelineController.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -3,6 +3,7 @@
import java.util.Date;
import java.util.List;
+import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -10,6 +11,8 @@
import com.google.inject.Singleton;
import com.tyndalehouse.step.core.data.entities.Timeband;
import com.tyndalehouse.step.core.service.TimelineService;
+import com.tyndalehouse.step.models.timeline.DigestableTimeline;
+import com.tyndalehouse.step.models.timeline.TimelineTranslator;
import com.tyndalehouse.step.rest.framework.Cacheable;
/**
@@ -22,16 +25,18 @@
public class TimelineController {
private static final Logger LOGGER = LoggerFactory.getLogger(TimelineController.class);
private final TimelineService timelineService;
+ private final TimelineTranslator translator;
/**
* The timeline controller relies on the timeline service to retrieve the data
*
* @param timelineService the service
+ * @param translator a service enabling the translation of the model into a chewable version for the UI
*/
@Inject
- public TimelineController(final TimelineService timelineService) {
+ public TimelineController(final TimelineService timelineService, final TimelineTranslator translator) {
this.timelineService = timelineService;
-
+ this.translator = translator;
}
/**
@@ -67,6 +72,23 @@
}
/**
+ * returns a list of events that fall within the time period
+ *
+ * @param from the from date, left-bound
+ * @param to the to date, right-bound
+ * @return a list of timeline events in format digestable by the UI
+ */
+ @Cacheable(true)
+ public DigestableTimeline getEventsInPeriod(final String from, final String to) {
+ // TODO enhance FrontController to accept basic types such as long
+ final long f = Long.parseLong(from);
+ final long t = Long.parseLong(to);
+
+ return this.translator.toDigestableTimeline(this.timelineService.getTimelineEvents(new LocalDateTime(
+ f), new LocalDateTime(t)));
+ }
+
+ /**
* Retrieves the timebands that will be used to configure the timeline component
*
* @return the timebands
Modified: trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/UserController.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/UserController.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/controllers/UserController.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -1,7 +1,5 @@
package com.tyndalehouse.step.rest.controllers;
-import org.apache.commons.codec.digest.DigestUtils;
-
import com.google.inject.Inject;
import com.tyndalehouse.step.core.data.entities.User;
import com.tyndalehouse.step.core.service.UserDataService;
@@ -34,13 +32,12 @@
* @param password the password he has chosen, which we should SHA-1 and salt
* @return the registered user
*
- * TODO: salt
*/
public User register(final String emailAddress, final String name, final String country,
final String password) {
+
// do sha1 encoding here to avoid sending unencrypted string singletons all over the place...
- return this.userDataService.register(emailAddress, name, country,
- new String(DigestUtils.sha512(password)));
+ return this.userDataService.register(emailAddress, name, country, password);
}
/**
@@ -51,7 +48,7 @@
* @return the user that has logged in
*/
public User login(final String emailAddress, final String password) {
- return this.userDataService.login(emailAddress, new String(DigestUtils.sha512(password)));
+ return this.userDataService.login(emailAddress, password);
}
/**
Modified: trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/framework/ResponseCache.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/framework/ResponseCache.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/framework/ResponseCache.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -5,6 +5,7 @@
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import com.google.inject.Inject;
+import com.google.inject.name.Named;
import com.tyndalehouse.step.core.data.caches.AbstractDefaultCache;
/**
@@ -18,12 +19,17 @@
* A simple cache for the responses to be sent to the client..
*
* @param cacheManager the cache manager with which to register the cache
+ * @param maxElements the maximum number of elements to store in the cache
+ * @param timeBeforeExpiration the amount of time before the cache expires
*/
@Inject
- public ResponseCache(final CacheManager cacheManager) {
- super(cacheManager, new CacheConfiguration("httpResponseCache", 500)
+ public ResponseCache(final CacheManager cacheManager,
+ @Named("app.cache.responses.maxElements") final int maxElements,
+ @Named("app.cache.timeBeforeExpiration") final int timeBeforeExpiration) {
+ super(cacheManager, new CacheConfiguration("httpResponseCache", maxElements)
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LFU).overflowToDisk(false)
- .eternal(false).timeToLiveSeconds(3600).timeToIdleSeconds(3600).diskPersistent(false)
+ .eternal(false).timeToLiveSeconds(timeBeforeExpiration)
+ .timeToIdleSeconds(timeBeforeExpiration).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
}
Modified: trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/framework/StepRequest.java
===================================================================
--- trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/framework/StepRequest.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/java/com/tyndalehouse/step/rest/framework/StepRequest.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -1,14 +1,27 @@
package com.tyndalehouse.step.rest.framework;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.tyndalehouse.step.core.exceptions.StepInternalException;
+
/**
* A simple class that hold request information, provides various cache keys
* <p />
- * TODO: move parse method from FrontController to here.
*
* @author Chris
*
*/
public class StepRequest {
+ private static final Logger LOGGER = LoggerFactory.getLogger(StepRequest.class);
+
private final String controllerName;
private final String methodName;
private final String[] args;
@@ -16,7 +29,8 @@
private final String requestURI;
/**
- * Creates a request holder object containing the relevant information about a request
+ * Creates a request holder object containing the relevant information about a request. This constructor
+ * is used more for testing and could possibly be removed later
*
* @param requestURI the request URI that determines the controller, method name, etc.
* @param controllerName the controller name
@@ -32,6 +46,75 @@
}
/**
+ * Returns the step request object containing the relevant information about the STEP Request
+ *
+ * @param request the HTTP request
+ * @param encoding the encoding with which to decode the request
+ */
+ public StepRequest(final HttpServletRequest request, final String encoding) {
+ this.requestURI = request.getRequestURI();
+
+ LOGGER.debug("Parsing {}", this.requestURI);
+
+ final int requestStart = getPathLength(request) + 1;
+ final int endOfControllerName = this.requestURI.indexOf('/', requestStart);
+ final int startOfMethodName = endOfControllerName + 1;
+ final int endOfMethodNameSlash = this.requestURI.indexOf('/', startOfMethodName);
+
+ // now we can set the controllerName and methodNme
+ this.controllerName = this.requestURI.substring(requestStart, endOfControllerName);
+ this.methodName = this.requestURI.substring(startOfMethodName,
+ endOfMethodNameSlash == -1 ? this.requestURI.length() : endOfMethodNameSlash);
+
+ LOGGER.debug("Request parsed as controller: [{}], method [{}]", this.controllerName, this.methodName);
+ final int endOfMethodName = startOfMethodName + this.methodName.length();
+ final String[] calculatedArguments = parseArguments(endOfMethodName + 1, encoding);
+ this.args = calculatedArguments == null ? new String[] {} : calculatedArguments;
+ }
+
+ /**
+ * gets the arguments out of the requestURI String
+ *
+ * @param parameterStart the location at which the parameters start
+ * @param encoding the encoding with which to decode the arguments
+ * @return a list of arguments
+ */
+ private String[] parseArguments(final int parameterStart, final String encoding) {
+ final List<String> arguments = new ArrayList<String>();
+ int argStart = parameterStart;
+ int nextArgStop = this.requestURI.indexOf('/', argStart);
+ try {
+ while (nextArgStop != -1) {
+ arguments.add(URLDecoder.decode(this.requestURI.substring(argStart, nextArgStop), encoding));
+ argStart = nextArgStop + 1;
+ nextArgStop = this.requestURI.indexOf('/', argStart);
+ }
+ } catch (final UnsupportedEncodingException e) {
+ throw new StepInternalException(e.getMessage(), e);
+ }
+
+ // add the last argument
+ if (argStart < this.requestURI.length()) {
+ try {
+ arguments.add(URLDecoder.decode(this.requestURI.substring(argStart), encoding));
+ } catch (final UnsupportedEncodingException e) {
+ throw new StepInternalException("Unable to decode last argument", e);
+ }
+ }
+ return arguments.toArray(new String[arguments.size()]);
+ }
+
+ /**
+ * Retrieves the path from the request
+ *
+ * @param req the request
+ * @return the concatenated request
+ */
+ private int getPathLength(final HttpServletRequest req) {
+ return req.getServletPath().length() + req.getContextPath().length();
+ }
+
+ /**
* returns the cache key to resolve from the cache
*
* @return the key to the method as expected in the cache.
Modified: trunk/step/step-web/src/main/webapp/css/initial-layout.css
===================================================================
--- trunk/step/step-web/src/main/webapp/css/initial-layout.css 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/webapp/css/initial-layout.css 2011-05-10 07:02:46 UTC (rev 227)
@@ -166,10 +166,22 @@
.passageContent {
position: absolute;
- top: 45px;
+ /* top: 45px; */
overflow: auto;
}
+/*********************************************/
+/** BOTTOM COMPONENT
+/*********************************************/
+#bottomSection {
+ height: 0px;
+ position: absolute;
+ bottom: 0px;
+ left: 0px;
+ width: 100%;
+}
+
+
.no-left-border {
/* border-left: none; */
margin-left: -1px;
Modified: trunk/step/step-web/src/main/webapp/index.html
===================================================================
--- trunk/step/step-web/src/main/webapp/index.html 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/webapp/index.html 2011-05-10 07:02:46 UTC (rev 227)
@@ -37,55 +37,60 @@
</HEAD>
<body>
-<div id="topMenu" class="ddsmoothmenu">
-</div>
-<div class="column">
- <div class="passageContainer">
- <div id="leftPaneMenu" class="innerMenus"></div>
- <div class="passageText ui-widget">
- <div class="headingContainer">
- <a class="bookmarkPassageLink">Add a bookmark</a>
- <input id="leftPassageReference" class="heading editable passageReference" size="30" value="Rom 1:1-7" />
- <input id="leftPassageBook" class="heading editable passageVersion" size="5" value="KJV" />
- </div>
- <div class="passageContent"></div>
- </div>
+<div id="topMenu" class="ddsmoothmenu"> </div>
+<div style="height: 100%">
+ <div id="middleSection">
+ <div class="column">
+ <div class="passageContainer">
+ <div id="leftPaneMenu" class="innerMenus"></div>
+ <div class="passageText ui-widget">
+ <div class="headingContainer">
+ <a class="bookmarkPassageLink">Add a bookmark</a>
+ <input id="leftPassageReference" class="heading editable passageReference" size="30" value="Rom 1:1-7" />
+ <input id="leftPassageBook" class="heading editable passageVersion" size="5" value="KJV" />
+ </div>
+ <div class="passageContent"></div>
+ </div>
+ </div>
+ </div>
+
+ <div class="bookmarks" id="centerPane">
+ <div class="northBookmark">
+ <img id="topLogo" src="images/step-logo.png" alt="STEP :: Scripture Tools for Every Pastor" />
+ </div>
+ <div id="bookmarkPane" class="bookmarkPane ui-corner-all">
+ <h3 class="ui-helper-reset ui-state-default ui-corner-all">
+ <span class="leftBookmarkArrow ui-icon ui-icon-triangle-1-e"></span>History
+ </h3>
+ <div id="historyDisplayPane" class="bookmarkContents"><br /></div>
+ <h3 id="bookmarkHeader" class="ui-helper-reset ui-state-default ui-corner-all">
+ <span class="leftBookmarkArrow ui-icon ui-icon-triangle-1-e"></span>Bookmarks
+ </h3>
+ <div id="bookmarkDisplayPane" class="bookmarkContents"><br /></div>
+ </div>
+ <div class="logo">
+ <span class="copyright">© Tyndale House</span>
+ </div>
+ </div>
+
+
+ <div class="column">
+ <div class="passageContainer">
+ <div id="rightPaneMenu" class="innerMenus"></div>
+ <div class="passageText ui-widget">
+ <div class="headingContainer">
+ <a class="bookmarkPassageLink">Add a bookmark</a>
+ <input id="leftPassageReference" class="heading editable passageReference" size="30" value="Jhn 1:1" />
+ <input id="leftPassageBook" class="heading editable passageVersion" size="5" value="ESV" />
+ </div>
+ <div class="passageContent"></div>
+ </div>
+ </div>
+ </div>
</div>
-</div>
-<div class="bookmarks" id="centerPane">
- <div class="northBookmark">
- <img id="topLogo" src="images/step-logo.png" alt="STEP :: Scripture Tools for Every Pastor" />
- </div>
- <div id="bookmarkPane" class="bookmarkPane ui-corner-all">
- <h3 class="ui-helper-reset ui-state-default ui-corner-all">
- <span class="leftBookmarkArrow ui-icon ui-icon-triangle-1-e"></span>History
- </h3>
- <div id="historyDisplayPane" class="bookmarkContents"><br /></div>
- <h3 id="bookmarkHeader" class="ui-helper-reset ui-state-default ui-corner-all">
- <span class="leftBookmarkArrow ui-icon ui-icon-triangle-1-e"></span>Bookmarks
- </h3>
- <div id="bookmarkDisplayPane" class="bookmarkContents"><br /></div>
- </div>
- <div class="logo">
- <span class="copyright">© Tyndale House</span>
- </div>
+ <div id="bottomSection" class="bottomModule timeline">No modules have yet been loaded.</div>
</div>
-
-
-<div class="column">
- <div class="passageContainer">
- <div id="rightPaneMenu" class="innerMenus"></div>
- <div class="passageText ui-widget">
- <div class="headingContainer">
- <a class="bookmarkPassageLink">Add a bookmark</a>
- <input id="leftPassageReference" class="heading editable passageReference" size="30" value="Jhn 1:1" />
- <input id="leftPassageBook" class="heading editable passageVersion" size="5" value="ESV" />
- </div>
- <div class="passageContent"></div>
- </div>
- </div>
-</div>
<div class="interlinearPopup">
<input type="text" class="interlinearVersions"/>
@@ -97,9 +102,6 @@
</div>
-
-<!--<div id="bottomSection" class="timeline">No modules have yet been loaded.</div>-->
-<!---->
<!--<div id="loading"><img alt="Loading..." src="images/wait16.gif" />Loading...</div>-->
<div id="error">A placeholder for error messages</div>
Modified: trunk/step/step-web/src/main/webapp/js/init.js
===================================================================
--- trunk/step/step-web/src/main/webapp/js/init.js 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/webapp/js/init.js 2011-05-10 07:02:46 UTC (rev 227)
@@ -13,7 +13,7 @@
initLayout();
initDefaultValues();
initLexicon();
-// initTimeline(mainAppLayout);
+ initTimeline();
initBookmarks();
initData();
initInitialEvents();
@@ -26,11 +26,37 @@
var windowHeight = $(window).height();
var innerMenuHeight = $("#leftPaneMenu").height();
var topMenuHeight = $("#topMenu").height();
+ var headingContainerHeight = $(".headingContainer").height();
var imageAndFooterHeight = $(".northBookmark").height() + $(".logo").height();
- $(".column").height(windowHeight - topMenuHeight);
- $(".bookmarkPane").height(windowHeight - topMenuHeight - imageAndFooterHeight);
- $(".passageText").height(windowHeight - topMenuHeight - innerMenuHeight);
- $(".passageContent").height($(".passageText").height() - $(".headingContainer").height());
+ var bottomSectionHeight = $("#bottomSection").height();
+ var windowWithoutMenuNorModule = windowHeight - topMenuHeight - bottomSectionHeight;
+ var columnHeight = windowWithoutMenuNorModule;
+ var bookmarkHeight = windowWithoutMenuNorModule - imageAndFooterHeight ;
+ var passageTextHeight = windowWithoutMenuNorModule - innerMenuHeight;
+ var passageContentHeight = passageTextHeight - headingContainerHeight;
+
+ $(".column").height(columnHeight);
+ $(".bookmarkPane").height(bookmarkHeight);
+ $(".passageText").height(passageTextHeight);
+ $(".passageContent").css("top", headingContainerHeight);
+ $(".passageContent").height(passageContentHeight);
+
+// alert(headingContainerHeight);
+// if($("#debug").text() == "") {
+// $("#bookmarkPane").append("<span id=\"debug\" />");
+// }
+//
+// var heights =
+// "window = " + windowHeight + "\n" +
+// "paneMenu = " + innerMenuHeight + "\n" +
+// "topMenu = " + topMenuHeight + "\n" +
+// "imageAndFooter = " + imageAndFooterHeight + "\n" +
+// "passageText = " + $(".passageText").height() + "\n" +
+// "heading = " + $(".headingContainer").height() + "\n" +
+// "passageContent = " + $(".passageContent").height() + "\n" ;
+//
+// $("#debug").text(heights);
+//
}
/**
@@ -228,7 +254,7 @@
}
function initTimeline(mainAppLayout) {
- new TimelineWidget($("#bottomSection"), mainAppLayout);
+ new TimelineWidget($("#bottomSection"));
}
function raiseError(error) {
Modified: trunk/step/step-web/src/main/webapp/js/timeline.js
===================================================================
--- trunk/step/step-web/src/main/webapp/js/timeline.js 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/webapp/js/timeline.js 2011-05-10 07:02:46 UTC (rev 227)
@@ -2,135 +2,163 @@
* Code for showing and interacting with the timeline
*/
-function TimelineWidget(rootElement, mainAppLayout) {
+function TimelineWidget(rootElement) {
this.rootElement = rootElement;
var self = this;
$(rootElement).hear("show-timeline", function(selfElement) {
//first show the bottom pane...
- mainAppLayout.open("south");
-
self.onLoad();
$(window).resize(self.onResize);
});
$(rootElement).hear("hide-timeline", function(selfElement) {
//first show the bottom pane...
- mainAppLayout.close("south");
+// mainAppLayout.close("south");
});
}
var tl;
TimelineWidget.prototype.onLoad = function() {
var eventSource = new Timeline.DefaultEventSource();
+ var zones = [];
+
+ zones[0] = { start: "-1252",
+ end: "-1249",
+// magnify: 1,
+ unit: Timeline.DateTime.YEAR
+ };
+
+
- var zones = [
- { start: "Fri Nov 22 1963 00:00:00 GMT-0600",
- end: "Mon Nov 25 1963 00:00:00 GMT-0600",
- magnify: 10,
- unit: Timeline.DateTime.DAY
- },
- { start: "Fri Nov 22 1963 09:00:00 GMT-0600",
- end: "Sun Nov 24 1963 00:00:00 GMT-0600",
- magnify: 5,
- unit: Timeline.DateTime.HOUR
- },
- { start: "Fri Nov 22 1963 11:00:00 GMT-0600",
- end: "Sat Nov 23 1963 00:00:00 GMT-0600",
- magnify: 5,
- unit: Timeline.DateTime.MINUTE,
- multiple: 10
- },
- { start: "Fri Nov 22 1963 12:00:00 GMT-0600",
- end: "Fri Nov 22 1963 14:00:00 GMT-0600",
- magnify: 3,
- unit: Timeline.DateTime.MINUTE,
- multiple: 5
- }
- ];
- var zones2 = [
- { start: "Fri Nov 22 1963 00:00:00 GMT-0600",
- end: "Mon Nov 25 1963 00:00:00 GMT-0600",
- magnify: 10,
- unit: Timeline.DateTime.WEEK
- },
- { start: "Fri Nov 22 1963 09:00:00 GMT-0600",
- end: "Sun Nov 24 1963 00:00:00 GMT-0600",
- magnify: 5,
- unit: Timeline.DateTime.DAY
- },
- { start: "Fri Nov 22 1963 11:00:00 GMT-0600",
- end: "Sat Nov 23 1963 00:00:00 GMT-0600",
- magnify: 5,
- unit: Timeline.DateTime.MINUTE,
- multiple: 60
- },
- { start: "Fri Nov 22 1963 12:00:00 GMT-0600",
- end: "Fri Nov 22 1963 14:00:00 GMT-0600",
- magnify: 3,
- unit: Timeline.DateTime.MINUTE,
- multiple: 15
- }
- ];
+ if(this.config == null) {
+ $.getSafe(TIMELINE_GET_CONFIG, function(data) {
+
+// $.each(data, function(index, item) {
+// //set up the bands
+// //set up the hotspots
+// });
+ });
+ }
+//
+//
+//
+// var zones = [
+// { start: "Fri Nov 22 1963 00:00:00 GMT-0600",
+// end: "Mon Nov 25 1963 00:00:00 GMT-0600",
+// magnify: 10,
+// unit: Timeline.DateTime.DAY
+// },
+// { start: "Fri Nov 22 1963 09:00:00 GMT-0600",
+// end: "Sun Nov 24 1963 00:00:00 GMT-0600",
+// magnify: 5,
+// unit: Timeline.DateTime.HOUR
+// },
+// { start: "Fri Nov 22 1963 11:00:00 GMT-0600",
+// end: "Sat Nov 23 1963 00:00:00 GMT-0600",
+// magnify: 5,
+// unit: Timeline.DateTime.MINUTE,
+// multiple: 10
+// },
+// { start: "Fri Nov 22 1963 12:00:00 GMT-0600",
+// end: "Fri Nov 22 1963 14:00:00 GMT-0600",
+// magnify: 3,
+// unit: Timeline.DateTime.MINUTE,
+// multiple: 5
+// }
+// ];
+// var zones2 = [
+// { start: "Fri Nov 22 1963 00:00:00 GMT-0600",
+// end: "Mon Nov 25 1963 00:00:00 GMT-0600",
+// magnify: 10,
+// unit: Timeline.DateTime.WEEK
+// },
+// { start: "Fri Nov 22 1963 09:00:00 GMT-0600",
+// end: "Sun Nov 24 1963 00:00:00 GMT-0600",
+// magnify: 5,
+// unit: Timeline.DateTime.DAY
+// },
+// { start: "Fri Nov 22 1963 11:00:00 GMT-0600",
+// end: "Sat Nov 23 1963 00:00:00 GMT-0600",
+// magnify: 5,
+// unit: Timeline.DateTime.MINUTE,
+// multiple: 60
+// },
+// { start: "Fri Nov 22 1963 12:00:00 GMT-0600",
+// end: "Fri Nov 22 1963 14:00:00 GMT-0600",
+// magnify: 3,
+// unit: Timeline.DateTime.MINUTE,
+// multiple: 15
+// }
+// ];
+//
var theme = Timeline.ClassicTheme.create();
theme.event.bubble.width = 250;
- var date = "Fri Nov 22 1963 13:00:00 GMT-0600"
+ var date = "-1250";
var bandInfos = [
- Timeline.createHotZoneBandInfo({
- width: "80%",
- intervalUnit: Timeline.DateTime.WEEK,
- intervalPixels: 220,
+ Timeline.createBandInfo({
+ width: "100%",
+ intervalUnit: Timeline.DateTime.MONTH,
+ intervalPixels: 150,
zones: zones,
eventSource: eventSource,
date: date,
- timeZone: -6,
+// timeZone: -6,
theme: theme
- }),
- Timeline.createHotZoneBandInfo({
- width: "20%",
- intervalUnit: Timeline.DateTime.MONTH,
- intervalPixels: 200,
- zones: zones2,
- eventSource: eventSource,
- date: date,
- timeZone: -6,
- overview: true,
- theme: theme
})
+// ,
+// Timeline.createHotZoneBandInfo({
+// width: "20%",
+// intervalUnit: Timeline.DateTime.MONTH,
+// intervalPixels: 200,
+// zones: zones2,
+// eventSource: eventSource,
+// date: date,
+// timeZone: -6,
+// overview: true,
+// theme: theme
+// })
];
- bandInfos[1].syncWith = 0;
- bandInfos[1].highlight = true;
+// bandInfos[1].syncWith = 0;
+// bandInfos[1].highlight = true;
- for (var i = 0; i < bandInfos.length; i++) {
- bandInfos[i].decorators = [
- new Timeline.SpanHighlightDecorator({
- startDate: "Fri Nov 22 1963 12:30:00 GMT-0600",
- endDate: "Fri Nov 22 1963 13:00:00 GMT-0600",
- color: "#FFC080", // set color explicitly
- opacity: 50,
- startLabel: "shot",
- endLabel: "t.o.d.",
- theme: theme
- }),
- new Timeline.PointHighlightDecorator({
- date: "Fri Nov 22 1963 14:38:00 GMT-0600",
- opacity: 50,
- theme: theme
- // use the color from the css file
- }),
- new Timeline.PointHighlightDecorator({
- date: "Sun Nov 24 1963 13:00:00 GMT-0600",
- opacity: 50,
- theme: theme
- // use the color from the css file
- })
- ];
- }
+// for (var i = 0; i < bandInfos.length; i++) {
+// bandInfos[i].decorators = [
+// new Timeline.SpanHighlightDecorator({
+// startDate: "Fri Nov 22 1963 12:30:00 GMT-0600",
+// endDate: "Fri Nov 22 1963 13:00:00 GMT-0600",
+// color: "#FFC080", // set color explicitly
+// opacity: 50,
+// startLabel: "shot",
+// endLabel: "t.o.d.",
+// theme: theme
+// }),
+// new Timeline.PointHighlightDecorator({
+// date: "Fri Nov 22 1963 14:38:00 GMT-0600",
+// opacity: 50,
+// theme: theme
+// // use the color from the css file
+// }),
+// new Timeline.PointHighlightDecorator({
+// date: "Sun Nov 24 1963 13:00:00 GMT-0600",
+// opacity: 50,
+// theme: theme
+// // use the color from the css file
+// })
+// ];
+// }
if(!tl) {
tl = Timeline.create(this.rootElement[0], bandInfos, Timeline.HORIZONTAL);
}
+
+ tl.loadJSON("rest/timeline/getEventsInPeriod/-101690000000000/-101580000000000", function(json, url) {
+ eventSource.loadJSON(json, url);
+ });
+
+
+
// tl.loadXML("jfk.xml", function(xml, url) { eventSource.loadXML(xml, url); });
// setupFilterHighlightControls(document.getElementById("controls"), tl, [0,1], theme);
}
Modified: trunk/step/step-web/src/main/webapp/js/ui_hooks.js
===================================================================
--- trunk/step/step-web/src/main/webapp/js/ui_hooks.js 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/webapp/js/ui_hooks.js 2011-05-10 07:02:46 UTC (rev 227)
@@ -30,6 +30,7 @@
TIMELINE_GET_EVENTS = "rest/timeline/getEvents/";
TIMELINE_GET_EVENTS_FROM_REFERENCE = "rest/timeline/getEventsFromReference/";
+TIMELINE_GET_CONFIG = "rest/timeline/getTimelineConfiguration";
USER_LOGIN = "rest/user/login/";
USER_LOGOUT = "rest/user/logout/";
@@ -45,14 +46,14 @@
function toggleMenuItem(menuItem) {
//the hook needs to find the passage id
$.shout("pane-menu-toggle-item-" + $(menuItem).closest(".passageContainer").attr("passage-id"), menuItem.name);
-}
+};
/**
* shows the login popup
*/
function login() {
$.shout("show-login-popup");
-}
+};
/**
* shows the interlinear options as a popup
@@ -61,7 +62,7 @@
function showInterlinearChoices(menuItem) {
//get passage id from menu parent
$.shout("interlinear-menu-option-triggered-" + $(menuItem).closest(".passageContainer").attr("passage-id"));
-}
+};
/**
* called when click on a piece of text.
@@ -69,7 +70,7 @@
*/
function showAllStrongMorphs(strongMorphs) {
$.shout("show-all-strong-morphs", strongMorphs);
-}
+};
/**
* Called when clicking on a strong link
@@ -77,7 +78,7 @@
*/
function showStrong(strong, sourceElement) {
showMorphOrStrong(strong, sourceElement);
-}
+};
/**
* called when clicking on a morph
@@ -85,7 +86,7 @@
*/
function showMorph(morph, sourceElement) {
showMorphOrStrong(morph, sourceElement);
-}
+};
/** TODO: move this out of here to utils.js if we have more utility classes/functions
* helper function for morph and strongs
@@ -96,7 +97,7 @@
//need to find what event is coming in, to get the clicked element and pass that down
$("#lexiconDefinition span:contains(" + tag + ")").parent().click();
-}
+};
function showAbout() {
//show popup for About box
@@ -105,4 +106,21 @@
width: DEFAULT_POPUP_WIDTH,
title: "STEP :: Scripture Tools for Every Pastor",
});
-}
\ No newline at end of file
+};
+
+/**
+ * Shows the timeline module
+ */
+function showTimelineModule() {
+ showBottomSection();
+ $.shout("show-timeline");
+};
+
+/**
+ * shows the bottom section
+ */
+function showBottomSection() {
+ var bottomSection = $("#bottomSection");
+ bottomSection.height(bottomSection.parent().parent().height() / 2);
+ refreshLayout();
+}
Modified: trunk/step/step-web/src/main/webapp/panemenu.html
===================================================================
--- trunk/step/step-web/src/main/webapp/panemenu.html 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/main/webapp/panemenu.html 2011-05-10 07:02:46 UTC (rev 227)
@@ -10,7 +10,7 @@
</li>
<li><a href="#">Context</a>
<ul>
- <li><a href="#" class="notYetImplemented">Timeline</a></li>
+ <li><a href="#" onclick="showTimelineModule();">Timeline</a></li>
</ul>
</li>
<li><a href="#">Tools</a>
Added: trunk/step/step-web/src/main/webapp/tempdev/events.json
===================================================================
--- trunk/step/step-web/src/main/webapp/tempdev/events.json (rev 0)
+++ trunk/step/step-web/src/main/webapp/tempdev/events.json 2011-05-10 07:02:46 UTC (rev 227)
@@ -0,0 +1,14 @@
+{
+'dateTimeFormat': 'iso8601',
+'wikiURL': "http://simile.mit.edu/shelf/",
+'wikiSection': "Simile Cubism Timeline",
+
+'events' : [
+ {'start': '-1262',
+ 'title': 'Barfusserkirche',
+ 'description': 'by Lyonel Feininger, American/German Painter, 1871-1956',
+ 'image': 'http://images.allposters.com/images/AWI/NR096_b.jpg',
+ 'link': 'http://www.allposters.com/-sp/Barfusserkirche-1924-Posters_i1116895_.htm'
+ },
+]
+}
\ No newline at end of file
Modified: trunk/step/step-web/src/test/java/com/tyndalehouse/step/rest/controllers/FrontControllerTest.java
===================================================================
--- trunk/step/step-web/src/test/java/com/tyndalehouse/step/rest/controllers/FrontControllerTest.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/test/java/com/tyndalehouse/step/rest/controllers/FrontControllerTest.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -7,7 +7,6 @@
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -17,9 +16,6 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -35,6 +31,7 @@
import com.tyndalehouse.step.core.exceptions.StepInternalException;
import com.tyndalehouse.step.core.service.BibleInformationService;
import com.tyndalehouse.step.rest.framework.ClientErrorResolver;
+import com.tyndalehouse.step.rest.framework.ControllerCacheKey;
import com.tyndalehouse.step.rest.framework.ResponseCache;
import com.tyndalehouse.step.rest.framework.StepRequest;
@@ -59,6 +56,8 @@
private ClientErrorResolver errorResolver;
@Mock
private ResponseCache responseCache;
+ @Mock
+ private StepRequest stepRequest;
/**
* Simply setting up the FrontController under test
@@ -76,21 +75,24 @@
*/
@Test
public void testDoGet() throws IOException {
- final HttpServletRequest request = mock(HttpServletRequest.class);
+ final HttpServletRequest req = mock(HttpServletRequest.class);
final HttpServletResponse response = mock(HttpServletResponse.class);
+ final String sampleRequest = "step-web/rest/bible/get/1K2/2K2/";
+ when(req.getRequestURI()).thenReturn(sampleRequest);
+ when(req.getServletPath()).thenReturn("step-web/");
+ when(req.getContextPath()).thenReturn("rest/");
+
final FrontController fc = spy(this.fcUnderTest);
- final StepRequest parsedRequest = new StepRequest("blah", "SomeController", "someMethod",
- new String[] { "arg1", "arg2" });
+
final ServletOutputStream mockOutputStream = mock(ServletOutputStream.class);
- doReturn(parsedRequest).when(fc).parseRequest(request);
doReturn(mockOutputStream).when(response).getOutputStream();
final byte[] sampleResponse = new byte[] { 1, 2, 3 };
- doReturn(sampleResponse).when(fc).invokeMethod(parsedRequest);
+ doReturn(sampleResponse).when(fc).invokeMethod(any(StepRequest.class));
// do the test
- fc.doGet(request, response);
+ fc.doGet(req, response);
verify(mockOutputStream).write(sampleResponse);
}
@@ -107,7 +109,8 @@
final StepRequest parsedRequest = new StepRequest("blah", "SomeController", "someMethod",
new String[] { "arg1", "arg2" });
- doThrow(testException).when(fc).parseRequest(request);
+ // TODO remove this/
+ // doThrow(testException).when(fc).parseRequest(request);
doNothing().when(fc).handleError(response, testException, parsedRequest);
// do the test
@@ -116,65 +119,6 @@
}
/**
- * tests that arguments are parsed correctly given the correct start
- */
- @Test
- public void testGetArgs() {
- // index starts at ...........0123456789-123456789-123456
- final String sampleRequest = "step-web/rest/bible/get/1K2/2K2";
-
- // when
- final Object[] args = this.fcUnderTest.getArgs(sampleRequest, 24);
-
- // then
- assertEquals(2, args.length);
- assertEquals("1K2", args[0]);
- assertEquals("2K2", args[1]);
- }
-
- /**
- * tests that parsing of request works if request finishes with a slash
- */
- @Test
- public void testGetArgsFinishingWithSlash() {
- // index starts at ...........0123456789-123456789-123456
- final String sampleRequest = "step-web/rest/bible/get/1K2/2K2/";
-
- // when
- final Object[] args = this.fcUnderTest.getArgs(sampleRequest, 24);
-
- // then
- assertEquals(2, args.length);
- assertEquals("1K2", args[0]);
- assertEquals("2K2", args[1]);
- }
-
- /**
- * we check that the path is concatenated with the servlet path
- *
- * @throws ServletException an uncaught exception
- */
- @Test
- public void testGetPath() throws ServletException {
- final FrontController spy = spy(this.fcUnderTest);
-
- final ServletContext mockServletContext = mock(ServletContext.class);
- final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
-
- spy.init(mock(ServletConfig.class));
-
- when(spy.getServletContext()).thenReturn(mockServletContext);
- when(mockServletContext.getContextPath()).thenReturn("context/");
- when(mockRequest.getServletPath()).thenReturn("servletPath");
-
- // when
- final String path = spy.getPath(mockRequest);
-
- // then
- assertEquals(path, "context/servletPath");
- }
-
- /**
* tests that the headers are setup correctly
*/
@Test
@@ -260,56 +204,20 @@
@Test
public void testDoErrorHandlesCorrectly() throws IOException {
final HttpServletResponse response = mock(HttpServletResponse.class);
- final StepRequest stepRequest = new StepRequest("blah", "controller", "method", null);
+ // final StepRequest stepRequest = new StepRequest("blah", "controller", "method", null);
final ServletOutputStream outputStream = mock(ServletOutputStream.class);
final Throwable exception = new Exception();
when(response.getOutputStream()).thenReturn(outputStream);
+ when(this.stepRequest.getCacheKey()).thenReturn(new ControllerCacheKey("method", "results"));
// do test
- this.fcUnderTest.handleError(response, exception, stepRequest);
+ this.fcUnderTest.handleError(response, exception, this.stepRequest);
// check
verify(outputStream).write(any(byte[].class));
}
/**
- * checks that parsing is working correctly
- *
- * @throws ServletException uncaught exception
- */
- @Test
- public void testParseRequest() throws ServletException {
- final HttpServletRequest request = mock(HttpServletRequest.class);
- final String requestSeparator = "/";
- final String contextName = "step-web";
- final String servletName = "servletName";
- final String controllerName = "controllerName";
- final String methodName = "methodName";
- final String arg1 = "argument1";
- final String arg2 = "argument2";
-
- when(request.getServletPath()).thenReturn(servletName);
- when(request.getRequestURI()).thenReturn(
- contextName + requestSeparator + servletName + requestSeparator + controllerName
- + requestSeparator + methodName + requestSeparator + arg1 + requestSeparator + arg2);
-
- this.fcUnderTest.init(mock(ServletConfig.class));
-
- final FrontController spy = spy(this.fcUnderTest);
-
- final ServletContext mockServletContext = mock(ServletContext.class);
- when(spy.getServletContext()).thenReturn(mockServletContext);
- when(mockServletContext.getContextPath()).thenReturn(contextName + "/");
-
- // do test
- final StepRequest parseRequest = this.fcUnderTest.parseRequest(request);
-
- // check controller name, method name and arguments
- assertEquals(controllerName, parseRequest.getControllerName());
- assertEquals(methodName, parseRequest.getMethodName());
- }
-
- /**
* We check that invoke method calls the correct controller and method with the right arguments
*/
@Test
Modified: trunk/step/step-web/src/test/java/com/tyndalehouse/step/rest/framework/StepRequestTest.java
===================================================================
--- trunk/step/step-web/src/test/java/com/tyndalehouse/step/rest/framework/StepRequestTest.java 2011-03-29 21:43:38 UTC (rev 226)
+++ trunk/step/step-web/src/test/java/com/tyndalehouse/step/rest/framework/StepRequestTest.java 2011-05-10 07:02:46 UTC (rev 227)
@@ -1,8 +1,17 @@
package com.tyndalehouse.step.rest.framework;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
import org.junit.Test;
/**
@@ -12,6 +21,7 @@
*
*/
public class StepRequestTest {
+ private static final String UTF_8_ENCODING = "UTF-8";
private static final String[] TEST_ARGS = new String[] { "arg1", "arg2", "arg3" };
private static final String TEST_CONTROLLER_NAME = "Controller";
private static final String TEST_METHOD_NAME = "method";
@@ -47,6 +57,76 @@
}
/**
+ * testing simple parsing of arguments
+ */
+ @Test
+ public void testParseArguments() {
+ // index starts at ...........0123456789-123456789-123456
+ final String stepRequest = "step-web/rest/bible/get/1K2/2K2/";
+ final HttpServletRequest req = mock(HttpServletRequest.class);
+
+ when(req.getRequestURI()).thenReturn(stepRequest);
+ when(req.getServletPath()).thenReturn("step-web/");
+ when(req.getContextPath()).thenReturn("rest/");
+
+ // index starts at ...........0123456789-123456789-123456
+ final StepRequest sr = new StepRequest(req, UTF_8_ENCODING);
+ assertEquals(2, sr.getArgs().length);
+ assertEquals("1K2", sr.getArgs()[0]);
+ assertEquals("2K2", sr.getArgs()[1]);
+ }
+
+ /**
+ * tests that parsing of request works if request finishes with a slash
+ */
+ @Test
+ public void testGetArgsFinishingWithSlash() {
+ // index starts at ...........0123456789-123456789-123456
+ final String sampleRequest = "step-web/rest/bible/get/1K2/2K2/";
+ final HttpServletRequest req = mock(HttpServletRequest.class);
+
+ when(req.getRequestURI()).thenReturn(sampleRequest);
+ when(req.getServletPath()).thenReturn("step-web/");
+ when(req.getContextPath()).thenReturn("rest/");
+
+ final StepRequest sr = new StepRequest(req, UTF_8_ENCODING);
+
+ // then
+ assertEquals(2, sr.getArgs().length);
+ assertEquals("1K2", sr.getArgs()[0]);
+ assertEquals("2K2", sr.getArgs()[1]);
+ }
+
+ /**
+ * we check that the path is concatenated with the servlet path
+ *
+ * @throws ServletException an uncaught exception
+ * @throws InvocationTargetException an uncaught exception
+ * @throws IllegalAccessException an uncaught exception
+ * @throws NoSuchMethodException an uncaught exception
+ */
+ @Test
+ public void testGetPath() throws ServletException, IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ // length is: 1234567890123456789012345
+ final String sampleRequest = "step-web/rest/bible/get/1K2/2K2/";
+ final HttpServletRequest req = mock(HttpServletRequest.class);
+
+ when(req.getRequestURI()).thenReturn(sampleRequest);
+ when(req.getServletPath()).thenReturn("letters");
+ when(req.getContextPath()).thenReturn("more");
+
+ // then
+ final StepRequest sr = new StepRequest(req, "UTF-8");
+ final Method declaredMethod = sr.getClass().getDeclaredMethod("getPathLength",
+ HttpServletRequest.class);
+ declaredMethod.setAccessible(true);
+
+ assertEquals(11, declaredMethod.invoke(sr, req));
+ }
+
+ /**
* helper factory method
*
* @return a step request
More information about the Tynstep-svn
mailing list