You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/07/12 13:19:36 UTC
git commit: ISIS-463: new isis-core-specsupport module
Updated Branches:
refs/heads/master 7276dc0b5 -> dd7f283ce
ISIS-463: new isis-core-specsupport module
... to decouple scoping of scenarios from step definitions.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/dd7f283c
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/dd7f283c
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/dd7f283c
Branch: refs/heads/master
Commit: dd7f283ce81cf3b0663b5a99e0ab87ac3aae700b
Parents: 7276dc0
Author: Dan Haywood <da...@apache.org>
Authored: Fri Jul 12 12:19:17 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Jul 12 12:19:17 2013 +0100
----------------------------------------------------------------------
core/integtestsupport/pom.xml | 5 +-
.../integtestsupport/IsisSystemForTest.java | 2 +-
.../ScenarioExecutionForIntegration.java | 75 +++++
...enarioExecutionIntegrationScopeAbstract.java | 93 ------
.../CukeStepDefsIntegrationScopeAbstract.java | 75 -----
core/pom.xml | 29 +-
core/specsupport/pom.xml | 85 +++++
.../scenarios/DomainServiceProvider.java | 37 +++
.../scenarios/ScenarioExecution.java | 287 ++++++++++++++++
.../scenarios/ScenarioExecutionScope.java | 51 +++
.../specsupport/specs/CukeSpecsAbstract.java | 38 +++
.../specsupport/specs/CukeStepDefsAbstract.java | 148 +++++++++
.../apache/isis/core/specsupport/specs/V.java | 332 +++++++++++++++++++
core/unittestsupport/pom.xml | 17 -
.../scenarios/DomainServiceProvider.java | 24 --
.../scenarios/ScenarioExecution.java | 215 ------------
.../scenarios/specs/CukeSpecsAbstract.java | 38 ---
.../scenarios/specs/CukeStepDefsAbstract.java | 38 ---
.../core/unittestsupport/scenarios/specs/V.java | 332 -------------------
19 files changed, 1074 insertions(+), 847 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/integtestsupport/pom.xml
----------------------------------------------------------------------
diff --git a/core/integtestsupport/pom.xml b/core/integtestsupport/pom.xml
index af7bdae..5e90dcd 100644
--- a/core/integtestsupport/pom.xml
+++ b/core/integtestsupport/pom.xml
@@ -67,6 +67,10 @@
<groupId>org.apache.isis.core</groupId>
<artifactId>isis-core-unittestsupport</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-specsupport</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.isis.core</groupId>
@@ -119,7 +123,6 @@
<artifactId>isis-core-runtime</artifactId>
</dependency>
- <!-- isis testing -->
<dependency>
<groupId>org.apache.isis.core</groupId>
<artifactId>isis-core-wrapper</artifactId>
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemForTest.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemForTest.java b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemForTest.java
index 63b2c68..9f4f6d8 100644
--- a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemForTest.java
+++ b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemForTest.java
@@ -57,7 +57,7 @@ import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
import org.apache.isis.core.runtime.system.transaction.IsisTransaction.State;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.core.security.authentication.AuthenticationRequestNameOnly;
-import org.apache.isis.core.unittestsupport.scenarios.DomainServiceProvider;
+import org.apache.isis.core.specsupport.scenarios.DomainServiceProvider;
/**
* Wraps a plain {@link IsisSystemDefault}, and provides a number of features to assist with testing.
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/ScenarioExecutionForIntegration.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/ScenarioExecutionForIntegration.java b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/ScenarioExecutionForIntegration.java
new file mode 100644
index 0000000..dfc9653
--- /dev/null
+++ b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/ScenarioExecutionForIntegration.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.integtestsupport.scenarios;
+
+import org.apache.isis.applib.fixtures.InstallableFixture;
+import org.apache.isis.core.integtestsupport.IsisSystemForTest;
+import org.apache.isis.core.specsupport.scenarios.ScenarioExecution;
+
+
+/**
+ * An extension of {@link ScenarioExecution} for use within (coarse grained)
+ * integration tests and Cucumber specs where there is back-end database.
+ *
+ * <p>
+ * To this end it provides implementations of
+ * {@link #install(InstallableFixture...)} (to tear down/setup data)
+ * and of {@link #beginTran() begin} and {@link #endTran(boolean) end} (
+ * for transaction management.
+ */
+public class ScenarioExecutionForIntegration extends ScenarioExecution {
+
+ protected final IsisSystemForTest isft;
+
+ public ScenarioExecutionForIntegration(IsisSystemForTest isft) {
+ super(isft);
+ this.isft = isft;
+ }
+
+
+ // //////////////////////////////////////
+
+ /**
+ * Install arbitrary fixtures, eg before an integration tests or as part of a
+ * Cucumber step definitions or hook.
+ */
+ public void install(InstallableFixture... fixtures) {
+ isft.installFixtures(fixtures);
+ }
+
+ // //////////////////////////////////////
+
+ /**
+ * For Cucumber hooks to call, performing transaction management around each step.
+ */
+ public void beginTran() {
+ isft.beginTran();
+ }
+
+ /**
+ * For Cucumber hooks to call, performing transaction management around each step.
+ */
+ public void endTran(boolean ok) {
+ if(ok) {
+ isft.commitTran();
+ } else {
+ isft.abortTran();
+ }
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/ScenarioExecutionIntegrationScopeAbstract.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/ScenarioExecutionIntegrationScopeAbstract.java b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/ScenarioExecutionIntegrationScopeAbstract.java
deleted file mode 100644
index d511420..0000000
--- a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/ScenarioExecutionIntegrationScopeAbstract.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.isis.core.integtestsupport.scenarios;
-
-import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.fixtures.InstallableFixture;
-import org.apache.isis.applib.services.wrapper.WrapperFactory;
-import org.apache.isis.core.integtestsupport.IsisSystemForTest;
-import org.apache.isis.core.unittestsupport.scenarios.ScenarioExecution;
-
-
-/**
- * An extension of {@link ScenarioExecution} for use within (coarse grained)
- * integration tests and Cucumber specs where there is back-end database.
- *
- * <p>
- * To this end it provides the ability to
- * {@link #install(InstallableFixture...) install arbitrary fixtures} to
- * tear down/setup data, and also to methods to {@link #beginTran() begin}
- * or {@link #endTran(boolean) end} transactions.
- */
-public abstract class ScenarioExecutionIntegrationScopeAbstract extends ScenarioExecution {
-
- protected final IsisSystemForTest isft;
-
- public ScenarioExecutionIntegrationScopeAbstract(IsisSystemForTest isft) {
- super(isft);
- this.isft = isft;
- }
-
- // //////////////////////////////////////
-
- /**
- * Convenience
- */
- public DomainObjectContainer getContainer() {
- return service(DomainObjectContainer.class);
- }
-
- /**
- * Convenience
- */
- public WrapperFactory getWrapperFactory() {
- return service(WrapperFactory.class);
- }
-
-
- // //////////////////////////////////////
-
- /**
- * Install arbitrary fixtures, eg before an integration tests or as part of a
- * Cucumber step definitions or hook.
- */
- public void install(InstallableFixture... fixtures) {
- isft.installFixtures(fixtures);
- }
-
- // //////////////////////////////////////
-
- /**
- * For Cucumber hooks to call, performing transaction management around each step.
- */
- public void beginTran() {
- isft.beginTran();
- }
-
- /**
- * For Cucumber hooks to call, performing transaction management around each step.
- */
- public void endTran(boolean ok) {
- if(ok) {
- isft.commitTran();
- } else {
- isft.abortTran();
- }
- }
-
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/specs/CukeStepDefsIntegrationScopeAbstract.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/specs/CukeStepDefsIntegrationScopeAbstract.java b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/specs/CukeStepDefsIntegrationScopeAbstract.java
deleted file mode 100644
index 42ebce2..0000000
--- a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/scenarios/specs/CukeStepDefsIntegrationScopeAbstract.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.isis.core.integtestsupport.scenarios.specs;
-
-import cucumber.api.java.After;
-import cucumber.api.java.Before;
-
-import org.apache.isis.core.integtestsupport.scenarios.ScenarioExecutionIntegrationScopeAbstract;
-import org.apache.isis.core.unittestsupport.scenarios.specs.CukeStepDefsAbstract;
-
-
-/**
- * Base class for integration-scope Cucumber step definitions.
- */
-public abstract class CukeStepDefsIntegrationScopeAbstract extends CukeStepDefsAbstract<ScenarioExecutionIntegrationScopeAbstract> {
-
- public CukeStepDefsIntegrationScopeAbstract(ScenarioExecutionIntegrationScopeAbstract scenarioExecution) {
- super(scenarioExecution);
- }
-
- // //////////////////////////////////////
-
- /**
- * Convenience method to start transaction.
- *
- * <p>
- * Cukes does not allow this to be annotated with {@link Before Cucumber's Before}
- * annotation. Subclasses should therefore override, annotate, and delegate back up:
- *
- * <pre>
- * @cucumber.api.java.Before
- * @Override
- * public void beginTran() {
- * super.beginTran();
- * }
- * </pre>
- */
- public void beginTran() {
- scenarioExecution.beginTran();
- }
-
- /**
- * Convenience method to start transaction.
- *
- * <p>
- * Cukes does not allow this to be annotated with {@link After Cucumber's After}
- * annotation. Subclasses should therefore override, annotate, and delegate back up:
- *
- * <pre>
- * @cucumber.api.java.After
- * @Override
- * public void endTran(cucumber.api.Scenario sc) {
- * super.endTran(sc);
- * }
- * </pre>
- */
- public void endTran(cucumber.api.Scenario sc) {
- scenarioExecution.endTran(!sc.isFailed());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 57d51c5..e945910 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -989,7 +989,7 @@ ${license.additional-notes}
<!-- is also for benefit of application developers, using scope=import -->
<dependencies>
- <!-- isis-unittestsupport -->
+ <!-- unittestsupport -->
<dependency>
<groupId>org.apache.isis.core</groupId>
<artifactId>isis-core-unittestsupport</artifactId>
@@ -1069,7 +1069,14 @@ ${license.additional-notes}
<version>1.3.0-SNAPSHOT</version>
</dependency>
- <!-- isis-integtestsupport -->
+ <!-- specsupport -->
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-specsupport</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+
+ <!-- integtestsupport -->
<dependency>
<groupId>org.apache.isis.core</groupId>
<artifactId>isis-core-integtestsupport</artifactId>
@@ -1407,17 +1414,6 @@ ${license.additional-notes}
<artifactId>cucumber-junit</artifactId>
<version>1.1.4-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>info.cukes</groupId>
- <artifactId>cucumber-picocontainer</artifactId>
- <version>1.1.4-SNAPSHOT</version>
- </dependency>
-
- <dependency>
- <groupId>org.picocontainer</groupId>
- <artifactId>picocontainer</artifactId>
- <version>2.14.3</version>
- </dependency>
<!-- Testing libraries (scope=test) -->
<dependency>
@@ -1464,6 +1460,12 @@ ${license.additional-notes}
<version>1.7.1</version>
</dependency>
+ <dependency>
+ <groupId>org.picocontainer</groupId>
+ <artifactId>picocontainer</artifactId>
+ <version>2.14.3</version>
+ </dependency>
+
</dependencies>
</dependencyManagement>
@@ -1820,6 +1822,7 @@ ${license.additional-notes}
<module>security-noop</module>
<module>unittestsupport</module>
+ <module>specsupport</module>
<module>integtestsupport</module>
<module>wrapper</module>
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/specsupport/pom.xml
----------------------------------------------------------------------
diff --git a/core/specsupport/pom.xml b/core/specsupport/pom.xml
new file mode 100644
index 0000000..ea1a304
--- /dev/null
+++ b/core/specsupport/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+ license agreements. See the NOTICE file distributed with this work for additional
+ information regarding copyright ownership. The ASF licenses this file to
+ you under the Apache License, Version 2.0 (the "License"); you may not use
+ this file except in compliance with the License. You may obtain a copy of
+ the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>isis-core-specsupport</artifactId>
+ <name>Isis Core Spec Support</name>
+
+ <properties>
+ <siteBaseDir>..</siteBaseDir>
+ <relativeUrl>specsupport/</relativeUrl>
+ </properties>
+
+ <!-- used in Site generation for relative references. -->
+ <url>http://isis.apache.org/${relativeUrl}</url>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>${maven-project-info-reports-plugin}</version>
+ <inherited>false</inherited>
+ <configuration>
+ <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+ </configuration>
+ <reportSets>
+ <reportSet>
+ <inherited>false</inherited>
+ <reports>
+ <report>dependencies</report>
+ <report>dependency-convergence</report>
+ <report>plugins</report>
+ <report>summary</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-unittestsupport</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-applib</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>info.cukes</groupId>
+ <artifactId>cucumber-java</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>info.cukes</groupId>
+ <artifactId>cucumber-junit</artifactId>
+ </dependency>
+
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/DomainServiceProvider.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/DomainServiceProvider.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/DomainServiceProvider.java
new file mode 100644
index 0000000..e630f39
--- /dev/null
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/DomainServiceProvider.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.specsupport.scenarios;
+
+import org.apache.isis.applib.DomainObjectContainer;
+
+
+/**
+ * Provides access to the {@link DomainObjectContainer} and any other domain services
+ * that may have been configured.
+ *
+ * <p>
+ * For {@link ScenarioExecution scenario}s with integration-scope, these will be
+ * configured services for an end-to-end running system. For scenarios with
+ * unit-scope, these will typically be mocks.
+ */
+public interface DomainServiceProvider {
+
+ public abstract DomainObjectContainer getContainer();
+
+ public abstract <T> T getService(Class<T> serviceClass);
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java
new file mode 100644
index 0000000..04cc378
--- /dev/null
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java
@@ -0,0 +1,287 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.specsupport.scenarios;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.fixtures.InstallableFixture;
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
+
+
+/**
+ * Represents the currently executing scenario, allowing information to be shared
+ * between Cucumber step definitions (for unit- or integration- scoped), and also for
+ * integration tests.
+ *
+ * <p>
+ * Two types of information are available:
+ * <ul>
+ * <li>First, there are the domain services, provided using the {@link #service(Class) method}.
+ * If running at unit-scope, then these will most likely be mocked services (and not all services
+ * will necessarily be available). If running at integration-scope, then these will most likely
+ * be real instances, eg wired to the backend database.</li>
+ * <li>Second, there is a map of identified objects. This is predominantly for Cucumber
+ * step definitions (either unit- or integration-scoped), such that information can be passed
+ * between steps in a decoupled fashion.
+ * </ul>
+ *
+ * <p>
+ * When instantiated, this object binds itself to the current thread (using a {@link ThreadLocal}).
+ *
+ * <p>
+ * Subclasses may tailor the world for specific types of tests; for example the
+ * <tt>IntegrationScenarioExecution</tt> provides additional support for fixtures and
+ * transaction management, used both by integration-scoped specs and by integration tests.
+ */
+public class ScenarioExecution {
+
+ private static ThreadLocal<ScenarioExecution> current = new ThreadLocal<ScenarioExecution>();
+
+ public static ScenarioExecution current() {
+ final ScenarioExecution execution = current.get();
+ if(execution == null) {
+ throw new IllegalStateException("Scenario has not yet been instantiated by Cukes");
+ }
+ return execution;
+ }
+
+
+ // //////////////////////////////////////
+
+ protected final DomainServiceProvider dsp;
+
+ public ScenarioExecution(final DomainServiceProvider dsp) {
+ this.dsp = dsp;
+ current.set(this);
+ }
+
+ /**
+ * Returns a domain service of the specified type, ensuring that
+ * it is available.
+ *
+ * @throws IllegalStateException if not available
+ */
+ public <T> T service(Class<T> cls) {
+ final T service = dsp.getService(cls);
+ if(service == null) {
+ throw new IllegalStateException(
+ "No service of type "
+ + cls.getSimpleName()
+ + " available");
+ }
+ return service;
+ }
+
+ /**
+ * Convenience method, returning the {@link DomainObjectContainer},
+ * first ensuring that it is available.
+ *
+ * @throws IllegalStateException if not available
+ */
+ public DomainObjectContainer container() {
+ final DomainObjectContainer container = dsp.getContainer();
+ if(container == null) {
+ throw new IllegalStateException(
+ "No DomainObjectContainer available");
+ }
+ return container;
+ }
+
+ /**
+ * Convenience method, returning the {@link WrapperFactory} domain service,
+ * first ensuring that it is available.
+ *
+ * @throws IllegalStateException if not available
+ */
+ public WrapperFactory wrapperFactory() {
+ return service(WrapperFactory.class);
+ }
+
+
+ // //////////////////////////////////////
+
+ /**
+ * Key for objects stored by steps in the scenario.
+ *
+ * <p>
+ * Objects can be identified in a variety of manners:
+ * <ul>
+ * <li>a fully qualified object provides both its type and a (unique) id; for example 'lease OXF-TOPMODEL-001'</li>
+ * <li>a named object provides only its id; for example 'OXF-TOPMODEL-001'</li>
+ * <li>a typed object provides only its type; for example 'the lease'.</li>
+ * </ul>
+ *
+ * <p>
+ * Because of the second rule, the id should be unique in and of itself.
+ *
+ * <p>
+ * The expectation is that scenarios will use the first form (fully qualified) the first time that an
+ * object is introduced within a scenario. Thereafter either of the other forms may be used.
+ * In the case of a typed object (eg "the lease"), the most recently "touched" object of that type
+ * is returned.
+ */
+ public static class VariableId {
+ private final String type;
+ private final String id;
+ public VariableId(String type, String id) {
+ this.type = type;
+ this.id = id;
+ }
+
+ /**
+ * eg 'lease'
+ */
+ public String getType() {
+ return type;
+ }
+ /**
+ * eg 'OXF-TOPMODEL-001'
+ */
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ VariableId other = (VariableId) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (type == null) {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "VariableId [type=" + type + ", id=" + id + "]";
+ }
+ }
+
+ private final Map<VariableId, Object> objectByVariableId = Maps.newLinkedHashMap();
+ private final Map<String, Object> objectsById = Maps.newLinkedHashMap();
+
+ private final Map<String, Object> mostRecent = Maps.newHashMap();
+
+ public void put(String type, String id, Object value) {
+ objectByVariableId.put(new VariableId(type, id), value);
+ mostRecent.put(type, value);
+ }
+
+ /**
+ * Retrieve an object previously used in the scenario.
+ *
+ * <p>
+ * Must specify type and/or id.
+ *
+ * @see VariableId - for rules on what constitutes an identifier.
+ */
+ public Object get(String type, String id) {
+ if(type != null && id != null) {
+ final VariableId variableId = new VariableId(type,id);
+ final Object value = objectByVariableId.get(variableId);
+ if(value != null) {
+ mostRecent.put(type, value);
+ return value;
+ }
+ throw new IllegalStateException("No such " + variableId);
+ }
+ if(type != null && id == null) {
+ return mostRecent.get(type);
+ }
+ if(type == null && id != null) {
+ final Object value = objectsById.get(id);
+ if(value != null) {
+ mostRecent.put(type, value);
+ }
+ return value;
+ }
+ throw new IllegalArgumentException("Must specify type and/or id");
+ }
+
+ /**
+ * As {@link #get(String, String)}, but downcasting to the provided class.
+ */
+ @SuppressWarnings("unchecked")
+ public <X> X get(String type, String id, Class<X> cls) {
+ return (X) get(type, id);
+ }
+
+ // //////////////////////////////////////
+
+ /**
+ * Install arbitrary fixtures, eg before an integration tests or as part of a
+ * Cucumber step definitions or hook.
+ *
+ * <p>
+ * This implementation has a no-op, but subclasses of this class tailored to
+ * supporting integration specs/tests are expected to override.
+ */
+ public void install(InstallableFixture... fixtures) {
+ // do nothing
+ }
+
+ // //////////////////////////////////////
+
+ /**
+ * For Cucumber hooks to call, performing transaction management around each step.
+ *
+ * <p>
+ * This implementation has a no-op, but subclasses of this class tailored to
+ * supporting integration specs are expected to override. (Integration tests can use
+ * the <tt>IsisTransactionRule</tt> to do transaction management transparently).
+ */
+ public void beginTran() {
+ // do nothing
+ }
+
+ /**
+ * For Cucumber hooks to call, performing transaction management around each step.
+ *
+ * <p>
+ * This implementation has a no-op, but subclasses of this class tailored to
+ * supporting integration specs are expected to override. (Integration tests can use
+ * the <tt>IsisTransactionRule</tt> to do transaction management transparently).
+ */
+ public void endTran(boolean ok) {
+ // do nothing
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java
new file mode 100644
index 0000000..3c8f487
--- /dev/null
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.specsupport.scenarios;
+
+
+/**
+ * The scope at which the specification will run; acts as a factory to create
+ * an instance of the appropriate subclass of {@link ScenarioExecution}.
+ */
+public class ScenarioExecutionScope {
+
+ public final static ScenarioExecutionScope UNIT = new ScenarioExecutionScope(ScenarioExecution.class);
+
+ private final Class<? extends ScenarioExecution> scenarioExecutionClass;
+
+ public ScenarioExecutionScope(Class<? extends ScenarioExecution> scenarioExecutionClass) {
+ this.scenarioExecutionClass = scenarioExecutionClass;
+ }
+
+ public ScenarioExecution instantiate() {
+ try {
+ return scenarioExecutionClass.newInstance();
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return scenarioExecutionClass.getName();
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeSpecsAbstract.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeSpecsAbstract.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeSpecsAbstract.java
new file mode 100644
index 0000000..7d6295d
--- /dev/null
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeSpecsAbstract.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.specsupport.specs;
+
+import cucumber.api.junit.Cucumber;
+
+import org.junit.runner.RunWith;
+
+/**
+ * Base class for all Cucumber specs run at unit-scope; runs the spec as a JUnit test.
+ */
+@RunWith(Cucumber.class)
+@Cucumber.Options(
+ format = {
+ "html:target/cucumber-html-report"
+ // addHook causes an exception to be thrown if this reporter is registered...
+ // ,"json-pretty:target/cucumber-json-report.json"
+ },
+ strict = true,
+ tags = { "~@backlog" })
+public abstract class CukeSpecsAbstract {
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java
new file mode 100644
index 0000000..45de214
--- /dev/null
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java
@@ -0,0 +1,148 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.specsupport.specs;
+
+import cucumber.api.java.Before;
+
+import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
+import org.apache.isis.core.specsupport.scenarios.ScenarioExecution;
+import org.apache.isis.core.specsupport.scenarios.ScenarioExecutionScope;
+
+/**
+ * Base class for unit-scope Cucumber step definitions.
+ *
+ * <p>
+ * Simply declares that an instance of {@link ScenarioExecution} (or a subclass)
+ * must be instantiated by the Cucumber-JVM runtime and injected into the step definitions.
+ */
+public abstract class CukeStepDefsAbstract {
+
+ private ScenarioExecution scenarioExecution;
+
+ /**
+ * Access the {@link ScenarioExecution} as setup through a previous call to {@link #before(ScenarioExecutionScope)}.
+ *
+ * <p>
+ * This corresponds, broadly, to the (Ruby) Cucumber's "World" object.
+ */
+ protected ScenarioExecution scenarioExecution() {
+ if(scenarioExecution == null) {
+ throw new IllegalStateException("The scenario execution has not been set up; call #before(ScenarioExecutionScope) first");
+ }
+ return scenarioExecution;
+ }
+
+ /**
+ * Convenience
+ */
+ protected <T> T service(Class<T> cls) {
+ return scenarioExecution().service(cls);
+ }
+
+ /**
+ * Convenience
+ */
+ protected DomainObjectContainer container() {
+ return scenarioExecution().container();
+ }
+
+ /**
+ * Convenience
+ */
+ protected WrapperFactory wrapperFactory() {
+ return scenarioExecution().wrapperFactory()
+ }
+
+ // //////////////////////////////////////
+
+ /**
+ * Indicate that a scenario is starting, and specify the {@link ScenarioExecutionScope scope}
+ * at which to run the scenario.
+ *
+ * <p>
+ * This method should be called from a "before" hook (a method annotated with
+ * Cucumber's {@link Before} annotation, in a step definition subclass. The tag
+ * should be appropriate for the scope specified. Typically this method should be delegated to
+ * twice, in two mutually exclusive before hooks.
+ *
+ * <p>
+ * Calling this method makes the {@link ScenarioExecution} available (via {@link #scenarioExecution()}).
+ * It also delegates to the scenario to {@link ScenarioExecution#beginTran() begin the transaction}.
+ * (Whether this actually does anything depends in implementation of the {@link ScenarioExecution}).
+ *
+ * <p>
+ * The boilerplate (to copy-n-paste as required) is:
+ * <pre>
+ * @cucumber.api.java.Before("@unit")
+ * public void beforeScenarioUnitScope() {
+ * before(ScenarioExecutionScope.UNIT);
+ * }
+ * @cucumber.api.java.Before("@integration")
+ * public void beforeScenarioIntegrationScope() {
+ * before(new ScenarioExecutionScope(ScenarioExecutionForMyAppIntegration.class));
+ * }
+ * </pre>
+ * where <tt>ScenarioExecutionForMyAppIntegration</tt> is an application-specific subclass of
+ * {@link ScenarioExecution} for integration-testing. Typically this is done using the
+ * <tt>IsisSystemForTest</tt> class provided in the <tt>isis-core-integtestsupport</tt> module).
+ *
+ * <p>
+ * Not every class holding step definitions should have these hooks, only those that correspond to the logical
+ * beginning and end of scenario. As such, this method may only be called once per scenario execution
+ * (and fails fast if called more than once).
+ */
+ protected void before(ScenarioExecutionScope scope) {
+ if(scenarioExecution != null) {
+ throw new IllegalStateException("Scenario execution scope has already been set");
+ }
+ scenarioExecution = scope.instantiate();
+ scenarioExecution.beginTran();
+ }
+
+ /**
+ * Indicate that a scenario is ending; the {@link ScenarioExecution} is discarded and no
+ * longer {@link #scenarioExecution() available}.
+ *
+ * <p>
+ * Before being discarded, the {@link ScenarioExecution} is delegated to
+ * in order to {@link ScenarioExecution#endTran(boolean) end the transaction}.
+ * (Whether this actually does anything depends in implementation of the {@link ScenarioExecution}).
+ *
+ * <p>
+ * The boilerplate (to copy-n-paste as required) is:
+ * <pre>
+ * @cucumber.api.java.After
+ * public void afterScenario(cucumber.api.Scenario sc) {
+ * after(sc);
+ * }
+ * </pre>
+ *
+ * <p>
+ * Not every class holding step definitions should have this hook, only those that correspond to the logical
+ * beginning and end of scenario. As such, this method may only be called once per scenario execution
+ * (and fails fast if called more than once).
+ */
+ public void after(cucumber.api.Scenario sc) {
+ if(scenarioExecution == null) {
+ throw new IllegalStateException("Scenario execution is not set");
+ }
+ scenarioExecution.endTran(!sc.isFailed());
+ scenarioExecution = null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/V.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/V.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/V.java
new file mode 100644
index 0000000..a67ce51
--- /dev/null
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/V.java
@@ -0,0 +1,332 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.specsupport.specs;
+
+import cucumber.api.Transformer;
+
+import org.joda.time.format.DateTimeFormat;
+
+/**
+ * A set of converters for built-in value types; for use in Cucumber step definitions.
+ */
+public class V {
+
+ private V() {
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.Byte}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class Byte extends Transformer<java.lang.Byte> {
+
+ @Override
+ public java.lang.Byte transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : java.lang.Byte.parseByte(value);
+ }
+
+ public static java.lang.Byte as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new Byte().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.Short}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class Short extends Transformer<java.lang.Short> {
+
+ @Override
+ public java.lang.Short transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : java.lang.Short.parseShort(value);
+ }
+
+ public static java.lang.Short as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new Short().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.Integer}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class Integer extends Transformer<java.lang.Integer> {
+
+ @Override
+ public java.lang.Integer transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : java.lang.Integer.parseInt(value);
+ }
+
+ public static java.lang.Integer as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new Integer().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.Long}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class Long extends Transformer<java.lang.Long> {
+
+ @Override
+ public java.lang.Long transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : java.lang.Long.parseLong(value);
+ }
+
+ public static java.lang.Long as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new Long().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.Float}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class Float extends Transformer<java.lang.Float> {
+
+ @Override
+ public java.lang.Float transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : java.lang.Float.parseFloat(value);
+ }
+
+ public static java.lang.Float as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new Float().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.Double}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class Double extends Transformer<java.lang.Double> {
+
+ @Override
+ public java.lang.Double transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : java.lang.Double.parseDouble(value);
+ }
+
+ public static java.lang.Double as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new Double().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.BigInteger}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class BigInteger extends Transformer<java.math.BigInteger> {
+
+ @Override
+ public java.math.BigInteger transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : new java.math.BigInteger(value);
+ }
+
+ public static java.math.BigInteger as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new BigInteger().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.BigDecimal}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class BigDecimal extends Transformer<java.math.BigDecimal> {
+
+ @Override
+ public java.math.BigDecimal transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : new java.math.BigDecimal(value);
+ }
+
+ public static java.math.BigDecimal as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new BigDecimal().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.Character}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class Character extends Transformer<java.lang.Character> {
+
+ @Override
+ public java.lang.Character transform(java.lang.String value) {
+ return value == null || "null".equals(value) || value.length() <1
+ ? null
+ : value.charAt(0);
+ }
+
+ public static java.lang.Character as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new Character().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link java.lang.String}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class String extends Transformer<java.lang.String> {
+
+ @Override
+ public java.lang.String transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : value;
+ }
+
+ public static java.lang.String as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new String().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link org.joda.time.LocalDate}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class LyyyyMMdd extends Transformer<org.joda.time.LocalDate> {
+
+ @Override
+ public org.joda.time.LocalDate transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : DateTimeFormat.forPattern("yyyy-MM-dd").parseLocalDate(value);
+ }
+
+ public static org.joda.time.LocalDate as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new LyyyyMMdd().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link org.joda.time.DateTime}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class yyyyMMddHHmmss extends Transformer<org.joda.time.DateTime> {
+
+ @Override
+ public org.joda.time.DateTime transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(value);
+ }
+
+ public static org.joda.time.DateTime as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new yyyyMMddHHmmss().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link org.joda.time.DateTime}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class yyyyMMddHHmm extends Transformer<org.joda.time.DateTime> {
+
+ @Override
+ public org.joda.time.DateTime transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").parseDateTime(value);
+ }
+
+ public static org.joda.time.DateTime as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new yyyyMMddHHmmss().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link org.joda.time.LocalDateTime}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class LyyyyMMddHHmm extends Transformer<org.joda.time.LocalDateTime> {
+
+ @Override
+ public org.joda.time.LocalDateTime transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").parseLocalDateTime(value);
+ }
+
+ public static org.joda.time.DateTime as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new yyyyMMddHHmmss().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+ /**
+ * Converts {@link java.lang.String}s to {@link org.joda.time.LocalDateTime}, but also recognizing the
+ * keyword 'null'.
+ */
+ public static class LyyyyMMddHHmmss extends Transformer<org.joda.time.LocalDateTime> {
+
+ @Override
+ public org.joda.time.LocalDateTime transform(java.lang.String value) {
+ return value == null || "null".equals(value)
+ ? null
+ : DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseLocalDateTime(value);
+ }
+
+ public static org.joda.time.DateTime as(Object value) {
+ return value != null && value instanceof java.lang.String
+ ? new yyyyMMddHHmmss().transform((java.lang.String) value)
+ : null;
+ }
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/unittestsupport/pom.xml
----------------------------------------------------------------------
diff --git a/core/unittestsupport/pom.xml b/core/unittestsupport/pom.xml
index 893b3a1..b329cb4 100644
--- a/core/unittestsupport/pom.xml
+++ b/core/unittestsupport/pom.xml
@@ -94,23 +94,6 @@
</dependency>
<dependency>
- <groupId>joda-time</groupId>
- <artifactId>joda-time</artifactId>
- </dependency>
- <dependency>
- <groupId>info.cukes</groupId>
- <artifactId>cucumber-java</artifactId>
- </dependency>
- <dependency>
- <groupId>info.cukes</groupId>
- <artifactId>cucumber-picocontainer</artifactId>
- </dependency>
- <dependency>
- <groupId>info.cukes</groupId>
- <artifactId>cucumber-junit</artifactId>
- </dependency>
-
- <dependency>
<groupId>javax.jdo</groupId>
<artifactId>jdo-api</artifactId>
<version>3.0.1</version>
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/DomainServiceProvider.java
----------------------------------------------------------------------
diff --git a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/DomainServiceProvider.java b/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/DomainServiceProvider.java
deleted file mode 100644
index cbfaa72..0000000
--- a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/DomainServiceProvider.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.isis.core.unittestsupport.scenarios;
-
-
-public interface DomainServiceProvider {
-
- public abstract <T> T getService(Class<T> serviceClass);
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/ScenarioExecution.java
----------------------------------------------------------------------
diff --git a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/ScenarioExecution.java b/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/ScenarioExecution.java
deleted file mode 100644
index 004d52f..0000000
--- a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/ScenarioExecution.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.isis.core.unittestsupport.scenarios;
-
-import java.util.Map;
-
-import com.google.common.collect.Maps;
-
-
-/**
- * Represents the currently executing scenario, allowing information to be shared
- * between Cucumber step definitions (for unit- or integration- scoped), and also for
- * integration tests.
- *
- * <p>
- * Two types of information are available:
- * <ul>
- * <li>First, there are the domain services, provided using the {@link #service(Class) method}.
- * If running at unit-scope, then these will most likely be mocked services (and not all services
- * will necessarily be available). If running at integration-scope, then these will most likely
- * be real instances, eg wired to the backend database.</li>
- * <li>Second, there is a map of identified objects. This is predominantly for Cucumber
- * step definitions (either unit- or integration-scoped), such that information can be passed
- * between steps in a decoupled fashion.
- * </ul>
- *
- * <p>
- * When instantiated, this object binds itself to the current thread (using a {@link ThreadLocal}).
- *
- * <p>
- * Subclasses may tailor the world for specific types of tests; for example the
- * <tt>IntegrationScenarioExecution</tt> provides additional support for fixtures and
- * transaction management, used both by integration-scoped specs and by integration tests.
- */
-public class ScenarioExecution {
-
- private static ThreadLocal<ScenarioExecution> current = new ThreadLocal<ScenarioExecution>();
-
- public static ScenarioExecution current() {
- final ScenarioExecution world = current.get();
- if(world == null) {
- throw new IllegalStateException("Scenario has not yet been instantiated by Cukes");
- }
- return world;
- }
-
-
- // //////////////////////////////////////
-
- protected final DomainServiceProvider dsp;
-
- /**
- * For instantiation by Cucumber-JVM only.
- */
- public ScenarioExecution(final DomainServiceProvider dsp) {
- this.dsp = dsp;
- current.set(this);
- }
-
- public <T> T service(Class<T> cls) {
- final T service = dsp.getService(cls);
- if(service == null) {
- throw new IllegalStateException(
- "No service of type "
- + cls.getSimpleName()
- + " available");
- }
- return service;
- }
-
-
- // //////////////////////////////////////
-
- /**
- * Key for objects stored by steps in the scenario.
- *
- * <p>
- * Objects can be identified in a variety of manners:
- * <ul>
- * <li>a fully qualified object provides both its type and a (unique) id; for example 'lease OXF-TOPMODEL-001'</li>
- * <li>a named object provides only its id; for example 'OXF-TOPMODEL-001'</li>
- * <li>a typed object provides only its type; for example 'the lease'.</li>
- * </ul>
- *
- * <p>
- * Because of the second rule, the id should be unique in and of itself.
- *
- * <p>
- * The expectation is that scenarios will use the first form (fully qualified) the first time that an
- * object is introduced within a scenario. Thereafter either of the other forms may be used.
- * In the case of a typed object (eg "the lease"), the most recently "touched" object of that type
- * is returned.
- */
- public static class VariableId {
- private final String type;
- private final String id;
- public VariableId(String type, String id) {
- this.type = type;
- this.id = id;
- }
-
- /**
- * eg 'lease'
- */
- public String getType() {
- return type;
- }
- /**
- * eg 'OXF-TOPMODEL-001'
- */
- public String getId() {
- return id;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((id == null) ? 0 : id.hashCode());
- result = prime * result + ((type == null) ? 0 : type.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- VariableId other = (VariableId) obj;
- if (id == null) {
- if (other.id != null)
- return false;
- } else if (!id.equals(other.id))
- return false;
- if (type == null) {
- if (other.type != null)
- return false;
- } else if (!type.equals(other.type))
- return false;
- return true;
- }
-
- @Override
- public String toString() {
- return "VariableId [type=" + type + ", id=" + id + "]";
- }
- }
-
- private final Map<VariableId, Object> objectByVariableId = Maps.newLinkedHashMap();
- private final Map<String, Object> objectsById = Maps.newLinkedHashMap();
-
- private final Map<String, Object> mostRecent = Maps.newHashMap();
-
- public void put(String type, String id, Object value) {
- objectByVariableId.put(new VariableId(type, id), value);
- mostRecent.put(type, value);
- }
-
- /**
- * Retrieve an object previously used in the scenario.
- *
- * <p>
- * Must specify type and/or id.
- *
- * @see VariableId - for rules on what constitutes an identifier.
- */
- public Object get(String type, String id) {
- if(type != null && id != null) {
- final VariableId variableId = new VariableId(type,id);
- final Object value = objectByVariableId.get(variableId);
- if(value != null) {
- mostRecent.put(type, value);
- return value;
- }
- throw new IllegalStateException("No such " + variableId);
- }
- if(type != null && id == null) {
- return mostRecent.get(type);
- }
- if(type == null && id != null) {
- final Object value = objectsById.get(id);
- if(value != null) {
- mostRecent.put(type, value);
- }
- return value;
- }
- throw new IllegalArgumentException("Must specify type and/or id");
- }
-
- /**
- * As {@link #get(String, String)}, but downcasting to the provided class.
- */
- @SuppressWarnings("unchecked")
- public <X> X get(String type, String id, Class<X> cls) {
- return (X) get(type, id);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/CukeSpecsAbstract.java
----------------------------------------------------------------------
diff --git a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/CukeSpecsAbstract.java b/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/CukeSpecsAbstract.java
deleted file mode 100644
index 57b4dcd..0000000
--- a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/CukeSpecsAbstract.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.isis.core.unittestsupport.scenarios.specs;
-
-import cucumber.api.junit.Cucumber;
-
-import org.junit.runner.RunWith;
-
-/**
- * Base class for all Cucumber specs run at unit-scope; runs the spec as a JUnit test.
- */
-@RunWith(Cucumber.class)
-@Cucumber.Options(
- format = {
- "html:target/cucumber-html-report"
- // addHook causes an exception to be thrown if this reporter is registered...
- // ,"json-pretty:target/cucumber-json-report.json"
- },
- strict = true,
- tags = { "~@backlog" })
-public abstract class CukeSpecsAbstract {
-
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/CukeStepDefsAbstract.java
----------------------------------------------------------------------
diff --git a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/CukeStepDefsAbstract.java b/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/CukeStepDefsAbstract.java
deleted file mode 100644
index 0a0693e..0000000
--- a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/CukeStepDefsAbstract.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.isis.core.unittestsupport.scenarios.specs;
-
-import org.apache.isis.core.unittestsupport.scenarios.ScenarioExecution;
-
-/**
- * Base class for unit-scope Cucumber step definitions.
- *
- * <p>
- * Simply declares that an instance of (a concrete subclass of)
- * {@link ScenarioExecution} must be instantiated by the Cucumber-JVM
- * runtime and injected into the step definitions.
- */
-public abstract class CukeStepDefsAbstract<T extends ScenarioExecution> {
-
- protected final T scenarioExecution;
-
- public CukeStepDefsAbstract(T scenarioExecution) {
- this.scenarioExecution = scenarioExecution;
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/dd7f283c/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/V.java
----------------------------------------------------------------------
diff --git a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/V.java b/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/V.java
deleted file mode 100644
index a4691f8..0000000
--- a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/scenarios/specs/V.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.isis.core.unittestsupport.scenarios.specs;
-
-import cucumber.api.Transformer;
-
-import org.joda.time.format.DateTimeFormat;
-
-/**
- * A set of converters for built-in value types; for use in Cucumber step definitions.
- */
-public class V {
-
- private V() {
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.Byte}, but also recognizing the
- * keyword 'null'.
- */
- public static class Byte extends Transformer<java.lang.Byte> {
-
- @Override
- public java.lang.Byte transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : java.lang.Byte.parseByte(value);
- }
-
- public static java.lang.Byte as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new Byte().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.Short}, but also recognizing the
- * keyword 'null'.
- */
- public static class Short extends Transformer<java.lang.Short> {
-
- @Override
- public java.lang.Short transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : java.lang.Short.parseShort(value);
- }
-
- public static java.lang.Short as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new Short().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.Integer}, but also recognizing the
- * keyword 'null'.
- */
- public static class Integer extends Transformer<java.lang.Integer> {
-
- @Override
- public java.lang.Integer transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : java.lang.Integer.parseInt(value);
- }
-
- public static java.lang.Integer as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new Integer().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.Long}, but also recognizing the
- * keyword 'null'.
- */
- public static class Long extends Transformer<java.lang.Long> {
-
- @Override
- public java.lang.Long transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : java.lang.Long.parseLong(value);
- }
-
- public static java.lang.Long as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new Long().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.Float}, but also recognizing the
- * keyword 'null'.
- */
- public static class Float extends Transformer<java.lang.Float> {
-
- @Override
- public java.lang.Float transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : java.lang.Float.parseFloat(value);
- }
-
- public static java.lang.Float as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new Float().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.Double}, but also recognizing the
- * keyword 'null'.
- */
- public static class Double extends Transformer<java.lang.Double> {
-
- @Override
- public java.lang.Double transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : java.lang.Double.parseDouble(value);
- }
-
- public static java.lang.Double as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new Double().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.BigInteger}, but also recognizing the
- * keyword 'null'.
- */
- public static class BigInteger extends Transformer<java.math.BigInteger> {
-
- @Override
- public java.math.BigInteger transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : new java.math.BigInteger(value);
- }
-
- public static java.math.BigInteger as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new BigInteger().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.BigDecimal}, but also recognizing the
- * keyword 'null'.
- */
- public static class BigDecimal extends Transformer<java.math.BigDecimal> {
-
- @Override
- public java.math.BigDecimal transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : new java.math.BigDecimal(value);
- }
-
- public static java.math.BigDecimal as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new BigDecimal().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.Character}, but also recognizing the
- * keyword 'null'.
- */
- public static class Character extends Transformer<java.lang.Character> {
-
- @Override
- public java.lang.Character transform(java.lang.String value) {
- return value == null || "null".equals(value) || value.length() <1
- ? null
- : value.charAt(0);
- }
-
- public static java.lang.Character as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new Character().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link java.lang.String}, but also recognizing the
- * keyword 'null'.
- */
- public static class String extends Transformer<java.lang.String> {
-
- @Override
- public java.lang.String transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : value;
- }
-
- public static java.lang.String as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new String().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link org.joda.time.LocalDate}, but also recognizing the
- * keyword 'null'.
- */
- public static class LyyyyMMdd extends Transformer<org.joda.time.LocalDate> {
-
- @Override
- public org.joda.time.LocalDate transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : DateTimeFormat.forPattern("yyyy-MM-dd").parseLocalDate(value);
- }
-
- public static org.joda.time.LocalDate as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new LyyyyMMdd().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link org.joda.time.DateTime}, but also recognizing the
- * keyword 'null'.
- */
- public static class yyyyMMddHHmmss extends Transformer<org.joda.time.DateTime> {
-
- @Override
- public org.joda.time.DateTime transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(value);
- }
-
- public static org.joda.time.DateTime as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new yyyyMMddHHmmss().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link org.joda.time.DateTime}, but also recognizing the
- * keyword 'null'.
- */
- public static class yyyyMMddHHmm extends Transformer<org.joda.time.DateTime> {
-
- @Override
- public org.joda.time.DateTime transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").parseDateTime(value);
- }
-
- public static org.joda.time.DateTime as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new yyyyMMddHHmmss().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link org.joda.time.LocalDateTime}, but also recognizing the
- * keyword 'null'.
- */
- public static class LyyyyMMddHHmm extends Transformer<org.joda.time.LocalDateTime> {
-
- @Override
- public org.joda.time.LocalDateTime transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").parseLocalDateTime(value);
- }
-
- public static org.joda.time.DateTime as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new yyyyMMddHHmmss().transform((java.lang.String) value)
- : null;
- }
- }
-
- /**
- * Converts {@link java.lang.String}s to {@link org.joda.time.LocalDateTime}, but also recognizing the
- * keyword 'null'.
- */
- public static class LyyyyMMddHHmmss extends Transformer<org.joda.time.LocalDateTime> {
-
- @Override
- public org.joda.time.LocalDateTime transform(java.lang.String value) {
- return value == null || "null".equals(value)
- ? null
- : DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseLocalDateTime(value);
- }
-
- public static org.joda.time.DateTime as(Object value) {
- return value != null && value instanceof java.lang.String
- ? new yyyyMMddHHmmss().transform((java.lang.String) value)
- : null;
- }
- }
-
-
-}
\ No newline at end of file