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 2014/07/04 16:53:42 UTC

[14/16] git commit: ISIS-833: completing the reorg of services into modules.

ISIS-833: completing the reorg of services into modules.

devutils and settings.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/8b6cab67
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/8b6cab67
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/8b6cab67

Branch: refs/heads/master
Commit: 8b6cab67d440cbff244367abc8b4f5fabff26627
Parents: e3c2059
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Jul 4 15:52:28 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Jul 4 15:52:28 2014 +0100

----------------------------------------------------------------------
 .../BookmarkHolderActionContributions.java      |   2 +-
 .../BookmarkHolderAssociationContributions.java |  65 ++++++
 .../devutils/DeveloperUtilitiesService.java     |  75 ------
 .../services/jdosupport/IsisJdoSupport.java     |  81 +++++++
 .../services/settings/ApplicationSetting.java   |  25 --
 .../settings/ApplicationSettingsService.java    |  34 ---
 .../settings/ApplicationSettingsServiceRW.java  |  38 ---
 .../isis/applib/services/settings/Setting.java  |  53 -----
 .../services/settings/SettingAbstract.java      | 192 ---------------
 .../applib/services/settings/SettingType.java   |  28 ---
 .../applib/services/settings/UserSetting.java   |  34 ---
 .../services/settings/UserSettingsService.java  |  36 ---
 .../settings/UserSettingsServiceRW.java         |  38 ---
 .../BookmarkHolderAssociationContributions.java |  67 ------
 .../applib/service/support/IsisJdoSupport.java  |  61 +----
 .../services/settings/SettingAbstractTest.java  | 106 ---------
 .../DeveloperUtilitiesServiceDefault.java       | 231 ------------------
 .../services/devutils/MetaModelRow.java         | 234 -------------------
 .../specloader/ServiceInitializer.java          |   7 +-
 .../devutils/DeveloperUtilitiesService.java     |  75 ++++++
 core/module-devutils/impl/pom.xml               |   8 +-
 .../DeveloperUtilitiesServiceDefault.java       | 223 ++++++++++++++++++
 .../services/devutils/MetaModelRow.java         | 234 +++++++++++++++++++
 .../RestfulObjectsSpecEventSerializer.java      |   2 +
 core/module-settings/applib/pom.xml             |   2 +-
 .../services/settings/ApplicationSetting.java   |  25 ++
 .../settings/ApplicationSettingsService.java    |  34 +++
 .../settings/ApplicationSettingsServiceRW.java  |  38 +++
 .../isis/applib/services/settings/Setting.java  |  53 +++++
 .../services/settings/SettingAbstract.java      | 192 +++++++++++++++
 .../applib/services/settings/SettingType.java   |  28 +++
 .../applib/services/settings/UserSetting.java   |  34 +++
 .../services/settings/UserSettingsService.java  |  36 +++
 .../settings/UserSettingsServiceRW.java         |  38 +++
 .../services/settings/SettingAbstractTest.java  | 103 ++++++++
 core/module-settings/impl-jdo/pom.xml           |   6 +-
 core/module-settings/pom.xml                    |   2 +-
 core/pom-jdo-enhance-all.xml                    | 130 +++++++++++
 .../ServicesInstallerFromAnnotation.java        |  22 +-
 .../scenarios/ScenarioExecutionForUnit.java     |   7 +-
 .../java/dom/todo/ToDoItemSubscriptions.java    |   1 +
 .../webapp/pom.xml                              |   8 +-
 .../src/main/webapp/WEB-INF/isis.properties     |   8 +-
 .../simple_wicket_restful_jdo/webapp/pom.xml    |  16 +-
 .../src/main/webapp/WEB-INF/isis.properties     |   8 +-
 45 files changed, 1443 insertions(+), 1297 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderActionContributions.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderActionContributions.java b/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderActionContributions.java
index f9a07fb..461c5fc 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderActionContributions.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderActionContributions.java
@@ -29,7 +29,7 @@ import org.apache.isis.applib.annotation.Programmatic;
  * any class that implements {@link org.apache.isis.applib.services.bookmark.BookmarkHolder}.
  *
  * <p>
- * Alternatively, can use {@link org.apache.isis.core.metamodel.services.bookmarks.BookmarkHolderAssociationContributions}
+ * Alternatively, can use {@link BookmarkHolderAssociationContributions}
  * to contribute an property.
  *
  * <p>

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderAssociationContributions.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderAssociationContributions.java b/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderAssociationContributions.java
new file mode 100644
index 0000000..dc0332e
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolderAssociationContributions.java
@@ -0,0 +1,65 @@
+/*
+ *  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.applib.services.bookmark;
+
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.applib.annotation.NotInServiceMenu;
+import org.apache.isis.applib.annotation.Programmatic;
+
+/**
+ * Domain service that contributes a property (named '<tt>Object</tt>') to
+ * any class that implements {@link org.apache.isis.applib.services.bookmark.BookmarkHolder}.
+ *
+ * <p>
+ * Alternatively, can use {@link org.apache.isis.applib.services.bookmark.BookmarkHolderActionContributions}
+ * to contribute an action.
+ *
+ * <p>
+ * The service must be explicitly registered, typically in <tt>isis.properties</tt>.
+ */
+public class BookmarkHolderAssociationContributions {
+
+
+    //region > init
+    @Programmatic
+    @PostConstruct
+    public void init(Map<String,String> props) {
+        ensureDependenciesInjected();
+    }
+
+    private void ensureDependenciesInjected() {
+        if(this.bookmarkService == null){
+            throw new IllegalStateException("BookmarkService domain service must be configured");
+        }
+    }
+    //endregion
+
+    @NotInServiceMenu
+    @NotContributed(NotContributed.As.ACTION)
+    public Object object(final BookmarkHolder bookmarkHolder) {
+        return bookmarkService.lookup(bookmarkHolder);
+    }
+
+
+    @javax.inject.Inject
+    private BookmarkService bookmarkService;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java b/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java
deleted file mode 100644
index 6a25cfc..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.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.applib.services.devutils;
-
-import org.apache.isis.applib.annotation.ActionSemantics;
-import org.apache.isis.applib.annotation.ActionSemantics.Of;
-import org.apache.isis.applib.annotation.Hidden;
-import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.Named;
-import org.apache.isis.applib.annotation.NotInServiceMenu;
-import org.apache.isis.applib.annotation.Prototype;
-import org.apache.isis.applib.value.Blob;
-import org.apache.isis.applib.value.Clob;
-
-@Named("Developer Utilities")
-public interface DeveloperUtilitiesService {
-
-    @MemberOrder(sequence="1")
-    @ActionSemantics(Of.SAFE)
-    @Prototype
-    public Clob downloadMetaModel();
-
-
-    /**
-     * Downloads a zip of the layout of all domain classes.
-     */
-    @ActionSemantics(Of.SAFE)
-    @MemberOrder(sequence="3")
-    @Prototype
-    public Blob downloadLayouts();
-
-    /**
-     * Rebuilds the metamodel of all registered domain services.
-     */
-    @ActionSemantics(Of.SAFE)
-    @MemberOrder(sequence="3")
-    @Prototype
-    public void refreshServices();
-
-    /**
-     * Download the JSON layout of the domain object's type.
-     */
-    @NotInServiceMenu
-    @ActionSemantics(Of.SAFE)
-    @MemberOrder(sequence="2")
-    @Prototype
-    public Clob downloadLayout(Object domainObject);
-
-    /**
-     * @deprecated - in prototype mode the Wicket viewer (at least) will automatically invalidate 
-     *               the Isis metamodel whenever the object is re-rendered.
-     */
-    @Deprecated
-    @Hidden
-    @NotInServiceMenu
-    @ActionSemantics(Of.SAFE)
-    @MemberOrder(sequence="99")
-    @Prototype
-    public Object refreshLayout(Object domainObject);
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/jdosupport/IsisJdoSupport.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/jdosupport/IsisJdoSupport.java b/core/applib/src/main/java/org/apache/isis/applib/services/jdosupport/IsisJdoSupport.java
new file mode 100644
index 0000000..00e486a
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/jdosupport/IsisJdoSupport.java
@@ -0,0 +1,81 @@
+/*
+ *  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.applib.services.jdosupport;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import javax.jdo.PersistenceManager;
+import org.apache.isis.applib.annotation.Programmatic;
+
+/**
+ * Service that provide a number of workarounds when using JDO/DataNucleus. 
+ */
+public interface IsisJdoSupport {
+
+    /**
+     * Force a reload (corresponding to the JDO <tt>PersistenceManager</tt>'s <tt>refresh()</tt> method)
+     * of a domain objects.
+     * 
+     * <p>
+     * In fact, this may just reset the lazy-load state of the domain object, but the effect is the same: 
+     * to cause the object's state to be reloaded from the database.
+     * 
+     * <p>
+     * The particular example that led to this method being added was a 1:m bidirectional relationship,
+     * analogous to <tt>Customer <-> * Order</tt>.  Persisting the child <tt>Order</tt> object did not cause
+     * the parent <tt>Customer</tt>'s collection of orders to be updated.  In fact, JDO does not make any
+     * such guarantee to do so.  Options are therefore either to maintain the collection in code, or to
+     * refresh the parent.
+     */
+    @Programmatic
+    <T> T refresh(T domainObject);
+    
+    @Programmatic
+    void ensureLoaded(Collection<?> collectionOfDomainObjects);
+    
+    @Programmatic
+    PersistenceManager getJdoPersistenceManager();
+
+    @Programmatic
+    List<Map<String, Object>> executeSql(String sql);
+
+    @Programmatic
+    Integer executeUpdate(String sql);
+
+    /**
+     * Force the deletion of all instances of the specified class.
+     * 
+     * <p>
+     * Note: this is intended primarily for testing purposes, eg clearing existing data as part of
+     * installing fixtures.  It will generate a <tt>SQL DELETE</tt> for each instance.  To perform
+     * a bulk deletion with a single <tt>SQL DELETE</tt>, use {@link #executeUpdate(String)}.  
+     * 
+     * <p>
+     * Implementation note: It can occasionally be the case that Isis' internal adapter for the domain object is
+     * still in memory.  JDO/DataNucleus seems to bump up the version of the object prior to its deletion, 
+     * which under normal circumstances would cause Isis to throw a concurrency exception.  Therefore
+     * To prevent this from happening (ie to <i>force</i> the deletion of all instances), concurrency checking
+     * is temporarily disabled while this method is performed. 
+     */
+    @Programmatic
+    void deleteAll(Class<?>... pcClasses);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSetting.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSetting.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSetting.java
deleted file mode 100644
index 06d4ec1..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSetting.java
+++ /dev/null
@@ -1,25 +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.applib.services.settings;
-
-
-
-public interface ApplicationSetting extends Setting {
-
-    String getKey();
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSettingsService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSettingsService.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSettingsService.java
deleted file mode 100644
index d6ded31..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSettingsService.java
+++ /dev/null
@@ -1,34 +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.applib.services.settings;
-
-import java.util.List;
-
-import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.Named;
-
-public interface ApplicationSettingsService {
-
-    @MemberOrder(sequence="1")
-    ApplicationSetting find(@Named("Key") String key);
-
-    @MemberOrder(sequence="2")
-    List<ApplicationSetting> listAll();
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSettingsServiceRW.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSettingsServiceRW.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSettingsServiceRW.java
deleted file mode 100644
index ae680eb..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/ApplicationSettingsServiceRW.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.applib.services.settings;
-
-import org.joda.time.LocalDate;
-
-import org.apache.isis.applib.annotation.MemberOrder;
-
-public interface ApplicationSettingsServiceRW extends ApplicationSettingsService {
-
-    @MemberOrder(sequence="11")
-    ApplicationSetting newBoolean(String name, String description, Boolean defaultValue);
-    @MemberOrder(sequence="12")
-    ApplicationSetting newString(String name, String description, String defaultValue);
-    @MemberOrder(sequence="13")
-    ApplicationSetting newLocalDate(String name, String description, LocalDate defaultValue);
-    @MemberOrder(sequence="14")
-    ApplicationSetting newInt(String name, String description, Integer defaultValue);
-    @MemberOrder(sequence="15")
-    ApplicationSetting newLong(String name, String description, Long defaultValue);
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/Setting.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/Setting.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/Setting.java
deleted file mode 100644
index 3999d4c..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/Setting.java
+++ /dev/null
@@ -1,53 +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.applib.services.settings;
-
-import org.joda.time.LocalDate;
-
-import org.apache.isis.applib.annotation.MemberOrder;
-
-
-/**
- * Common supertype for both {@link ApplicationSetting} and {@link UserSetting}.
- * 
- * <p>
- * The difference between the two is in the settings unique identifier; 
- * the former just is uniquely identified by a single key (defined in 
- * {@link #getKey() this interface}, whereas the latter is uniquely identified by
- * the combination of the key plus an identifier of the user.
- */
-public interface Setting {
-
-    /**
-     * In the case of {@link ApplicationSetting}, this constitutes the unique identifier;
-     * for a {@link UserSetting}, the unique identifier is both this key plus an identifier
-     * for the user.  
-     */
-    String getKey();
-
-    SettingType getType();
-    String getDescription();
-
-    String getValueRaw();
-
-    String valueAsString();
-    LocalDate valueAsLocalDate();
-    Integer valueAsInt();
-    Long valueAsLong();
-    Boolean valueAsBoolean();
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/SettingAbstract.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/SettingAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/SettingAbstract.java
deleted file mode 100644
index 6eb39c8..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/SettingAbstract.java
+++ /dev/null
@@ -1,192 +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.applib.services.settings;
-
-import org.joda.time.LocalDate;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-
-import org.apache.isis.applib.annotation.Hidden;
-import org.apache.isis.applib.annotation.Immutable;
-import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.Named;
-import org.apache.isis.applib.annotation.Optional;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.Title;
-import org.apache.isis.applib.annotation.Where;
-
-
-/**
- * Convenience class to implement {@link Setting}.
- */
-@Immutable
-public abstract class SettingAbstract implements Setting {
-
-    public final static DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
-
-    @Title(sequence="10")
-    @MemberOrder(sequence="10")
-    public abstract String getKey();
-
-    @Optional
-    @MemberOrder(sequence="80")
-    public abstract String getDescription();
-
-    @MemberOrder(sequence="90")
-    public abstract SettingType getType();
-
-    // //////////////////////////////////////
-
-    @Title(prepend=" = ", sequence="30")
-    @MemberOrder(sequence="30")
-    @Hidden(where=Where.OBJECT_FORMS)
-    public abstract String getValueRaw();
-
-    // //////////////////////////////////////
-
-    @Programmatic
-    public String valueAsString() {
-        ensure(SettingType.STRING);
-        return getValueRaw();
-    }
-
-    // //////////////////////////////////////
-
-    @Programmatic
-    public LocalDate valueAsLocalDate() {
-        ensure(SettingType.LOCAL_DATE);
-        return parseValueAsLocalDate();
-    }
-
-    protected LocalDate parseValueAsLocalDate() {
-        return LocalDate.parse(getValueRaw(), DATE_FORMATTER);
-    }
-
-    // //////////////////////////////////////
-
-    @Programmatic
-    public Integer valueAsInt() {
-        ensure(SettingType.INT);
-        return parseValueAsInt();
-    }
-
-    protected int parseValueAsInt() {
-        return Integer.parseInt(getValueRaw());
-    }
-
-    // //////////////////////////////////////
-    
-    @Programmatic
-    public Long valueAsLong() {
-        ensure(SettingType.LONG);
-        return parseValueAsLong();
-    }
-    
-    protected long parseValueAsLong() {
-        return Long.parseLong(getValueRaw());
-    }
-    
-    // //////////////////////////////////////
-    
-    @Programmatic
-    public Boolean valueAsBoolean() {
-        ensure(SettingType.BOOLEAN);
-        return parseValueAsBoolean();
-    }
-
-    protected boolean parseValueAsBoolean() {
-        return Boolean.parseBoolean(getValueRaw());
-    }
-
-    // //////////////////////////////////////
-    
-    @MemberOrder(sequence="30")
-    @Hidden(where=Where.ALL_TABLES)
-    @Named("Value")
-    public String getValueAsString() {
-        return getValueRaw();
-    }
-    public boolean hideValueAsString() {
-        return typeIsNot(SettingType.STRING);
-    }
-
-    // //////////////////////////////////////
-    
-    @MemberOrder(sequence="30")
-    @Hidden(where=Where.ALL_TABLES)
-    @Named("Value")
-    public LocalDate getValueAsLocalDate() {
-        return parseValueAsLocalDate();
-    }
-    public boolean hideValueAsLocalDate() {
-        return typeIsNot(SettingType.LOCAL_DATE);
-    }
-    
-    // //////////////////////////////////////
-    
-    
-    @MemberOrder(sequence="30")
-    @Hidden(where=Where.ALL_TABLES)
-    @Named("Value")
-    public Integer getValueAsInt() {
-        return parseValueAsInt();
-    }
-    public boolean hideValueAsInt() {
-        return typeIsNot(SettingType.INT);
-    }
-    
-    // //////////////////////////////////////
-    
-    
-    
-    @MemberOrder(sequence="30")
-    @Hidden(where=Where.ALL_TABLES)
-    @Named("Value")
-    public Long getValueAsLong() {
-        return parseValueAsLong();
-    }
-    public boolean hideValueAsLong() {
-        return typeIsNot(SettingType.LONG);
-    }
-
-    // //////////////////////////////////////
-    
-    
-    
-    @MemberOrder(sequence="30")
-    @Hidden(where=Where.ALL_TABLES)
-    @Named("Value")
-    public Boolean getValueAsBoolean() {
-        return parseValueAsBoolean();
-    }
-    public boolean hideValueAsBoolean() {
-        return typeIsNot(SettingType.BOOLEAN);
-    }
-
-    // //////////////////////////////////////
-
-    private void ensure(SettingType settingType) {
-        if(typeIsNot(settingType)) {
-            throw new IllegalStateException("Setting '" + getKey() + "' is of type " + getType() + ", not of type " + settingType);
-        }
-    }
-    
-    protected boolean typeIsNot(SettingType settingType) {
-        return getType() != settingType;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/SettingType.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/SettingType.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/SettingType.java
deleted file mode 100644
index a652bf3..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/SettingType.java
+++ /dev/null
@@ -1,28 +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.applib.services.settings;
-
-
-public enum SettingType {
-
-    BOOLEAN,
-    INT,
-    LONG,
-    STRING,
-    LOCAL_DATE
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSetting.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSetting.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSetting.java
deleted file mode 100644
index 24ccf65..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSetting.java
+++ /dev/null
@@ -1,34 +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.applib.services.settings;
-
-import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.security.UserMemento;
-
-
-
-public interface UserSetting extends Setting {
-
-    String getKey();
-    
-    /**
-     * Typically as obtained from the {@link UserMemento#getName() UserMemento} class
-     * (accessible in turn from the {@link DomainObjectContainer#getUser() DomainObjectContainer}).
-     */
-    String getUser();
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSettingsService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSettingsService.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSettingsService.java
deleted file mode 100644
index f798e62..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSettingsService.java
+++ /dev/null
@@ -1,36 +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.applib.services.settings;
-
-import java.util.List;
-
-import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.Named;
-
-public interface UserSettingsService {
-
-    @MemberOrder(sequence="1")
-    UserSetting find(@Named("User") String user, @Named("Key") String key);
-    
-    @MemberOrder(sequence="2")
-    List<UserSetting> listAll();
-
-    @MemberOrder(sequence="3")
-    List<UserSetting> listAllFor(@Named("User") String user);
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSettingsServiceRW.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSettingsServiceRW.java b/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSettingsServiceRW.java
deleted file mode 100644
index 8b048ea..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/settings/UserSettingsServiceRW.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.applib.services.settings;
-
-import org.joda.time.LocalDate;
-
-import org.apache.isis.applib.annotation.MemberOrder;
-
-public interface UserSettingsServiceRW extends UserSettingsService {
-
-    @MemberOrder(sequence="11")
-    UserSetting newBoolean(String user, String name, String description, Boolean defaultValue);
-    @MemberOrder(sequence="12")
-    UserSetting newString(String user, String name, String description, String defaultValue);
-    @MemberOrder(sequence="13")
-    UserSetting newLocalDate(String user, String name, String description, LocalDate defaultValue);
-    @MemberOrder(sequence="14")
-    UserSetting newInt(String user, String name, String description, Integer defaultValue);
-    @MemberOrder(sequence="15")
-    UserSetting newLong(String user, String name, String description, Long defaultValue);
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkHolderAssociationContributions.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkHolderAssociationContributions.java b/core/applib/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkHolderAssociationContributions.java
deleted file mode 100644
index 8eb4aeb..0000000
--- a/core/applib/src/main/java/org/apache/isis/core/metamodel/services/bookmarks/BookmarkHolderAssociationContributions.java
+++ /dev/null
@@ -1,67 +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.metamodel.services.bookmarks;
-
-import java.util.Map;
-import javax.annotation.PostConstruct;
-import org.apache.isis.applib.annotation.NotContributed;
-import org.apache.isis.applib.annotation.NotInServiceMenu;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.bookmark.BookmarkHolder;
-import org.apache.isis.applib.services.bookmark.BookmarkService;
-
-/**
- * Domain service that contributes a property (named '<tt>Object</tt>') to
- * any class that implements {@link org.apache.isis.applib.services.bookmark.BookmarkHolder}.
- *
- * <p>
- * Alternatively, can use {@link org.apache.isis.applib.services.bookmark.BookmarkHolderActionContributions}
- * to contribute an action.
- *
- * <p>
- * The service must be explicitly registered, typically in <tt>isis.properties</tt>.
- */
-public class BookmarkHolderAssociationContributions {
-
-
-    //region > init
-    @Programmatic
-    @PostConstruct
-    public void init(Map<String,String> props) {
-        ensureDependenciesInjected();
-    }
-
-    private void ensureDependenciesInjected() {
-        if(this.bookmarkService == null){
-            throw new IllegalStateException("BookmarkService domain service must be configured");
-        }
-    }
-    //endregion
-
-    @NotInServiceMenu
-    @NotContributed(NotContributed.As.ACTION)
-    public Object object(final BookmarkHolder bookmarkHolder) {
-        return bookmarkService.lookup(bookmarkHolder);
-    }
-
-
-    @javax.inject.Inject
-    private BookmarkService bookmarkService;
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java b/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java
index 23faeb2..2d50ce6 100644
--- a/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java
+++ b/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java
@@ -19,65 +19,10 @@
 
 package org.apache.isis.objectstore.jdo.applib.service.support;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import javax.jdo.PersistenceManager;
-
-import org.apache.isis.applib.annotation.Programmatic;
-
 /**
- * Service that provide a number of workarounds when using JDO/DataNucleus. 
+ * @deprecated - replaced by {@link org.apache.isis.applib.services.jdosupport.IsisJdoSupport}
  */
-public interface IsisJdoSupport {
-
-    /**
-     * Force a reload (corresponding to the JDO <tt>PersistenceManager</tt>'s <tt>refresh()</tt> method)
-     * of a domain objects.
-     * 
-     * <p>
-     * In fact, this may just reset the lazy-load state of the domain object, but the effect is the same: 
-     * to cause the object's state to be reloaded from the database.
-     * 
-     * <p>
-     * The particular example that led to this method being added was a 1:m bidirectional relationship,
-     * analogous to <tt>Customer <-> * Order</tt>.  Persisting the child <tt>Order</tt> object did not cause
-     * the parent <tt>Customer</tt>'s collection of orders to be updated.  In fact, JDO does not make any
-     * such guarantee to do so.  Options are therefore either to maintain the collection in code, or to
-     * refresh the parent.
-     */
-    @Programmatic
-    <T> T refresh(T domainObject);
-    
-    @Programmatic
-    void ensureLoaded(Collection<?> collectionOfDomainObjects);
-    
-    @Programmatic
-    PersistenceManager getJdoPersistenceManager();
-
-    @Programmatic
-    List<Map<String, Object>> executeSql(String sql);
-
-    @Programmatic
-    Integer executeUpdate(String sql);
-
-    /**
-     * Force the deletion of all instances of the specified class.
-     * 
-     * <p>
-     * Note: this is intended primarily for testing purposes, eg clearing existing data as part of
-     * installing fixtures.  It will generate a <tt>SQL DELETE</tt> for each instance.  To perform
-     * a bulk deletion with a single <tt>SQL DELETE</tt>, use {@link #executeUpdate(String)}.  
-     * 
-     * <p>
-     * Implementation note: It can occasionally be the case that Isis' internal adapter for the domain object is
-     * still in memory.  JDO/DataNucleus seems to bump up the version of the object prior to its deletion, 
-     * which under normal circumstances would cause Isis to throw a concurrency exception.  Therefore
-     * To prevent this from happening (ie to <i>force</i> the deletion of all instances), concurrency checking
-     * is temporarily disabled while this method is performed. 
-     */
-    @Programmatic
-    void deleteAll(Class<?>... pcClasses);
+@Deprecated
+public interface IsisJdoSupport extends org.apache.isis.applib.services.jdosupport.IsisJdoSupport {
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/applib/src/test/java/org/apache/isis/applib/services/settings/SettingAbstractTest.java
----------------------------------------------------------------------
diff --git a/core/applib/src/test/java/org/apache/isis/applib/services/settings/SettingAbstractTest.java b/core/applib/src/test/java/org/apache/isis/applib/services/settings/SettingAbstractTest.java
deleted file mode 100644
index cc3191b..0000000
--- a/core/applib/src/test/java/org/apache/isis/applib/services/settings/SettingAbstractTest.java
+++ /dev/null
@@ -1,106 +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.applib.services.settings;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import org.joda.time.LocalDate;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import org.apache.isis.applib.annotation.Hidden;
-import org.apache.isis.applib.annotation.MemberOrder;
-
-public class SettingAbstractTest {
-
-    @Rule
-    public ExpectedException expectedExceptions = ExpectedException.none();
-
-    private static final class SettingAbstractForTesting extends SettingAbstract {
-        private final String key;
-        private final String valueRaw;
-        private final SettingType type;
-        
-        public SettingAbstractForTesting(String key, String valueRaw, SettingType type) {
-            this.key = key;
-            this.valueRaw = valueRaw;
-            this.type = type;
-        }
-        
-        public String getKey() {
-            return key;
-        }
-
-        public String getValueRaw() {
-            return valueRaw;
-        }
-
-        public SettingType getType() {
-            return type;
-        }
-
-        public String getDescription() {
-            return null;
-        }
-    }
-    
-    private SettingAbstract strSetting;
-    private SettingAbstract intSetting;
-    private SettingAbstract localDateSetting;
-    private SettingAbstract longSetting;
-    private SettingAbstract boolSetting;
-    
-    private LocalDate someLocalDate;
-    
-    @Before
-    public void setUp() throws Exception {
-        someLocalDate = new LocalDate(2012,4,1);
-        
-        strSetting = new SettingAbstractForTesting("strSetting", "ABC", SettingType.STRING);
-        intSetting = new SettingAbstractForTesting("intSetting", "" + Integer.MAX_VALUE, SettingType.INT);
-        localDateSetting = new SettingAbstractForTesting("localDateSetting", someLocalDate.toString(SettingAbstract.DATE_FORMATTER), SettingType.LOCAL_DATE);
-        longSetting = new SettingAbstractForTesting("longSetting", ""+Long.MAX_VALUE, SettingType.LONG);
-        boolSetting = new SettingAbstractForTesting("boolSetting", Boolean.TRUE.toString(), SettingType.BOOLEAN);
-    }
-    
-    @Test
-    public void happyCases() {
-        assertThat(strSetting.valueAsString(), is("ABC"));
-        assertThat(intSetting.valueAsInt(), is(Integer.MAX_VALUE));
-        assertThat(localDateSetting.valueAsLocalDate(), is(someLocalDate));
-        assertThat(longSetting.valueAsLong(), is(Long.MAX_VALUE));
-        assertThat(boolSetting.valueAsBoolean(), is(true));
-    }
-
-    @Test
-    public void sadCases() {
-        expectedExceptions.expectMessage("Setting 'strSetting' is of type STRING, not of type INT");
-        strSetting.valueAsInt();
-        expectedExceptions.expectMessage("Setting 'strSetting' is of type STRING, not of type LONG");
-        strSetting.valueAsLong();
-        expectedExceptions.expectMessage("Setting 'strSetting' is of type STRING, not of type LOCAL_DATE");
-        strSetting.valueAsLocalDate();
-        expectedExceptions.expectMessage("Setting 'strSetting' is of type STRING, not of type BOOLEAN");
-        strSetting.valueAsBoolean();
-        expectedExceptions.expectMessage("Setting 'intSetting' is of type INT, not of type STRING");
-        intSetting.valueAsString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
deleted file mode 100644
index 3c5af53..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
+++ /dev/null
@@ -1,231 +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.metamodel.services.devutils;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
-import javax.activation.MimeType;
-import javax.activation.MimeTypeParseException;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-
-import org.apache.isis.applib.FatalException;
-import org.apache.isis.applib.RecoverableException;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.devutils.DeveloperUtilitiesService;
-import org.apache.isis.applib.value.Blob;
-import org.apache.isis.applib.value.Clob;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManagerAware;
-import org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
-import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpiAware;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-
-public class DeveloperUtilitiesServiceDefault implements DeveloperUtilitiesService, SpecificationLoaderSpiAware, AdapterManagerAware {
-
-
-    private final MimeType mimeTypeTextCsv;
-    private final MimeType mimeTypeApplicationZip;
-    private final MimeType mimeTypeApplicationJson;
-
-    public DeveloperUtilitiesServiceDefault() {
-        try {
-            mimeTypeTextCsv = new MimeType("text", "csv");
-            mimeTypeApplicationJson = new MimeType("application", "jzon");
-            mimeTypeApplicationZip = new MimeType("application", "zip");
-        } catch (MimeTypeParseException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    // //////////////////////////////////////
-
-    
-    @Override
-    public Clob downloadMetaModel() {
-
-        final Collection<ObjectSpecification> specifications = specificationLoader.allSpecifications();
-
-        final List<MetaModelRow> rows = Lists.newArrayList();
-        for (ObjectSpecification spec : specifications) {
-            if (exclude(spec)) {
-                continue;
-            }
-            final List<ObjectAssociation> properties = spec.getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES);
-            for (ObjectAssociation property : properties) {
-                final OneToOneAssociation otoa = (OneToOneAssociation) property;
-                if (exclude(otoa)) {
-                    continue;
-                }
-                rows.add(new MetaModelRow(spec, otoa));
-            }
-            final List<ObjectAssociation> associations = spec.getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.COLLECTIONS);
-            for (ObjectAssociation collection : associations) {
-                final OneToManyAssociation otma = (OneToManyAssociation) collection;
-                if (exclude(otma)) {
-                    continue;
-                }
-                rows.add(new MetaModelRow(spec, otma));
-            }
-            final List<ObjectAction> actions = spec.getObjectActions(Contributed.INCLUDED);
-            for (ObjectAction action : actions) {
-                if (exclude(action)) {
-                    continue;
-                }
-                rows.add(new MetaModelRow(spec, action));
-            }
-        }
-
-        Collections.sort(rows);
-
-        final StringBuilder buf = new StringBuilder();
-        buf.append(MetaModelRow.header()).append("\n");
-        for (MetaModelRow row : rows) {
-            buf.append(row.asTextCsv()).append("\n");
-        }
-        return new Clob("metamodel.csv", mimeTypeTextCsv, buf.toString().toCharArray());
-    }
-
-    protected boolean exclude(OneToOneAssociation property) {
-        return false;
-    }
-
-    protected boolean exclude(OneToManyAssociation collection) {
-        return false;
-    }
-
-    protected boolean exclude(ObjectAction action) {
-        return false;
-    }
-
-    protected boolean exclude(ObjectSpecification spec) {
-        return isBuiltIn(spec) || spec.isAbstract();
-    }
-
-    protected boolean isBuiltIn(ObjectSpecification spec) {
-        final String className = spec.getFullIdentifier();
-        return className.startsWith("java") || className.startsWith("org.joda");
-    }
-
-    // //////////////////////////////////////
-    
-    @Override
-    public void refreshServices() {
-        Collection<ObjectSpecification> specifications = Lists.newArrayList(specificationLoader.allSpecifications());
-        for (ObjectSpecification objectSpec : specifications) {
-            if(objectSpec.isService()){
-                specificationLoader.invalidateCache(objectSpec.getCorrespondingClass());
-            }
-        }
-    }
-
-    // //////////////////////////////////////
-
-    @Override
-    public Object refreshLayout(Object domainObject) {
-        specificationLoader.invalidateCacheFor(domainObject);
-        return domainObject;
-    }
-
-    // //////////////////////////////////////
-    
-    @Override
-    public Clob downloadLayout(Object domainObject) {
-        
-        final ObjectAdapter adapterFor = adapterManager.adapterFor(domainObject);
-        final ObjectSpecification objectSpec = adapterFor.getSpecification();
-        
-        final LayoutMetadataReaderFromJson propertiesReader = new LayoutMetadataReaderFromJson();
-        final String json = propertiesReader.asJson(objectSpec);
-        
-        return new Clob(objectSpec.getShortIdentifier() +".layout.json", mimeTypeApplicationJson, json);
-    }
-
-    // //////////////////////////////////////
-
-    @Override
-    public Blob downloadLayouts() {
-        final LayoutMetadataReaderFromJson propertiesReader = new LayoutMetadataReaderFromJson();
-        final Collection<ObjectSpecification> allSpecs = specificationLoader.allSpecifications();
-        final Collection<ObjectSpecification> domainObjectSpecs = Collections2.filter(allSpecs, new Predicate<ObjectSpecification>(){
-            @Override
-            public boolean apply(ObjectSpecification input) {
-                return  !input.isAbstract() && 
-                        !input.isService() && 
-                        !input.isValue() && 
-                        !input.isParentedOrFreeCollection();
-            }});
-        try {
-            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            ZipOutputStream zos = new ZipOutputStream(baos);
-            OutputStreamWriter writer = new OutputStreamWriter(zos);
-            for (ObjectSpecification objectSpec : domainObjectSpecs) {
-                zos.putNextEntry(new ZipEntry(zipEntryNameFor(objectSpec)));
-                writer.write(propertiesReader.asJson(objectSpec));
-                writer.flush();
-                zos.closeEntry();
-            }
-            writer.close();
-            return new Blob("layouts.zip", mimeTypeApplicationZip, baos.toByteArray());
-        } catch (final IOException ex) {
-            throw new FatalException("Unable to create zip of layouts", ex);
-        }
-    }
-
-    private static String zipEntryNameFor(ObjectSpecification objectSpec) {
-        final String fqn = objectSpec.getFullIdentifier();
-        return fqn.replace(".", File.separator)+".layout.json";
-    }
-
-
-    // //////////////////////////////////////
-
-    private SpecificationLoaderSpi specificationLoader;
-    private AdapterManager adapterManager;
-
-    @Programmatic
-    @Override
-    public void setSpecificationLoaderSpi(SpecificationLoaderSpi specificationLoader) {
-        this.specificationLoader = specificationLoader;
-    }
-
-    @Override
-    public void setAdapterManager(AdapterManager adapterManager) {
-        this.adapterManager = adapterManager;
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/MetaModelRow.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/MetaModelRow.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/MetaModelRow.java
deleted file mode 100644
index 5af35fc..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/MetaModelRow.java
+++ /dev/null
@@ -1,234 +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.metamodel.services.devutils;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.SortedSet;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Strings;
-import com.google.common.collect.Sets;
-
-import org.apache.isis.applib.util.ObjectContracts;
-import org.apache.isis.core.commons.lang.StringExtensions;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.ImperativeFacet;
-import org.apache.isis.core.metamodel.facets.actions.choices.ActionChoicesFacet;
-import org.apache.isis.core.metamodel.facets.actions.defaults.ActionDefaultsFacet;
-import org.apache.isis.core.metamodel.facets.hide.HiddenFacet;
-import org.apache.isis.core.metamodel.facets.param.autocomplete.ActionParameterAutoCompleteFacet;
-import org.apache.isis.core.metamodel.facets.param.choices.ActionParameterChoicesFacet;
-import org.apache.isis.core.metamodel.facets.param.defaults.ActionParameterDefaultsFacet;
-import org.apache.isis.core.metamodel.facets.properties.autocomplete.PropertyAutoCompleteFacet;
-import org.apache.isis.core.metamodel.facets.properties.choices.PropertyChoicesFacet;
-import org.apache.isis.core.metamodel.facets.properties.defaults.PropertyDefaultFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
-import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.isis.core.progmodel.facets.actions.validate.ActionValidationFacet;
-import org.apache.isis.core.progmodel.facets.collections.validate.CollectionValidateAddToFacet;
-import org.apache.isis.core.progmodel.facets.collections.validate.CollectionValidateRemoveFromFacet;
-import org.apache.isis.core.progmodel.facets.members.disabled.DisabledFacet;
-import org.apache.isis.core.progmodel.facets.properties.validate.PropertyValidateFacet;
-
-public class MetaModelRow implements Comparable<MetaModelRow>{
-
-    enum MemberType {
-        PROPERTY,
-        COLLECTION,
-        ACTION;
-    }
-
-    private final ObjectSpecification spec;
-    private final MemberType memberType;
-    private final ObjectMember member;
-    private ObjectAction action;
-    
-    MetaModelRow(ObjectSpecification spec, OneToOneAssociation property) {
-        this.spec = spec;
-        this.member = property;
-        this.memberType = MemberType.PROPERTY;
-    }
-
-    MetaModelRow(ObjectSpecification spec, OneToManyAssociation collection) {
-        this.spec = spec;
-        this.member = collection;
-        this.memberType = MemberType.COLLECTION;
-    }
-    
-    MetaModelRow(ObjectSpecification spec, ObjectAction action) {
-        this.spec = spec;
-        this.member = this.action = action;
-        this.memberType = MemberType.ACTION;
-    }
-
-    public String getClassType() {
-        boolean service = false;
-        for(ObjectSpecification subspecs: spec.subclasses()) {
-            service = service || subspecs.isService();
-        }
-        return service || spec.isService() ?"2 Service":spec.isValue()?"3 Value":spec.isParentedOrFreeCollection()?"4 Collection":"1 Object";
-    }
-    public String getClassName() {
-        final String fullIdentifier = spec.getFullIdentifier();
-        final int lastDot = fullIdentifier.lastIndexOf(".");
-        return lastDot>0 && lastDot < fullIdentifier.length()-1
-                ?fullIdentifier.substring(lastDot+1,fullIdentifier.length())
-                :fullIdentifier;
-    }
-    public String getPackageName() {
-        final String fullIdentifier = spec.getFullIdentifier();
-        final int lastDot = fullIdentifier.lastIndexOf(".");
-        return lastDot>0?fullIdentifier.substring(0,lastDot):fullIdentifier;
-    }
-    public String getType() {
-        return memberType.name().toLowerCase();
-    }
-    public String getMemberName() {
-        return member.getId();
-    }
-    public String getNumParams() {
-        return action!=null?""+action.getParameterCount():"";
-    }
-    String getHidden() {
-        return interpret(HiddenFacet.class);
-    }
-    String getDisabled() {
-        return interpret(DisabledFacet.class);
-    }
-    public String getChoices() {
-        if(memberType == MemberType.PROPERTY) {
-            return interpretRowAndFacet(PropertyChoicesFacet.class);
-        } else if(memberType == MemberType.COLLECTION) {
-            return "";
-        } else {
-            final List<ObjectActionParameter> parameters = this.action.getParameters();
-            final SortedSet<String> interpretations = Sets.newTreeSet();
-            for (ObjectActionParameter param : parameters) {
-                final ActionParameterChoicesFacet facet = param.getFacet(ActionParameterChoicesFacet.class);
-                addIfNotEmpty(interpretFacet(facet), interpretations);
-            }
-            return !interpretations.isEmpty()? Joiner.on(";").join(interpretations) : interpretRowAndFacet(ActionChoicesFacet.class);
-        }
-    }
-    public String getAutoComplete() {
-        if(memberType == MemberType.PROPERTY) {
-            return interpretRowAndFacet(PropertyAutoCompleteFacet.class);
-        } else if(memberType == MemberType.COLLECTION) {
-           return "";
-        } else {
-            final List<ObjectActionParameter> parameters = this.action.getParameters();
-            final SortedSet<String> interpretations = Sets.newTreeSet();
-            for (ObjectActionParameter param : parameters) {
-                final ActionParameterAutoCompleteFacet facet = param.getFacet(ActionParameterAutoCompleteFacet.class);
-                addIfNotEmpty(interpretFacet(facet), interpretations);
-            }
-            return !interpretations.isEmpty()? Joiner.on(";").join(interpretations) : "";
-        }
-    }
-    String getDefault() {
-        if(memberType == MemberType.PROPERTY) {
-            return interpretRowAndFacet(PropertyDefaultFacet.class);
-        } else if(memberType == MemberType.COLLECTION) {
-            return "";
-        } else {
-            final List<ObjectActionParameter> parameters = this.action.getParameters();
-            final SortedSet<String> interpretations = Sets.newTreeSet();
-            for (ObjectActionParameter param : parameters) {
-                final ActionParameterDefaultsFacet facet = param.getFacet(ActionParameterDefaultsFacet.class);
-                addIfNotEmpty(interpretFacet(facet), interpretations);
-            }
-            return !interpretations.isEmpty()? Joiner.on(";").join(interpretations) : interpretRowAndFacet(ActionDefaultsFacet.class);
-        }
-    }
-    String getValidate() {
-        if(memberType == MemberType.PROPERTY) {
-            return interpretRowAndFacet(PropertyValidateFacet.class);
-        } else if(memberType == MemberType.COLLECTION) {
-            final SortedSet<String> interpretations = Sets.newTreeSet();
-            addIfNotEmpty(interpretRowAndFacet(CollectionValidateAddToFacet.class), interpretations);
-            addIfNotEmpty(interpretRowAndFacet(CollectionValidateRemoveFromFacet.class), interpretations);
-            return !interpretations.isEmpty()? Joiner.on(";").join(interpretations) : "";
-       } else {
-           return interpretRowAndFacet(ActionValidationFacet.class);
-        }
-    }
-
-    static Object header() {
-        return "classType,packageName,className,memberType,memberName,numParams,hidden,disabled,choices,autoComplete,default,validate";
-    }
-    
-    String asTextCsv() {
-        return Joiner.on(",").join(
-                getClassType(),
-                getPackageName(),
-                getClassName(),
-                getType(),
-                getMemberName(),
-                getNumParams(),
-                getHidden(),
-                getDisabled(),
-                getChoices(),
-                getAutoComplete(),
-                getDefault(),
-                getValidate());
-    }
- 
-    private String interpretRowAndFacet(Class<? extends Facet> facetClass) {
-        final Facet facet = member.getFacet(facetClass);
-        return interpretFacet(facet);
-    }
-    
-    private static void addIfNotEmpty(final String str, final SortedSet<String> set) {
-        if(!Strings.isNullOrEmpty(str)) {
-            set.add(str);
-        }
-    }
-    
-    private String interpret(final Class<? extends Facet> cls) {
-        return interpretFacet(member.getFacet(cls));
-    }
-
-    private static String interpretFacet(final Facet facet) {
-        if (facet == null || facet.isNoop()) {
-            return "";
-        }
-        if (facet instanceof ImperativeFacet) {
-            ImperativeFacet imperativeFacet = (ImperativeFacet) facet;
-            return imperativeFacet.getMethods().get(0).getName();
-        } 
-        final String name = facet.getClass().getSimpleName();
-        if (ignore(name)) {
-            return "";
-        } 
-        final String abbr = StringExtensions.toAbbreviation(name);
-        return abbr.length()>0 ? abbr : name;
-    }
-
-    protected static boolean ignore(final String name) {
-        return Arrays.asList("PropertyValidateFacetDefault","PropertyDefaultFacetDerivedFromDefaultedFacet").contains(name);
-    }
-
-    @Override
-    public int compareTo(MetaModelRow o) {
-        return ObjectContracts.compare(this, o, "classType,className,type desc,memberName");
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ServiceInitializer.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ServiceInitializer.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ServiceInitializer.java
index 59108e7..367e99e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ServiceInitializer.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ServiceInitializer.java
@@ -38,12 +38,7 @@ public class ServiceInitializer {
 
     private Map<String, String> props;
     
-    static class ServiceInitMethods {
-        Object service;
-        Method postConstruct;
-        Method preDestrory;
-    }
-    
+
     private Map<Object, Method> postConstructMethodsByService = Maps.newLinkedHashMap(); 
     private Map<Object, Method> preDestroyMethodsByService = Maps.newLinkedHashMap(); 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/module-devutils/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java
----------------------------------------------------------------------
diff --git a/core/module-devutils/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java b/core/module-devutils/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java
new file mode 100644
index 0000000..6a25cfc
--- /dev/null
+++ b/core/module-devutils/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.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.applib.services.devutils;
+
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.annotation.NotInServiceMenu;
+import org.apache.isis.applib.annotation.Prototype;
+import org.apache.isis.applib.value.Blob;
+import org.apache.isis.applib.value.Clob;
+
+@Named("Developer Utilities")
+public interface DeveloperUtilitiesService {
+
+    @MemberOrder(sequence="1")
+    @ActionSemantics(Of.SAFE)
+    @Prototype
+    public Clob downloadMetaModel();
+
+
+    /**
+     * Downloads a zip of the layout of all domain classes.
+     */
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence="3")
+    @Prototype
+    public Blob downloadLayouts();
+
+    /**
+     * Rebuilds the metamodel of all registered domain services.
+     */
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence="3")
+    @Prototype
+    public void refreshServices();
+
+    /**
+     * Download the JSON layout of the domain object's type.
+     */
+    @NotInServiceMenu
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence="2")
+    @Prototype
+    public Clob downloadLayout(Object domainObject);
+
+    /**
+     * @deprecated - in prototype mode the Wicket viewer (at least) will automatically invalidate 
+     *               the Isis metamodel whenever the object is re-rendered.
+     */
+    @Deprecated
+    @Hidden
+    @NotInServiceMenu
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence="99")
+    @Prototype
+    public Object refreshLayout(Object domainObject);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/module-devutils/impl/pom.xml
----------------------------------------------------------------------
diff --git a/core/module-devutils/impl/pom.xml b/core/module-devutils/impl/pom.xml
index 20c3ad7..da20f0f 100644
--- a/core/module-devutils/impl/pom.xml
+++ b/core/module-devutils/impl/pom.xml
@@ -42,9 +42,15 @@
 
 	<dependencies>
         <dependency>
+            <groupId>org.apache.isis.module</groupId>
+            <artifactId>isis-module-devutils-applib</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.isis.core</groupId>
-            <artifactId>isis-core-applib</artifactId>
+            <artifactId>isis-core-metamodel</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.apache.isis.core</groupId>
             <artifactId>isis-core-unittestsupport</artifactId>

http://git-wip-us.apache.org/repos/asf/isis/blob/8b6cab67/core/module-devutils/impl/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/module-devutils/impl/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java b/core/module-devutils/impl/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
new file mode 100644
index 0000000..d36746b
--- /dev/null
+++ b/core/module-devutils/impl/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
@@ -0,0 +1,223 @@
+/*
+ *  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.metamodel.services.devutils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import javax.activation.MimeType;
+import javax.activation.MimeTypeParseException;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.devutils.DeveloperUtilitiesService;
+import org.apache.isis.applib.value.Blob;
+import org.apache.isis.applib.value.Clob;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManagerAware;
+import org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpiAware;
+import org.apache.isis.core.metamodel.spec.feature.*;
+
+public class DeveloperUtilitiesServiceDefault implements DeveloperUtilitiesService, SpecificationLoaderSpiAware, AdapterManagerAware {
+
+
+    private final MimeType mimeTypeTextCsv;
+    private final MimeType mimeTypeApplicationZip;
+    private final MimeType mimeTypeApplicationJson;
+
+    public DeveloperUtilitiesServiceDefault() {
+        try {
+            mimeTypeTextCsv = new MimeType("text", "csv");
+            mimeTypeApplicationJson = new MimeType("application", "jzon");
+            mimeTypeApplicationZip = new MimeType("application", "zip");
+        } catch (MimeTypeParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // //////////////////////////////////////
+
+    
+    @Override
+    public Clob downloadMetaModel() {
+
+        final Collection<ObjectSpecification> specifications = specificationLoader.allSpecifications();
+
+        final List<MetaModelRow> rows = Lists.newArrayList();
+        for (ObjectSpecification spec : specifications) {
+            if (exclude(spec)) {
+                continue;
+            }
+            final List<ObjectAssociation> properties = spec.getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES);
+            for (ObjectAssociation property : properties) {
+                final OneToOneAssociation otoa = (OneToOneAssociation) property;
+                if (exclude(otoa)) {
+                    continue;
+                }
+                rows.add(new MetaModelRow(spec, otoa));
+            }
+            final List<ObjectAssociation> associations = spec.getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.COLLECTIONS);
+            for (ObjectAssociation collection : associations) {
+                final OneToManyAssociation otma = (OneToManyAssociation) collection;
+                if (exclude(otma)) {
+                    continue;
+                }
+                rows.add(new MetaModelRow(spec, otma));
+            }
+            final List<ObjectAction> actions = spec.getObjectActions(Contributed.INCLUDED);
+            for (ObjectAction action : actions) {
+                if (exclude(action)) {
+                    continue;
+                }
+                rows.add(new MetaModelRow(spec, action));
+            }
+        }
+
+        Collections.sort(rows);
+
+        final StringBuilder buf = new StringBuilder();
+        buf.append(MetaModelRow.header()).append("\n");
+        for (MetaModelRow row : rows) {
+            buf.append(row.asTextCsv()).append("\n");
+        }
+        return new Clob("metamodel.csv", mimeTypeTextCsv, buf.toString().toCharArray());
+    }
+
+    protected boolean exclude(OneToOneAssociation property) {
+        return false;
+    }
+
+    protected boolean exclude(OneToManyAssociation collection) {
+        return false;
+    }
+
+    protected boolean exclude(ObjectAction action) {
+        return false;
+    }
+
+    protected boolean exclude(ObjectSpecification spec) {
+        return isBuiltIn(spec) || spec.isAbstract();
+    }
+
+    protected boolean isBuiltIn(ObjectSpecification spec) {
+        final String className = spec.getFullIdentifier();
+        return className.startsWith("java") || className.startsWith("org.joda");
+    }
+
+    // //////////////////////////////////////
+    
+    @Override
+    public void refreshServices() {
+        Collection<ObjectSpecification> specifications = Lists.newArrayList(specificationLoader.allSpecifications());
+        for (ObjectSpecification objectSpec : specifications) {
+            if(objectSpec.isService()){
+                specificationLoader.invalidateCache(objectSpec.getCorrespondingClass());
+            }
+        }
+    }
+
+    // //////////////////////////////////////
+
+    @Override
+    public Object refreshLayout(Object domainObject) {
+        specificationLoader.invalidateCacheFor(domainObject);
+        return domainObject;
+    }
+
+    // //////////////////////////////////////
+    
+    @Override
+    public Clob downloadLayout(Object domainObject) {
+        
+        final ObjectAdapter adapterFor = adapterManager.adapterFor(domainObject);
+        final ObjectSpecification objectSpec = adapterFor.getSpecification();
+        
+        final LayoutMetadataReaderFromJson propertiesReader = new LayoutMetadataReaderFromJson();
+        final String json = propertiesReader.asJson(objectSpec);
+        
+        return new Clob(objectSpec.getShortIdentifier() +".layout.json", mimeTypeApplicationJson, json);
+    }
+
+    // //////////////////////////////////////
+
+    @Override
+    public Blob downloadLayouts() {
+        final LayoutMetadataReaderFromJson propertiesReader = new LayoutMetadataReaderFromJson();
+        final Collection<ObjectSpecification> allSpecs = specificationLoader.allSpecifications();
+        final Collection<ObjectSpecification> domainObjectSpecs = Collections2.filter(allSpecs, new Predicate<ObjectSpecification>(){
+            @Override
+            public boolean apply(ObjectSpecification input) {
+                return  !input.isAbstract() && 
+                        !input.isService() && 
+                        !input.isValue() && 
+                        !input.isParentedOrFreeCollection();
+            }});
+        try {
+            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ZipOutputStream zos = new ZipOutputStream(baos);
+            OutputStreamWriter writer = new OutputStreamWriter(zos);
+            for (ObjectSpecification objectSpec : domainObjectSpecs) {
+                zos.putNextEntry(new ZipEntry(zipEntryNameFor(objectSpec)));
+                writer.write(propertiesReader.asJson(objectSpec));
+                writer.flush();
+                zos.closeEntry();
+            }
+            writer.close();
+            return new Blob("layouts.zip", mimeTypeApplicationZip, baos.toByteArray());
+        } catch (final IOException ex) {
+            throw new FatalException("Unable to create zip of layouts", ex);
+        }
+    }
+
+    private static String zipEntryNameFor(ObjectSpecification objectSpec) {
+        final String fqn = objectSpec.getFullIdentifier();
+        return fqn.replace(".", File.separator)+".layout.json";
+    }
+
+
+    // //////////////////////////////////////
+
+    private SpecificationLoaderSpi specificationLoader;
+    private AdapterManager adapterManager;
+
+    @Programmatic
+    @Override
+    public void setSpecificationLoaderSpi(SpecificationLoaderSpi specificationLoader) {
+        this.specificationLoader = specificationLoader;
+    }
+
+    @Override
+    public void setAdapterManager(AdapterManager adapterManager) {
+        this.adapterManager = adapterManager;
+    }
+
+
+}