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 2015/02/14 15:01:06 UTC
[09/29] isis git commit: ISIS-928: mothballing the todoapp (example
app and archetype)
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java b/mothballed/example/application/todoapp/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java
new file mode 100644
index 0000000..c859340
--- /dev/null
+++ b/mothballed/example/application/todoapp/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java
@@ -0,0 +1,165 @@
+/**
+ * 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 integration.glue.todoitem;
+
+import cucumber.api.java.en.Given;
+import cucumber.api.java.en.Then;
+import cucumber.api.java.en.When;
+import dom.todo.ToDoItem;
+import dom.todo.ToDoItems;
+
+import java.util.List;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.jmock.Expectations;
+import org.junit.Assert;
+import org.apache.isis.applib.services.actinvoc.ActionInvocationContext;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.specsupport.scenarios.InMemoryDB;
+import org.apache.isis.core.specsupport.specs.CukeGlueAbstract;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ToDoItemGlue extends CukeGlueAbstract {
+
+ @Given("^there are a number of incomplete ToDo items$")
+ public void there_are_a_number_of_incomplete_ToDo_items() throws Throwable {
+ if(supportsMocks()) {
+ checking(new Expectations() {
+ {
+ allowing(service(ToDoItems.class)).notYetComplete();
+ will(returnValue(notYetCompleteItems()));
+ }
+ });
+ }
+ try {
+ final List<ToDoItem> notYetComplete = service(ToDoItems.class).notYetComplete();
+ assertThat(notYetComplete.isEmpty(), is(false));
+ putVar("list", "notYetCompleteItems", notYetComplete);
+
+ } finally {
+ assertMocksSatisfied();
+ }
+ }
+
+ @When("^I choose the first of the incomplete items$")
+ public void I_choose_the_first_one() throws Throwable {
+ @SuppressWarnings("unchecked")
+ List<ToDoItem> notYetComplete = getVar(null, "notYetCompleteItems", List.class);
+ assertThat(notYetComplete.isEmpty(), is(false));
+
+ putVar("todo", "toDoItem", notYetComplete.get(0));
+ }
+
+ @When("^mark the item as complete$")
+ public void mark_it_as_complete() throws Throwable {
+ final ToDoItem toDoItem = getVar(null, "toDoItem", ToDoItem.class);
+ if(supportsMocks()) {
+ final ActionInvocationContext actionInvocationContext = service(ActionInvocationContext.class);
+ final EventBusService eventBusService = service(EventBusService.class);
+ checking(new Expectations() {
+ {
+ allowing(actionInvocationContext);
+ allowing(eventBusService);
+ }
+ });
+ toDoItem.actionInvocationContext = actionInvocationContext;
+ toDoItem.eventBusService = eventBusService;
+ }
+ wrap(toDoItem).completed();
+ }
+
+ @Then("^the item is no longer listed as incomplete$")
+ public void the_item_is_no_longer_listed_as_incomplete() throws Throwable {
+ ToDoItem toDoItem = getVar(null, "toDoItem", ToDoItem.class);
+ whetherNotYetCompletedContains(toDoItem, false);
+ }
+
+ @Given("^.*completed .*item$")
+ public void a_completed_ToDo_item() throws Throwable {
+ if(supportsMocks()) {
+ checking(new Expectations(){{
+ allowing(service(ToDoItems.class)).allToDos();
+ will(returnValue(findItems(Predicates.<ToDoItem>alwaysTrue()) ));
+ }});
+ }
+ try {
+ final List<ToDoItem> allToDos = service(ToDoItems.class).allToDos();
+ for (ToDoItem toDoItem : allToDos) {
+ if(toDoItem.isComplete()) {
+ putVar("todo", "toDoItem", toDoItem);
+ return;
+ }
+ }
+ Assert.fail("could not locate any completed ToDo items");
+ } finally {
+ assertMocksSatisfied();
+ }
+ }
+
+ @When("^I mark the .*item as not yet complete$")
+ public void I_mark_it_as_not_yet_complete() throws Throwable {
+ ToDoItem toDoItem = getVar(null, "toDoItem", ToDoItem.class);
+ assertThat(toDoItem.isComplete(), is(true));
+
+ toDoItem.setComplete(false);
+ }
+
+ @Then("^the .*item is listed as incomplete$")
+ public void the_item_is_listed_as_incomplete() throws Throwable {
+ ToDoItem toDoItem = getVar(null, "toDoItem", ToDoItem.class);
+ whetherNotYetCompletedContains(toDoItem, true);
+ }
+
+ private void whetherNotYetCompletedContains(ToDoItem toDoItem, final boolean whetherContained) {
+ if(supportsMocks()) {
+ final List<ToDoItem> notYetCompleteItems = notYetCompleteItems();
+ checking(new Expectations() {
+ {
+ oneOf(service(ToDoItems.class)).notYetComplete();
+ will(returnValue(notYetCompleteItems));
+ }
+ });
+ }
+ try {
+ final List<ToDoItem> notYetComplete = service(ToDoItems.class).notYetComplete();
+ assertThat(notYetComplete.contains(toDoItem), is(whetherContained));
+ } finally {
+ assertMocksSatisfied();
+ }
+ }
+
+
+ // helper
+ private List<ToDoItem> notYetCompleteItems() {
+ return findItems(new Predicate<ToDoItem>(){
+ @Override
+ public boolean apply(ToDoItem input) {
+ return !input.isComplete();
+ }
+ });
+ }
+
+ private List<ToDoItem> findItems(final Predicate<ToDoItem> predicate) {
+ final InMemoryDB inMemoryDB = getVar("isis", "in-memory-db", InMemoryDB.class);
+ final List<ToDoItem> items = inMemoryDB.findAll(ToDoItem.class);
+ return Lists.newArrayList(Iterables.filter(items, predicate));
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/RunSpecs.java
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/RunSpecs.java b/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/RunSpecs.java
new file mode 100644
index 0000000..dcb56ad
--- /dev/null
+++ b/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/RunSpecs.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 integration.specs.todoitem;
+
+import cucumber.api.junit.Cucumber;
+
+import org.junit.runner.RunWith;
+
+
+/**
+ * Runs scenarios in all <tt>.feature</tt> files (this package and any subpackages).
+ */
+@RunWith(Cucumber.class)
+@Cucumber.Options(
+ format = {
+ "html:target/cucumber-html-report"
+ ,"json:target/cucumber.json"
+ },
+ glue={"classpath:integration.glue"},
+ strict = true,
+ tags = { "~@backlog", "~@ignore" })
+public class RunSpecs {
+ // intentionally empty
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findAndComplete.feature
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findAndComplete.feature b/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findAndComplete.feature
new file mode 100644
index 0000000..9fc1596
--- /dev/null
+++ b/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findAndComplete.feature
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+@ToDoItemsFixture
+Feature: Find And Complete ToDo Items
+
+ # the scenario is listed twice here just to demonstrate that it
+ # can be run either at @unit-level scope (using mocks) or
+ # at @integration-level scope (against the running system).
+
+ @unit
+ Scenario: Todo items once completed are no longer listed
+ Given there are a number of incomplete ToDo items
+ When I choose the first of the incomplete items
+ And mark the item as complete
+ Then the item is no longer listed as incomplete
+
+
+ @integration
+ Scenario: Todo items once completed are no longer listed
+ Given there are a number of incomplete ToDo items
+ When I choose the first of the incomplete items
+ And mark the item as complete
+ Then the item is no longer listed as incomplete
+
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findCompletedAndMarkAsNotYetComplete.feature
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findCompletedAndMarkAsNotYetComplete.feature b/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findCompletedAndMarkAsNotYetComplete.feature
new file mode 100644
index 0000000..1f5f73e
--- /dev/null
+++ b/mothballed/example/application/todoapp/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findCompletedAndMarkAsNotYetComplete.feature
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+@ToDoItemsFixture
+Feature: Find completed ToDoItem and mark as not yet complete
+
+ # the scenario is listed twice here just to demonstrate that it
+ # can be run either at @unit-level scope (using mocks) or
+ # at @integration-level scope (against the running system).
+
+ @integration
+ Scenario: Todo items can be uncompleted
+ Given a completed item
+ When I mark the item as not yet complete
+ Then the item is listed as incomplete
+
+
+ @unit
+ Scenario: Todo items can be uncompleted
+ Given a completed ToDo item
+ When I mark the item as not yet complete
+ Then the item is listed as incomplete
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/AbstractToDoIntegTest.java
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/AbstractToDoIntegTest.java b/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/AbstractToDoIntegTest.java
new file mode 100644
index 0000000..ab15a30
--- /dev/null
+++ b/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/AbstractToDoIntegTest.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 integration.tests;
+
+import integration.ToDoAppSystemInitializer;
+
+import org.junit.BeforeClass;
+import org.apache.isis.core.integtestsupport.IntegrationTestAbstract;
+import org.apache.isis.core.integtestsupport.scenarios.ScenarioExecutionForIntegration;
+
+public abstract class AbstractToDoIntegTest extends IntegrationTestAbstract {
+
+ @BeforeClass
+ public static void initClass() {
+ org.apache.log4j.PropertyConfigurator.configure("logging.properties");
+ ToDoAppSystemInitializer.initIsft();
+
+ // instantiating will install onto ThreadLocal
+ new ScenarioExecutionForIntegration();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemContributionsIntegTest.java
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemContributionsIntegTest.java b/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemContributionsIntegTest.java
new file mode 100644
index 0000000..f377f52
--- /dev/null
+++ b/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemContributionsIntegTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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 integration.tests;
+
+import dom.todo.ToDoItem;
+import dom.todo.ToDoItemContributions;
+import dom.todo.ToDoItems;
+import fixture.todo.scenarios.ToDoItemsRecreateAndCompleteSeveral;
+
+import java.util.List;
+import javax.inject.Inject;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.isis.applib.fixturescripts.FixtureScripts;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public abstract class ToDoItemContributionsIntegTest extends AbstractToDoIntegTest {
+
+ ToDoItemsRecreateAndCompleteSeveral fixtureScript;
+
+ @Before
+ public void setUpData() throws Exception {
+ fixtureScript = new ToDoItemsRecreateAndCompleteSeveral();
+ fixtureScripts.runFixtureScript(fixtureScript, null);
+ }
+
+ @Inject
+ FixtureScripts fixtureScripts;
+ @Inject
+ ToDoItems toDoItems;
+ @Inject
+ ToDoItemContributions toDoItemContributions;
+
+ ToDoItemContributions toDoItemContributionsWrapped;
+ ToDoItem toDoItem;
+
+ @Before
+ public void setUp() throws Exception {
+
+ toDoItem = wrap(fixtureScript.lookup("to-do-items-recreate-and-complete-several/to-do-item-complete-for-buy-stamps/item-1", ToDoItem.class));
+ assertThat(toDoItem, is(not(nullValue())));
+
+ toDoItemContributionsWrapped = wrap(toDoItemContributions);
+ }
+
+ public static class Actions {
+ public static class UpdateCategory extends ToDoItemContributionsIntegTest {
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // when
+ toDoItemContributionsWrapped.updateCategory(toDoItem, ToDoItem.Category.Professional, ToDoItem.Subcategory.Consulting);
+
+ // then
+ assertThat(toDoItem.getCategory(), is(ToDoItem.Category.Professional));
+ assertThat(toDoItem.getSubcategory(), is(ToDoItem.Subcategory.Consulting));
+
+ // when
+ toDoItemContributionsWrapped.updateCategory(toDoItem, ToDoItem.Category.Domestic, ToDoItem.Subcategory.Chores);
+
+ // then
+ assertThat(toDoItem.getCategory(), is(ToDoItem.Category.Domestic));
+ assertThat(toDoItem.getSubcategory(), is(ToDoItem.Subcategory.Chores));
+ }
+
+
+ @Test
+ public void categoryCannotBeNull() throws Exception {
+
+ // when, then
+ expectedExceptions.expectMessage("'Category' is mandatory");
+ toDoItemContributionsWrapped.updateCategory(toDoItem, null, ToDoItem.Subcategory.Chores);
+ }
+
+ @Test
+ public void subcategoryCanBeNull() throws Exception {
+
+ // when, then
+ toDoItemContributionsWrapped.updateCategory(toDoItem, ToDoItem.Category.Professional, null);
+ }
+
+ @Test
+ public void subcategoryMustBelongToCategory() throws Exception {
+
+ // when, then
+ expectedExceptions.expectMessage(containsString("Invalid subcategory"));
+ toDoItemContributionsWrapped.updateCategory(toDoItem, ToDoItem.Category.Professional, ToDoItem.Subcategory.Chores);
+ }
+ }
+
+ public static class SimilarTo extends ToDoItemContributionsIntegTest {
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // when
+ List<ToDoItem> similarItems = toDoItemContributionsWrapped.similarTo(toDoItem);
+
+ // then
+ assertThat(similarItems.size(), is(6));
+ }
+
+ }
+ }
+
+ public static class Properties {
+ public static class Priority extends ToDoItemContributionsIntegTest {
+
+ private List<ToDoItem> notYetComplete;
+
+ @Before
+ public void setUp() throws Exception {
+ notYetComplete = wrap(toDoItems).notYetComplete();
+ }
+
+ @Test
+ public void happyCase() throws Exception {
+ assertPriority(0, 1);
+ assertPriority(1, 2);
+ assertPriority(2, 4);
+ assertPriority(3, 6);
+ assertPriority(4, 5);
+ assertPriority(5, 7);
+ assertPriority(6, 9);
+ assertPriority(7, 8);
+ assertPriority(8, 3);
+ assertPriority(9, 10);
+ }
+
+ private void assertPriority(final int n, final int priority) {
+ assertThat(toDoItemContributions.relativePriority(notYetComplete.get(n)), is(Integer.valueOf(priority)));
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java b/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java
new file mode 100644
index 0000000..5bb2f0f
--- /dev/null
+++ b/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java
@@ -0,0 +1,1057 @@
+/*
+ * 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 integration.tests;
+
+import dom.todo.ToDoItem;
+import dom.todo.ToDoItemSubscriptions;
+import dom.todo.ToDoItems;
+import fixture.todo.scenarios.ToDoItemsRecreateAndCompleteSeveral;
+
+import java.math.BigDecimal;
+import java.nio.charset.Charset;
+import java.util.EventObject;
+import java.util.List;
+import javax.activation.MimeType;
+import javax.inject.Inject;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.jmock.Expectations;
+import org.jmock.Sequence;
+import org.jmock.auto.Mock;
+import org.joda.time.LocalDate;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.isis.applib.NonRecoverableException;
+import org.apache.isis.applib.RecoverableException;
+import org.apache.isis.applib.clock.Clock;
+import org.apache.isis.applib.fixturescripts.FixtureScripts;
+import org.apache.isis.applib.services.clock.ClockService;
+import org.apache.isis.applib.services.eventbus.AbstractInteractionEvent;
+import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
+import org.apache.isis.applib.services.eventbus.CollectionDomainEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyDomainEvent;
+import org.apache.isis.applib.value.Blob;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class ToDoItemIntegTest extends AbstractToDoIntegTest {
+
+ ToDoItemsRecreateAndCompleteSeveral fixtureScript;
+
+ @Before
+ public void setUpData() throws Exception {
+ fixtureScript = new ToDoItemsRecreateAndCompleteSeveral();
+ fixtureScripts.runFixtureScript(fixtureScript, null);
+ }
+
+ @Inject
+ FixtureScripts fixtureScripts;
+ @Inject
+ ToDoItems toDoItems;
+ @Inject
+ ToDoItemSubscriptions toDoItemSubscriptions;
+
+ ToDoItem toDoItem;
+
+ @Before
+ public void setUp() throws Exception {
+ final List<ToDoItem> all = toDoItems.notYetComplete();
+ toDoItem = wrap(all.get(0));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ toDoItemSubscriptions.reset();
+ }
+
+
+ public static class Title extends ToDoItemIntegTest {
+
+ private LocalDate dueBy;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ final List<ToDoItem> all = wrap(toDoItems).notYetComplete();
+ toDoItem = wrap(all.get(0));
+
+ toDoItem = wrap(fixtureScript.lookup("to-do-items-recreate-and-complete-several/to-do-item-for-buy-bread/item-1", ToDoItem.class));
+ assertThat(toDoItem, is(not(nullValue())));
+
+ nextTransaction();
+
+ dueBy = toDoItem.getDueBy();
+ }
+
+
+ @Test
+ public void includesDescription() throws Exception {
+
+ // given
+ assertThat(container().titleOf(toDoItem), containsString("Buy bread due by"));
+
+ // when
+ unwrap(toDoItem).setDescription("Buy bread and butter");
+
+ // then
+ assertThat(container().titleOf(toDoItem), containsString("Buy bread and butter due by"));
+ }
+
+ @Test
+ public void includesDueDateIfAny() throws Exception {
+
+ // given
+ assertThat(container().titleOf(toDoItem), containsString("due by " + dueBy.toString("yyyy-MM-dd")));
+
+ // when
+ final LocalDate fiveDaysFromNow = Clock.getTimeAsLocalDate().plusDays(5);
+ unwrap(toDoItem).setDueBy(fiveDaysFromNow);
+
+ // then
+ assertThat(container().titleOf(toDoItem), containsString("due by " + fiveDaysFromNow.toString("yyyy-MM-dd")));
+ }
+
+
+ @Test
+ public void ignoresDueDateIfNone() throws Exception {
+
+ // when
+ // (since wrapped, will call clearDueBy)
+ toDoItem.setDueBy(null);
+
+ // then
+ assertThat(container().titleOf(toDoItem), not(containsString("due by")));
+ }
+
+ @Test
+ public void usesWhetherCompleted() throws Exception {
+
+ // given
+ assertThat(container().titleOf(toDoItem), not(containsString("Completed!")));
+
+ // when
+ toDoItem.completed();
+
+ // then
+ assertThat(container().titleOf(toDoItem), not(containsString("due by")));
+ assertThat(container().titleOf(toDoItem), containsString("Buy bread - Completed!"));
+ }
+ }
+
+ public static class Actions {
+
+ public static class Completed extends ToDoItemIntegTest {
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // given
+ assertThat(toDoItem.isComplete(), is(false));
+
+ // when
+ toDoItem.completed();
+
+ // then
+ assertThat(toDoItem.isComplete(), is(true));
+ }
+
+ @Test
+ public void cannotCompleteIfAlreadyCompleted() throws Exception {
+
+ // given
+ unwrap(toDoItem).setComplete(true);
+
+ // when, then should fail
+ expectedExceptions.expectMessage("Already completed");
+ toDoItem.completed();
+
+ // and then
+ final EventObject ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(EventObject.class);
+ assertThat(ev, is(nullValue()));
+ }
+
+
+ @Test
+ public void cannotSetPropertyDirectly() throws Exception {
+
+ // given
+
+ // when, then should fail
+ expectedExceptions.expectMessage("Always disabled");
+ toDoItem.setComplete(true);
+
+ // and then
+ final EventObject ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(EventObject.class);
+ assertThat(ev, is(nullValue()));
+ }
+
+ @Test
+ public void subscriberReceivesEvents() throws Exception {
+
+ // given
+ toDoItemSubscriptions.reset();
+ assertThat(toDoItemSubscriptions.getSubscriberBehaviour(), is(ToDoItemSubscriptions.Behaviour.AnyExecuteAccept));
+ assertThat(unwrap(toDoItem).isComplete(), is(false));
+
+ // when
+ toDoItem.completed();
+
+ // then
+ assertThat(unwrap(toDoItem).isComplete(), is(true));
+
+ // and then
+ final List<ToDoItem.CompletedEvent> receivedEvents = toDoItemSubscriptions.receivedEvents(ToDoItem.CompletedEvent.class);
+
+ // hide, disable, validate, executing, executed
+ // sent to both the general on(ActionInteractionEvent ev)
+ // and also the specific on(final ToDoItem.CompletedEvent ev)
+ assertThat(receivedEvents.size(), is(5*2));
+ final ToDoItem.CompletedEvent ev = receivedEvents.get(0);
+
+ ToDoItem source = ev.getSource();
+ assertThat(source, is(equalTo(unwrap(toDoItem))));
+ assertThat(ev.getIdentifier().getMemberName(), is("completed"));
+ }
+
+ @Test
+ public void subscriberVetoesEventWithRecoverableException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
+
+ // then
+ expectedExceptions.expect(RecoverableException.class);
+
+ // when
+ toDoItem.completed();
+ }
+
+ @Test
+ public void subscriberVetoesEventWithNonRecoverableException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
+
+ // then
+ expectedExceptions.expect(NonRecoverableException.class);
+
+ // when
+ toDoItem.completed();
+ }
+
+ @Test
+ public void subscriberVetoesEventWithAnyOtherException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
+
+ // then
+ expectedExceptions.expect(RuntimeException.class);
+
+ // when
+ toDoItem.completed();
+ }
+
+ }
+
+ /**
+ * This test demonstrates how a single service can be replaced, eg to use a mock.
+ */
+ public static class Completed_withMockService extends ToDoItemIntegTest {
+
+ private EventBusService originalEventBusService;
+ @Mock
+ private EventBusService mockEventBusService;
+
+ @Before
+ public void setUpMockEventBusService() throws Exception {
+ originalEventBusService = scenarioExecution().service(EventBusService.class);
+
+ context.checking(new Expectations() {{
+ ignoring(mockEventBusService).register(with(any(Object.class)));
+ ignoring(mockEventBusService).unregister(with(any(Object.class)));
+ }});
+
+ scenarioExecution().replaceService(originalEventBusService, mockEventBusService);
+ scenarioExecution().closeSession();
+ scenarioExecution().openSession();
+
+ final List<ToDoItem> all = toDoItems.notYetComplete();
+ toDoItem = wrap(all.get(0));
+ }
+
+
+ @After
+ public void reinstateOriginalEventBusService() throws Exception {
+ scenarioExecution().replaceService(mockEventBusService, originalEventBusService);
+ }
+
+ @Test
+ public void raisesEvent() throws Exception {
+
+ final Sequence busRulesThenExec = context.sequence("busRulesThenExec");
+ // then
+ context.checking(new Expectations() {{
+ oneOf(mockEventBusService).post(with(completedEvent(AbstractInteractionEvent.Phase.HIDE)));
+ inSequence(busRulesThenExec);
+ oneOf(mockEventBusService).post(with(completedEvent(AbstractInteractionEvent.Phase.DISABLE)));
+ inSequence(busRulesThenExec);
+ oneOf(mockEventBusService).post(with(completedEvent(AbstractInteractionEvent.Phase.VALIDATE)));
+ inSequence(busRulesThenExec);
+ oneOf(mockEventBusService).post(with(completedEvent(AbstractInteractionEvent.Phase.EXECUTING)));
+ inSequence(busRulesThenExec);
+ oneOf(mockEventBusService).post(with(completedEvent(AbstractInteractionEvent.Phase.EXECUTED)));
+ inSequence(busRulesThenExec);
+ }});
+
+ // when
+ toDoItem.completed();
+ }
+
+ private Matcher<Object> completedEvent(final AbstractInteractionEvent.Phase phase) {
+ return new TypeSafeMatcher<Object>() {
+ @Override
+ protected boolean matchesSafely(Object item) {
+ if (!(item instanceof ToDoItem.CompletedEvent)) {
+ return false;
+ }
+
+ final ToDoItem.CompletedEvent completedEvent = (ToDoItem.CompletedEvent) item;
+ return completedEvent.getPhase() == phase;
+
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(" instance of a ToDoItem.CompletedEvent, " + phase);
+ }
+ };
+ }
+ }
+
+
+ public static class Duplicate extends ToDoItemIntegTest {
+
+ ToDoItem duplicateToDoItem;
+
+ @Inject
+ private ClockService clockService;
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // given
+ final LocalDate todaysDate = clockService.now();
+ toDoItem.setDueBy(todaysDate);
+ toDoItem.updateCost(new BigDecimal("123.45"));
+
+ duplicateToDoItem = toDoItem.duplicate(
+ unwrap(toDoItem).default0Duplicate(),
+ unwrap(toDoItem).default1Duplicate(),
+ unwrap(toDoItem).default2Duplicate(),
+ unwrap(toDoItem).default3Duplicate(),
+ new BigDecimal("987.65"));
+
+ // then
+ assertThat(duplicateToDoItem.getDescription(), is(toDoItem.getDescription() + " - Copy"));
+ assertThat(duplicateToDoItem.getCategory(), is(toDoItem.getCategory()));
+ assertThat(duplicateToDoItem.getDueBy(), is(todaysDate));
+ assertThat(duplicateToDoItem.getCost(), is(new BigDecimal("987.65")));
+ }
+ }
+
+ public static class NotYetCompleted extends ToDoItemIntegTest {
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // given
+ unwrap(toDoItem).setComplete(true);
+
+ // when
+ toDoItem.notYetCompleted();
+
+ // then
+ assertThat(toDoItem.isComplete(), is(false));
+ }
+
+ @Test
+ public void cannotUndoIfNotYetCompleted() throws Exception {
+
+ // given
+ assertThat(toDoItem.isComplete(), is(false));
+
+ // when, then should fail
+ expectedExceptions.expectMessage("Not yet completed");
+ toDoItem.notYetCompleted();
+ }
+
+ /**
+ * Even though {@link dom.todo.ToDoItem#notYetCompleted()} is not annotated with
+ * {@link org.apache.isis.applib.annotation.ActionInteraction}, an event is still raised.
+ */
+ @Test
+ public void subscriberReceivesEvent() throws Exception {
+
+ // given
+ assertThat(toDoItemSubscriptions.getSubscriberBehaviour(), is(ToDoItemSubscriptions.Behaviour.AnyExecuteAccept));
+ unwrap(toDoItem).setComplete(true);
+
+ // when
+ toDoItem.notYetCompleted();
+
+ // then
+ assertThat(unwrap(toDoItem).isComplete(), is(false));
+
+ // and then
+ final ActionDomainEvent<ToDoItem> ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(ActionDomainEvent.class);
+ assertThat(ev, is(not(nullValue())));
+
+ ToDoItem source = ev.getSource();
+ assertThat(source, is(equalTo(unwrap(toDoItem))));
+ assertThat(ev.getIdentifier().getMemberName(), is("notYetCompleted"));
+ }
+ }
+ }
+
+ public static class Collections {
+
+ public static class Dependencies {
+ public static class Add extends ToDoItemIntegTest {
+
+ private ToDoItem otherToDoItem;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ final List<ToDoItem> items = wrap(toDoItems).notYetComplete();
+ otherToDoItem = wrap(items.get(1));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ unwrap(toDoItem).getDependencies().clear();
+ super.tearDown();
+ }
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // given
+ assertThat(toDoItem.getDependencies().size(), is(0));
+
+ // when
+ toDoItem.add(otherToDoItem);
+
+ // then
+ assertThat(toDoItem.getDependencies().size(), is(1));
+ assertThat(toDoItem.getDependencies().iterator().next(), is(unwrap(otherToDoItem)));
+ }
+
+
+ @Test
+ public void cannotDependOnSelf() throws Exception {
+
+ // then
+ expectedExceptions.expectMessage("Can't set up a dependency to self");
+
+ // when
+ toDoItem.add(toDoItem);
+ }
+
+ @Test
+ public void cannotAddIfComplete() throws Exception {
+
+ // given
+ unwrap(toDoItem).setComplete(true);
+
+ // then
+ expectedExceptions.expectMessage("Cannot add dependencies for items that are complete");
+
+ // when
+ toDoItem.add(otherToDoItem);
+ }
+
+
+ @Test
+ public void subscriberReceivesEvent() throws Exception {
+
+ // given
+ toDoItemSubscriptions.reset();
+
+ // when
+ toDoItem.add(otherToDoItem);
+
+ // then received events
+ @SuppressWarnings("unchecked")
+ final List<EventObject> receivedEvents = toDoItemSubscriptions.receivedEvents();
+
+ assertThat(receivedEvents.size(), is(7));
+ assertThat(receivedEvents.get(0) instanceof ActionDomainEvent, is(true)); // ToDoItem#add() executed
+ assertThat(receivedEvents.get(1) instanceof CollectionDomainEvent, is(true)); // ToDoItem#dependencies add, executed
+ assertThat(receivedEvents.get(2) instanceof CollectionDomainEvent, is(true)); // ToDoItem#dependencies add, executing
+ assertThat(receivedEvents.get(3) instanceof ActionDomainEvent, is(true)); // ToDoItem#add executing
+ assertThat(receivedEvents.get(4) instanceof ActionDomainEvent, is(true)); // ToDoItem#add validate
+ assertThat(receivedEvents.get(5) instanceof ActionDomainEvent, is(true)); // ToDoItem#add disable
+ assertThat(receivedEvents.get(6) instanceof ActionDomainEvent, is(true)); // ToDoItem#add hide
+
+ // inspect the collection interaction (posted programmatically in ToDoItem#add)
+ final CollectionDomainEvent<ToDoItem,ToDoItem> ciEv = (CollectionDomainEvent<ToDoItem, ToDoItem>) toDoItemSubscriptions.mostRecentlyReceivedEvent(CollectionDomainEvent.class);
+ assertThat(ciEv, is(notNullValue()));
+
+ assertThat(ciEv.getSource(), is(equalTo(unwrap(toDoItem))));
+ assertThat(ciEv.getIdentifier().getMemberName(), is("dependencies"));
+ assertThat(ciEv.getOf(), is(CollectionDomainEvent.Of.ADD_TO));
+ assertThat(ciEv.getValue(), is(unwrap(otherToDoItem)));
+
+ // inspect the action interaction (posted declaratively by framework)
+ final ActionDomainEvent<ToDoItem> aiEv = (ActionDomainEvent<ToDoItem>) toDoItemSubscriptions.mostRecentlyReceivedEvent(ActionDomainEvent.class);
+ assertThat(aiEv, is(notNullValue()));
+
+ assertThat(aiEv.getSource(), is(equalTo(unwrap(toDoItem))));
+ assertThat(aiEv.getIdentifier().getMemberName(), is("add"));
+ assertThat(aiEv.getArguments().size(), is(1));
+ assertThat(aiEv.getArguments().get(0), is(unwrap((Object)otherToDoItem)));
+ assertThat(aiEv.getCommand(), is(notNullValue()));
+ }
+
+ @Test
+ public void subscriberVetoesEventWithRecoverableException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
+
+ // then
+ expectedExceptions.expect(RecoverableException.class);
+
+ // when
+ toDoItem.add(otherToDoItem);
+ }
+
+ @Test
+ public void subscriberVetoesEventWithNonRecoverableException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
+
+ // then
+ expectedExceptions.expect(NonRecoverableException.class);
+
+ // when
+ toDoItem.add(otherToDoItem);
+ }
+
+ @Test
+ public void subscriberVetoesEventWithAnyOtherException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
+
+ // then
+ expectedExceptions.expect(RuntimeException.class);
+
+ // when
+ toDoItem.add(otherToDoItem);
+ }
+ }
+ public static class Remove extends ToDoItemIntegTest {
+
+ private ToDoItem otherToDoItem;
+ private ToDoItem yetAnotherToDoItem;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ final List<ToDoItem> items = wrap(toDoItems).notYetComplete();
+ otherToDoItem = wrap(items.get(1));
+ yetAnotherToDoItem = wrap(items.get(2));
+
+ toDoItem.add(otherToDoItem);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ unwrap(toDoItem).getDependencies().clear();
+ super.tearDown();
+ }
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // given
+ assertThat(toDoItem.getDependencies().size(), is(1));
+
+ // when
+ toDoItem.remove(otherToDoItem);
+
+ // then
+ assertThat(toDoItem.getDependencies().size(), is(0));
+ }
+
+
+ @Test
+ public void cannotRemoveItemIfNotADependency() throws Exception {
+
+ // then
+ expectedExceptions.expectMessage("Not a dependency");
+
+ // when
+ toDoItem.remove(yetAnotherToDoItem);
+ }
+
+ @Test
+ public void cannotRemoveDependencyIfComplete() throws Exception {
+
+ // given
+ unwrap(toDoItem).setComplete(true);
+
+ // then
+ expectedExceptions.expectMessage("Cannot remove dependencies for items that are complete");
+
+ // when
+ toDoItem.remove(otherToDoItem);
+ }
+
+ @Test
+ public void subscriberVetoesEventWithRecoverableException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
+
+ // then
+ expectedExceptions.expect(RecoverableException.class);
+
+ // when
+ toDoItem.remove(otherToDoItem);
+ }
+
+ @Test
+ public void subscriberVetoesEventWithNonRecoverableException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
+
+ // then
+ expectedExceptions.expect(NonRecoverableException.class);
+
+ // when
+ toDoItem.remove(otherToDoItem);
+ }
+
+ @Test
+ public void subscriberVetoesEventWithAnyOtherException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
+
+ // then
+ expectedExceptions.expect(RuntimeException.class);
+
+ // when
+ toDoItem.remove(otherToDoItem);
+ }
+ }
+ }
+
+ }
+
+ public static class Properties {
+
+ public static class Attachment extends ToDoItemIntegTest {
+
+ @Test
+ public void happyCase() throws Exception {
+
+ byte[] bytes = "{\"foo\": \"bar\"}".getBytes(Charset.forName("UTF-8"));
+ final Blob newAttachment = new Blob("myfile.json", new MimeType("application/json"), bytes);
+
+ // when
+ toDoItem.setAttachment(newAttachment);
+
+ // then
+ assertThat(toDoItem.getAttachment(), is(newAttachment));
+ }
+
+ @Test
+ public void canBeNull() throws Exception {
+
+ // when
+ toDoItem.setAttachment((Blob)null);
+
+ // then
+ assertThat(toDoItem.getAttachment(), is((Blob)null));
+ }
+ }
+
+ public static class Category extends ToDoItemIntegTest {
+
+ @Test
+ public void cannotModify() throws Exception {
+
+ // when, then
+ expectedExceptions.expectMessage(containsString("Reason: Use action to update both category and subcategory."));
+ toDoItem.setCategory(ToDoItem.Category.Professional);
+ }
+ }
+
+ public static class Cost extends ToDoItemIntegTest {
+
+ private BigDecimal cost;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ cost = toDoItem.getCost();
+ }
+
+ @Test
+ public void happyCaseUsingProperty() throws Exception {
+
+ final BigDecimal newCost = new BigDecimal("123.45");
+
+ // when
+ toDoItem.updateCost(newCost);
+
+ // then
+ assertThat(toDoItem.getCost(), is(newCost));
+ }
+
+ @Test
+ public void happyCaseUsingAction() throws Exception {
+
+ final BigDecimal newCost = new BigDecimal("123.45");
+
+ // when
+ toDoItem.updateCost(newCost);
+
+ // then
+ assertThat(toDoItem.getCost(), is(newCost));
+ }
+
+ @Test
+ public void canBeNull() throws Exception {
+
+ // when
+ toDoItem.updateCost((BigDecimal)null);
+
+ // then
+ assertThat(toDoItem.getCost(), is((BigDecimal)null));
+ }
+
+ @Test
+ public void defaultForAction() throws Exception {
+
+ // then
+ assertThat(unwrap(toDoItem).default0UpdateCost(), is(cost));
+ }
+
+ }
+
+ public static class Description extends ToDoItemIntegTest {
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // given
+ assertThat(toDoItem.getDescription(), is("Buy bread"));
+
+ // when
+ toDoItem.setDescription("Buy bread and butter");
+
+ // then
+ assertThat(toDoItem.getDescription(), is("Buy bread and butter"));
+ }
+
+
+ @Test
+ public void failsRegex() throws Exception {
+
+ // when
+ expectedExceptions.expectMessage("Doesn't match pattern");
+ toDoItem.setDescription("exclamation marks are not allowed!!!");
+ }
+
+ @Test
+ public void cannotBeNull() throws Exception {
+
+ // when, then
+ expectedExceptions.expectMessage("Mandatory");
+ toDoItem.setDescription(null);
+ }
+
+ @Test
+ public void cannotUseModify() throws Exception {
+
+ expectedExceptions.expectMessage("Cannot invoke supporting method for 'Description'; use only property accessor/mutator");
+
+ // given
+ assertThat(toDoItem.getDescription(), is("Buy bread"));
+
+ // when
+ toDoItem.modifyDescription("Buy bread and butter");
+
+ // then
+ assertThat(toDoItem.getDescription(), is("Buy bread"));
+ }
+
+ @Test
+ public void cannotUseClear() throws Exception {
+
+ expectedExceptions.expectMessage("Cannot invoke supporting method for 'Description'; use only property accessor/mutator");
+
+ // given
+ assertThat(toDoItem.getDescription(), is("Buy bread"));
+
+ // when
+ toDoItem.clearDescription();
+
+ // then
+ assertThat(toDoItem.getDescription(), is("Buy bread"));
+ }
+
+
+ @Test
+ public void onlyJustShortEnough() throws Exception {
+
+ // when, then
+ toDoItem.setDescription(characters(100));
+ }
+
+ @Test
+ public void tooLong() throws Exception {
+
+ // then
+ expectedExceptions.expectMessage("The value proposed exceeds the maximum length of 100");
+
+ // when
+ toDoItem.setDescription(characters(101));
+ }
+
+
+ @Test
+ public void subscriberReceivesEvent() throws Exception {
+
+ // given
+ assertThat(toDoItemSubscriptions.getSubscriberBehaviour(), is(ToDoItemSubscriptions.Behaviour.AnyExecuteAccept));
+ assertThat(toDoItem.getDescription(), is("Buy bread"));
+
+ // when
+ toDoItem.setDescription("Buy bread and butter");
+
+ // then published and received
+ @SuppressWarnings("unchecked")
+ final PropertyDomainEvent<ToDoItem,String> ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(PropertyDomainEvent.class);
+ assertThat(ev, is(not(nullValue())));
+
+ ToDoItem source = ev.getSource();
+ assertThat(source, is(equalTo(unwrap(toDoItem))));
+ assertThat(ev.getIdentifier().getMemberName(), is("description"));
+ assertThat(ev.getOldValue(), is("Buy bread"));
+ assertThat(ev.getNewValue(), is("Buy bread and butter"));
+ }
+
+ @Test
+ public void subscriberVetoesEventWithRecoverableException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
+
+ // then
+ expectedExceptions.expect(RecoverableException.class);
+
+ // when
+ toDoItem.setDescription("Buy bread and butter");
+ }
+
+
+ @Test
+ public void subscriberVetoesEventWithNonRecoverableException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
+
+ // then
+ expectedExceptions.expect(NonRecoverableException.class);
+
+ // when
+ toDoItem.setDescription("Buy bread and butter");
+ }
+
+
+ @Test
+ public void subscriberVetoesEventWithAnyOtherException() throws Exception {
+
+ // given
+ toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
+
+ // then
+ expectedExceptions.expect(RuntimeException.class);
+
+ // when
+ toDoItem.setDescription("Buy bread and butter");
+ }
+
+
+ private static String characters(final int n) {
+ StringBuffer buf = new StringBuffer();
+ for(int i=0; i<n; i++) {
+ buf.append("a");
+ }
+ return buf.toString();
+ }
+ }
+
+ public static class DueBy extends ToDoItemIntegTest {
+
+ @Inject
+ private ClockService clockService;
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // when
+ final LocalDate fiveDaysFromNow = clockService.now().plusDays(5);
+ toDoItem.setDueBy(fiveDaysFromNow);
+
+ // then
+ assertThat(toDoItem.getDueBy(), is(fiveDaysFromNow));
+ }
+
+
+ @Test
+ public void canBeNull() throws Exception {
+
+ // when
+ toDoItem.setDueBy((LocalDate)null);
+
+ // then
+ assertThat(toDoItem.getDueBy(), is((LocalDate)null));
+ }
+
+ @Test
+ public void canBeUpToSixDaysInPast() throws Exception {
+
+ final LocalDate nowAsLocalDate = clockService.now();
+ final LocalDate sixDaysAgo = nowAsLocalDate.plusDays(-5);
+
+ // when
+ toDoItem.setDueBy(sixDaysAgo);
+
+ // then
+ assertThat(toDoItem.getDueBy(), is(sixDaysAgo));
+ }
+
+
+ @Test
+ public void cannotBeMoreThanSixDaysInPast() throws Exception {
+
+ final LocalDate sevenDaysAgo = Clock.getTimeAsLocalDate().plusDays(-7);
+
+ // when, then
+ expectedExceptions.expectMessage("Due by date cannot be more than one week old");
+ toDoItem.setDueBy(sevenDaysAgo);
+ }
+ }
+
+ public static class Notes extends ToDoItemIntegTest {
+
+ @Test
+ public void happyCase() throws Exception {
+
+ final String newNotes = "Lorem ipsum yada yada";
+
+ // when
+ toDoItem.setNotes(newNotes);
+
+ // then
+ assertThat(toDoItem.getNotes(), is(newNotes));
+ }
+
+ @Test
+ public void canBeNull() throws Exception {
+
+ // when
+ toDoItem.setNotes((String)null);
+
+ // then
+ assertThat(toDoItem.getNotes(), is((String)null));
+ }
+
+ @Test
+ public void suscriberReceivedDefaultEvent() throws Exception {
+
+ final String newNotes = "Lorem ipsum yada yada";
+
+ // when
+ toDoItem.setNotes(newNotes);
+
+ // then
+ assertThat(unwrap(toDoItem).getNotes(), is(newNotes));
+
+ // and then receive the default event.
+ @SuppressWarnings("unchecked")
+ final PropertyDomainEvent.Default ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(PropertyDomainEvent.Default.class);
+ assertThat(ev, is(notNullValue()));
+
+ assertThat(ev.getSource(), is((Object)unwrap(toDoItem)));
+ assertThat(ev.getNewValue(), is((Object)newNotes));
+ }
+
+
+ }
+
+ public static class OwnedBy extends ToDoItemIntegTest {
+
+ @Test
+ public void cannotModify() throws Exception {
+
+ // when, then
+ expectedExceptions.expectMessage("Reason: Hidden on Everywhere. Identifier: dom.todo.ToDoItem#ownedBy()");
+ toDoItem.setOwnedBy("other");
+ }
+
+
+ }
+
+ public static class Subcategory extends ToDoItemIntegTest {
+
+ @Test
+ public void cannotModify() throws Exception {
+
+ // when, then
+ expectedExceptions.expectMessage(containsString("Reason: Use action to update both category and subcategory."));
+ toDoItem.setSubcategory(ToDoItem.Subcategory.Chores);
+ }
+ }
+
+ }
+
+
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemsIntegTest.java
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemsIntegTest.java b/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemsIntegTest.java
new file mode 100644
index 0000000..2c06dc0
--- /dev/null
+++ b/mothballed/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemsIntegTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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 integration.tests;
+
+import dom.todo.ToDoItem;
+import dom.todo.ToDoItems;
+import fixture.todo.integtests.ToDoItemsIntegTestFixture;
+
+import java.util.List;
+import javax.inject.Inject;
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.isis.applib.fixturescripts.FixtureScripts;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ToDoItemsIntegTest extends AbstractToDoIntegTest {
+
+ @Inject
+ FixtureScripts fixtureScripts;
+ @Inject
+ ToDoItems toDoItems;
+
+ public static class Finders extends ToDoItemsIntegTest {
+
+ ToDoItemsIntegTestFixture fixture;
+
+ @Before
+ public void setUpData() throws Exception {
+ // executing the fixtures directly allows us to look up the results later.
+ fixtureScripts.runFixtureScript(fixture = new ToDoItemsIntegTestFixture(), null);
+ }
+
+ private int notYetCompletedSize;
+ private int completedSize;
+
+ @Before
+ public void setUp() throws Exception {
+
+ // could use fixture#lookup(...), but can also just search directly.
+ final List<ToDoItem> notYetCompleteItems = wrap(toDoItems).notYetComplete();
+ final List<ToDoItem> completedItems = wrap(toDoItems).complete();
+
+ notYetCompletedSize = notYetCompleteItems.size();
+ completedSize = completedItems.size();
+
+ assertThat(notYetCompletedSize, is(Matchers.greaterThan(5)));
+ }
+
+ @Test
+ public void complete_and_notYetComplete() throws Exception {
+
+ // given
+ List<ToDoItem> notYetCompleteItems = wrap(toDoItems).notYetComplete();
+ final ToDoItem toDoItem = wrap(notYetCompleteItems.get(0));
+ nextTransaction();
+
+ // when
+ toDoItem.completed();
+ nextTransaction();
+
+ // then
+ assertThat(wrap(toDoItems).notYetComplete().size(), is(notYetCompletedSize-1));
+ assertThat(wrap(toDoItems).complete().size(), is(completedSize+1));
+ nextTransaction();
+
+ // and when
+ toDoItem.notYetCompleted();
+ nextTransaction();
+
+ // then
+ assertThat(wrap(toDoItems).notYetComplete().size(), is(notYetCompletedSize));
+ assertThat(wrap(toDoItems).complete().size(), is(completedSize));
+ }
+ }
+
+ public static class NewToDo_and_Delete extends ToDoItemsIntegTest {
+
+ @Before
+ public void setUpData() throws Exception {
+ // none
+ }
+
+ @Test
+ public void happyCase() throws Exception {
+
+ // given
+ int size = wrap(toDoItems).notYetComplete().size();
+ nextTransaction();
+
+ // when
+ final ToDoItem newToDo = toDoItems.newToDo("new todo", ToDoItem.Category.Professional, ToDoItem.Subcategory.OpenSource, null, null);
+ nextTransaction();
+
+ // then
+ assertThat(newToDo.getDescription(), is("new todo"));
+ assertThat(newToDo.getCategory(), is(ToDoItem.Category.Professional));
+ assertThat(wrap(toDoItems).notYetComplete().size(), is(size+1));
+ assertThat(container().isPersistent(newToDo), is(true));
+ assertThat(container().isPersistent(wrap(newToDo)), is(true));
+
+ nextTransaction();
+
+ // when
+ newToDo.delete();
+ nextTransaction();
+
+ // then
+ assertThat(wrap(toDoItems).notYetComplete().size(), is(size));
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/pom.xml
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/pom.xml b/mothballed/example/application/todoapp/pom.xml
new file mode 100644
index 0000000..c47dc8e
--- /dev/null
+++ b/mothballed/example/application/todoapp/pom.xml
@@ -0,0 +1,378 @@
+<?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>
+
+ <groupId>org.apache.isis.example.application</groupId>
+ <artifactId>todoapp</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+
+ <name>ToDo App</name>
+
+ <packaging>pom</packaging>
+
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <properties>
+ <isis.version>1.8.0-SNAPSHOT</isis.version>
+ <isis-viewer-wicket.version>1.8.0-SNAPSHOT</isis-viewer-wicket.version>
+
+ <!-- must be consistent with the versions defined by the JDO Objectstore -->
+ <datanucleus-accessplatform-jdo-rdbms.version>3.3.6</datanucleus-accessplatform-jdo-rdbms.version>
+ <datanucleus-maven-plugin.version>3.3.2</datanucleus-maven-plugin.version>
+
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>apache.snapshots</id>
+ <name>Apache Snapshots</name>
+ <url>https://repository.apache.org/content/repositories/snapshots/</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>Cloudbees snapshots</id>
+ <url>http://repository-estatio.forge.cloudbees.com/snapshot/</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ </repository>
+ </repositories>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ <executions>
+ <execution>
+ <id>source</id>
+ <phase>compile</phase>
+ </execution>
+ <execution>
+ <id>test</id>
+ <phase>test-compile</phase>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.16</version>
+ <configuration>
+ <includes>
+ <include>**/*Test.java</include>
+ <include>**/*Test$*.java</include>
+ <include>**/*Test_*.java</include>
+ <include>**/*Spec*.java</include>
+ </includes>
+ <excludes>
+ <exclude>**/Test*.java</exclude>
+ <exclude>**/*ForTesting.java</exclude>
+ <exclude>**/*Abstract*.java</exclude>
+ </excludes>
+ <useFile>true</useFile>
+ <printSummary>true</printSummary>
+ <outputDirectory>${project.build.directory}/surefire-reports</outputDirectory>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>2.16</version>
+ <configuration>
+ <includes>
+ <include>**/*Test.java</include>
+ <include>**/*Test$*.java</include>
+ <include>**/*Test_*.java</include>
+ <include>**/*Spec*.java</include>
+ </includes>
+ <excludes>
+ <exclude>**/Test*.java</exclude>
+ <exclude>**/*ForTesting.java</exclude>
+ <exclude>**/*Abstract*.java</exclude>
+ </excludes>
+ <showSuccess>false</showSuccess>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>test</phase>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.5.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.8.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <version>6.1.26</version>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.7</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- http://simplericity.com/2009/11/10/1257880778509.html -->
+ <plugin>
+ <groupId>org.simplericity.jettyconsole</groupId>
+ <artifactId>jetty-console-maven-plugin</artifactId>
+ <!-- update to 1.54 reversed,since seems compiled against 1.7 (major.minor version 51.0) -->
+ <version>1.43</version>
+ </plugin>
+
+ <!-- Apache Release Audit Tool -->
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <version>0.10</version>
+ <configuration>
+ <addDefaultLicenseMatchers>true</addDefaultLicenseMatchers>
+ <excludeSubProjects>true</excludeSubProjects>
+ <excludes>
+ <exclude>**/target/**</exclude>
+ <exclude>**/target-ide/**</exclude>
+
+ <exclude>**/*.project</exclude>
+ <exclude>**/.classpath</exclude>
+ <exclude>**/.settings/**</exclude>
+ <exclude>**/*.launch</exclude>
+ <exclude>**/ide/eclipse/launch/**</exclude>
+ <exclude>**/ide/intellij/launch/**</exclude>
+ <exclude>src/site/resources/ide/eclipse/**</exclude>
+
+ <exclude>**/rebel.xml</exclude>
+ <exclude>**/*.gitignore</exclude>
+ <exclude>**/*.log</exclude>
+ <exclude>**/*.pdn</exclude>
+ <exclude>**/*.svg</exclude>
+ <exclude>**/*.json</exclude>
+ <exclude>**/*.min.js</exclude>
+ <exclude>**/*.js</exclude>
+ </excludes>
+ <licenses>
+ <license implementation="org.apache.rat.analysis.license.SimplePatternBasedLicense">
+ <licenseFamilyCategory>AL2</licenseFamilyCategory>
+ <licenseFamilyName>Apache License 2.0</licenseFamilyName>
+ <notes/>
+ <patterns>
+ <pattern>Licensed to the Apache Software Foundation (ASF) under one</pattern>
+ </patterns>
+ </license>
+ <license implementation="org.apache.rat.analysis.license.SimplePatternBasedLicense">
+ <licenseFamilyCategory>JQRY</licenseFamilyCategory>
+ <licenseFamilyName>MIT</licenseFamilyName>
+ <notes/>
+ <patterns>
+ <pattern>Dual licensed under the MIT or GPL Version 2 licenses.</pattern>
+ </patterns>
+ </license>
+ <license implementation="org.apache.rat.analysis.license.SimplePatternBasedLicense">
+ <licenseFamilyCategory>JMOCK</licenseFamilyCategory>
+ <licenseFamilyName>JMock</licenseFamilyName>
+ <notes/>
+ <patterns>
+ <pattern>Copyright (c) 2000-2007, jMock.org</pattern>
+ </patterns>
+ </license>
+ <license implementation="org.apache.rat.analysis.license.SimplePatternBasedLicense">
+ <licenseFamilyCategory>DOCBK</licenseFamilyCategory>
+ <licenseFamilyName>DocBook 4.5</licenseFamilyName>
+ <notes/>
+ <patterns>
+ <pattern>Permission to copy in any form is granted for use</pattern>
+ <pattern>Permission to use, copy, modify and distribute the DocBook DTD</pattern>
+ <pattern>is hereby granted in perpetuity, provided that the above copyright
+ </pattern>
+ <pattern>This is the catalog data file for DocBook XML V4.5. It is provided as
+ </pattern>
+ <pattern>XML Catalog data for DocBook XML V4.5</pattern>
+ <pattern>DocBook additional general entities V4.5</pattern>
+ <pattern>XML EXCHANGE TABLE MODEL DECLARATION MODULE</pattern>
+ </patterns>
+ </license>
+ <license implementation="org.apache.rat.analysis.license.SimplePatternBasedLicense">
+ <licenseFamilyCategory>W3C</licenseFamilyCategory>
+ <licenseFamilyName>XHTML</licenseFamilyName>
+ <notes/>
+ <patterns>
+ <pattern>Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),</pattern>
+ </patterns>
+ </license>
+ </licenses>
+ <licenseFamilies>
+ <licenseFamily implementation="org.apache.rat.license.SimpleLicenseFamily">
+ <familyName>Apache License 2.0</familyName>
+ </licenseFamily>
+ <licenseFamily implementation="org.apache.rat.license.SimpleLicenseFamily">
+ <familyName>MIT</familyName>
+ </licenseFamily>
+ <licenseFamily implementation="org.apache.rat.license.SimpleLicenseFamily">
+ <familyName>JMock</familyName>
+ </licenseFamily>
+ <licenseFamily implementation="org.apache.rat.license.SimpleLicenseFamily">
+ <familyName>DocBook 4.5</familyName>
+ </licenseFamily>
+ <licenseFamily implementation="org.apache.rat.license.SimpleLicenseFamily">
+ <familyName>XHTML</familyName>
+ </licenseFamily>
+ </licenseFamilies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <modules>
+ <module>dom</module>
+ <module>fixture</module>
+ <module>integtests</module>
+ <module>webapp</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis</artifactId>
+ <version>${isis.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.viewer</groupId>
+ <artifactId>isis-viewer-wicket</artifactId>
+ <version>${isis-viewer-wicket.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+
+ <!-- this project's own modules -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>todoapp-dom</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>todoapp-fixture</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>todoapp-webapp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ </dependencies>
+ </dependencyManagement>
+
+
+ <profiles>
+ <profile>
+ <id>m2e</id>
+ <activation>
+ <property>
+ <name>m2e.version</name>
+ </property>
+ </activation>
+ <build>
+ <directory>target-ide</directory>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/webapp/ide/eclipse/launch/ToDoApp-PROTOTYPE-jrebel.launch
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/webapp/ide/eclipse/launch/ToDoApp-PROTOTYPE-jrebel.launch b/mothballed/example/application/todoapp/webapp/ide/eclipse/launch/ToDoApp-PROTOTYPE-jrebel.launch
new file mode 100644
index 0000000..14ac1bf
--- /dev/null
+++ b/mothballed/example/application/todoapp/webapp/ide/eclipse/launch/ToDoApp-PROTOTYPE-jrebel.launch
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/isis-core-webserver/src/main/java/org/apache/isis/WebServer.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<mapAttribute key="org.eclipse.debug.core.preferred_launchers">
+<mapEntry key="[debug]" value="org.eclipse.jdt.launching.localJavaApplication"/>
+<mapEntry key="[run]" value="org.eclipse.jdt.launching.localJavaApplication"/>
+</mapAttribute>
+<stringAttribute key="org.eclipse.debug.core.source_locator_id" value="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"/>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.apache.isis.WebServer"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="--port 8080 --type SERVER_PROTOTYPE"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="todoapp-webapp"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="${jrebel_args} -Drebel.log=false -Drebel.check_class_hash=true -Drebel.packages_exclude=org.apache.isis -Dproject.root=${project_loc}/.. -Dtarget.dir=target-ide -Drebel.plugins=C:/github/danhaywood/isis-jrebel-plugin/target/danhaywood-isis-jrebel-plugin-1.0.0-SNAPSHOT.jar -Disis-jrebel-plugin.packagePrefix=dom.todo,org.apache.isis.objectstore.jdo.applib -Disis-jrebel-plugin.loggingLevel=warn -XX:MaxPermSize=128m"/>
+</launchConfiguration>
http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/mothballed/example/application/todoapp/webapp/ide/eclipse/launch/ToDoApp-PROTOTYPE-with-fixtures.launch
----------------------------------------------------------------------
diff --git a/mothballed/example/application/todoapp/webapp/ide/eclipse/launch/ToDoApp-PROTOTYPE-with-fixtures.launch b/mothballed/example/application/todoapp/webapp/ide/eclipse/launch/ToDoApp-PROTOTYPE-with-fixtures.launch
new file mode 100644
index 0000000..2e272aa
--- /dev/null
+++ b/mothballed/example/application/todoapp/webapp/ide/eclipse/launch/ToDoApp-PROTOTYPE-with-fixtures.launch
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/isis-core-webserver/src/main/java/org/apache/isis/WebServer.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<mapAttribute key="org.eclipse.debug.core.preferred_launchers">
+<mapEntry key="[debug]" value="org.eclipse.jdt.launching.localJavaApplication"/>
+<mapEntry key="[run]" value="org.eclipse.jdt.launching.localJavaApplication"/>
+</mapAttribute>
+<stringAttribute key="org.eclipse.debug.core.source_locator_id" value="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"/>
+<booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.apache.isis.WebServer"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="--port 8080 -D isis.persistor.datanucleus.install-fixtures=true --type SERVER_PROTOTYPE"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="todoapp-webapp"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
+</launchConfiguration>