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 2012/12/06 11:10:34 UTC
[17/51] [partial] ISIS-188: moving modules into core
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/docbkx/to-incorporate/eclipse-templates.xml
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/docbkx/to-incorporate/eclipse-templates.xml b/framework/core/applib/src/docbkx/to-incorporate/eclipse-templates.xml
new file mode 100644
index 0000000..7492af1
--- /dev/null
+++ b/framework/core/applib/src/docbkx/to-incorporate/eclipse-templates.xml
@@ -0,0 +1,467 @@
+<?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.
+-->
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V1.1//EN"
+"http://www.oasis-open.org/docbook/xml/simple/1.1/sdocbook.dtd">
+<article>
+ <articleinfo>
+ <title></title>
+
+ <author>
+ <firstname></firstname>
+
+ <surname></surname>
+
+ <affiliation>
+ <orgname></orgname>
+ </affiliation>
+ </author>
+
+ <pubdate></pubdate>
+ </articleinfo>
+
+ <section>
+ <title>Using the templates in Eclipse</title>
+
+ <para>The latest release of [[NAME]] (version 4) provides a set of
+ templates for quickly adding snippets to your domain classes, from properties and collections to title and dependencies.</para>
+
+ <para>To set up Eclipse so these are available you need to import the template files that are included in the distribution. In both the Ant and
+ Maven based distributions they can be found the following
+ directory:</para>
+
+ <literallayout>resources
+|-- ide
+| `-- eclipse
+| |-- launch
+| `-- templates
+| |-- jmock2-templates.xml
+| |-- junit4-templates.xml
+| `-- isis-templates.xml
+</literallayout>
+
+ <para>Open up Eclipse's preferences dialog
+ (<option>Windows</option>/<option>Preferences</option>) and navigate to
+ <option>Java</option> - <option>Editor</option> -
+ <option>Template</option>. Click the <option>Import</option> button,
+ browse to the <filename>templates</filename> directory, select the
+ <filename>isis-templates.xml</filename> file and press OK. A
+ series of templates will be added prefixed with <emphasis>no</emphasis>
+ such as <emphasis>noa</emphasis>, <emphasis>nol</emphasis>,
+ <emphasis>nop</emphasis> etc. Press OK to commit the changes and you are
+ ready to use them.</para>
+
+ <para>For example, to insert a property type <emphasis>nop</emphasis> in the editor
+ window within the class declations and press
+ <userinput>ctrl-space</userinput> to bring up the available
+ templates.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/template-list.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>Each template has a brief description and the template result is
+ shown in the box next to the list. Selecting the template inserts the code
+ into your file at the cursor replacing the template name that you
+ typed.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/template-insert.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>It also highlights the parts that you can change. So in this example
+ when we type <emphasis>Purchase</emphasis>, tab,
+ <emphasis>Date</emphasis>, tab, and <emphasis>date</emphasis> we end up
+ with a complete property declaration for a Date value that will display
+ with the label <emphasis>Date</emphasis>.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/template-complete.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>The other files each provide a couple of templates for building
+ Junit version 4 tests and using JMock.</para>
+
+ <para>The available [[NAME]] templates are:-</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>noa</term>
+
+ <listitem>
+ <para>Action</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noacho</term>
+
+ <listitem>
+ <para>Action argument N choices</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noadef</term>
+
+ <listitem>
+ <para>Action argument defaults</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noadis</term>
+
+ <listitem>
+ <para>Action disabling</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noahid</term>
+
+ <listitem>
+ <para>Action hiding</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noaval</term>
+
+ <listitem>
+ <para>Action validation</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noc-1m</term>
+
+ <listitem>
+ <para>Collection (1:m bidir parent)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noc-mmc</term>
+
+ <listitem>
+ <para>Collection (m:m bidir child)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noc-mmp</term>
+
+ <listitem>
+ <para>Collection (m:m bidir parent)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nocdis</term>
+
+ <listitem>
+ <para>Collection disabling</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nochid</term>
+
+ <listitem>
+ <para>Collection hiding</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nocl</term>
+
+ <listitem>
+ <para>Collection (list)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nocmod</term>
+
+ <listitem>
+ <para>Collection modify</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nocs</term>
+
+ <listitem>
+ <para>Collection (set)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nocval</term>
+
+ <listitem>
+ <para>Collection validation</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nod</term>
+
+ <listitem>
+ <para>Dependencies region</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nods</term>
+
+ <listitem>
+ <para>Dependencies - injected service</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nofp</term>
+
+ <listitem>
+ <para>Factory - new instance (persistent)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noft</term>
+
+ <listitem>
+ <para>Factory - new instance (transient)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noid</term>
+
+ <listitem>
+ <para>Identification region</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noidicon</term>
+
+ <listitem>
+ <para>Identification - icon</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noidtitle</term>
+
+ <listitem>
+ <para>Identification - title</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nol</term>
+
+ <listitem>
+ <para>Lifecycle region</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nolc</term>
+
+ <listitem>
+ <para>Lifecycle - create</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noll</term>
+
+ <listitem>
+ <para>Lifecycle - load</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nolp</term>
+
+ <listitem>
+ <para>Lifecycle - persist</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nolr</term>
+
+ <listitem>
+ <para>Lifecycle - remove</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nolu</term>
+
+ <listitem>
+ <para>Lifecycle - update</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nop</term>
+
+ <listitem>
+ <para>Property</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nop-11c</term>
+
+ <listitem>
+ <para>Property (1:1 bidir child)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nop-11p</term>
+
+ <listitem>
+ <para>Property (1:1 bidir parent)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nop-m1</term>
+
+ <listitem>
+ <para>Property (m:1 bidir child)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nopcho</term>
+
+ <listitem>
+ <para>Property choices</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nopdef</term>
+
+ <listitem>
+ <para>Property defaults</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nopdis</term>
+
+ <listitem>
+ <para>Property disabling</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nophid</term>
+
+ <listitem>
+ <para>Property hiding</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nopmod</term>
+
+ <listitem>
+ <para>Property modify</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nopval</term>
+
+ <listitem>
+ <para>Property validation</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nosa</term>
+
+ <listitem>
+ <para>Search for all</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nosafil</term>
+
+ <listitem>
+ <para>Search for all matching</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nosffil</term>
+
+ <listitem>
+ <para>Search for first matching</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nosufil</term>
+
+ <listitem>
+ <para>Search for unique matching</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>noval</term>
+
+ <listitem>
+ <para>Object-level validation</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <variablelist>
+ <varlistentry>
+ <term></term>
+
+ <listitem>
+ <para></para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para></para>
+ </section>
+</article>
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/docbkx/to-incorporate/images/create-patch-dialog.png
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/docbkx/to-incorporate/images/create-patch-dialog.png b/framework/core/applib/src/docbkx/to-incorporate/images/create-patch-dialog.png
new file mode 100644
index 0000000..5588e1d
Binary files /dev/null and b/framework/core/applib/src/docbkx/to-incorporate/images/create-patch-dialog.png differ
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/docbkx/to-incorporate/images/template-complete.png
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/docbkx/to-incorporate/images/template-complete.png b/framework/core/applib/src/docbkx/to-incorporate/images/template-complete.png
new file mode 100644
index 0000000..db0713a
Binary files /dev/null and b/framework/core/applib/src/docbkx/to-incorporate/images/template-complete.png differ
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/docbkx/to-incorporate/images/template-insert.png
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/docbkx/to-incorporate/images/template-insert.png b/framework/core/applib/src/docbkx/to-incorporate/images/template-insert.png
new file mode 100644
index 0000000..4c781ea
Binary files /dev/null and b/framework/core/applib/src/docbkx/to-incorporate/images/template-insert.png differ
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/docbkx/to-incorporate/images/template-list.png
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/docbkx/to-incorporate/images/template-list.png b/framework/core/applib/src/docbkx/to-incorporate/images/template-list.png
new file mode 100644
index 0000000..cd02cfb
Binary files /dev/null and b/framework/core/applib/src/docbkx/to-incorporate/images/template-list.png differ
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/docbkx/to-incorporate/snippet-fixture-service.xml
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/docbkx/to-incorporate/snippet-fixture-service.xml b/framework/core/applib/src/docbkx/to-incorporate/snippet-fixture-service.xml
new file mode 100644
index 0000000..f151cc2
--- /dev/null
+++ b/framework/core/applib/src/docbkx/to-incorporate/snippet-fixture-service.xml
@@ -0,0 +1,82 @@
+<?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.
+-->
+<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V1.1//EN"
+"http://www.oasis-open.org/docbook/xml/simple/1.1/sdocbook.dtd">
+<article>
+ <articleinfo>
+ <title></title>
+
+ <author>
+ <firstname></firstname>
+
+ <surname></surname>
+
+ <affiliation>
+ <orgname></orgname>
+ </affiliation>
+ </author>
+
+ <pubdate></pubdate>
+ </articleinfo>
+
+ <section>
+ <title>Dynamic fixture service</title>
+
+ <para>When developing applications it is nice to ready prepared objects so
+ you don't have to continually create them every time you run in
+ exploration mode. As you read already these can be created using fixtures,
+ but that requires coding specific classes. Whilst turing on persistence
+ means that you get back what you had last time, but that probably includes
+ objects that you didn't want to keep. A better solution is to use the new
+ fixture service that allows you to save specific objects on the desktop
+ and have them, and only them, recreated when you next start up.</para>
+
+ <para></para>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>Add the following property to
+ <filename>isis.properties</filename> to enable this feature.
+ Better still create and add it to a file called
+ <filename>exploration.properties</filename> so it is only used in
+ exploration mode.</para>
+
+ <literallayout>isis.exploration-objects=true</literallayout>
+
+ <para>There is a second property that allows you specify where your data
+ file is stored.</para>
+
+ <literallayout>isis.exploration-objects.file=tmp/data</literallayout>
+
+ <section>
+ <title></title>
+
+ <para></para>
+ </section>
+ </section>
+
+ <section>
+ <title></title>
+
+ <para>Data for an object is </para>
+ </section>
+ </section>
+</article>
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java b/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
new file mode 100644
index 0000000..ec0978a
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
@@ -0,0 +1,327 @@
+/*
+ * 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;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Aggregated;
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.applib.query.Query;
+import org.apache.isis.applib.security.UserMemento;
+
+/**
+ * Convenience super class for all classes that wish to interact with the
+ * container.
+ *
+ * @see org.apache.isis.applib.DomainObjectContainer
+ */
+public abstract class AbstractContainedObject {
+
+ // {{ factory methods
+ @Hidden
+ protected <T> T newTransientInstance(final Class<T> ofType) {
+ return getContainer().newTransientInstance(ofType);
+ }
+
+ /**
+ * Create an instance that will be persisted as part of this domain object
+ * (ie this domain object is its parent in the aggregate).
+ *
+ * <p>
+ * The type provided should be annotated with {@link Aggregated}.
+ *
+ * @see #newAggregatedInstance(Object, Class)
+ */
+ @Hidden
+ protected <T> T newAggregatedInstance(final Class<T> ofType) {
+ return newAggregatedInstance(this, ofType);
+ }
+
+ /**
+ * Create an instance that will be persisted as part of specified paremt domain object
+ * (ie that domain object will be its parent in the aggregate).
+ *
+ * <p>
+ * The type provided should be annotated with {@link Aggregated}.
+ *
+ * @see #newAggregatedInstance(Class)
+ */
+ @Hidden
+ protected <T> T newAggregatedInstance(final Object parent, final Class<T> ofType) {
+ return getContainer().newAggregatedInstance(parent, ofType);
+ }
+ // }}
+
+ // {{ allInstances, allMatches
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#allInstances(Class)
+ */
+ protected <T> List<T> allInstances(final Class<T> ofType) {
+ return getContainer().allInstances(ofType);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#allMatches(Class, Filter)
+ */
+ protected <T> List<T> allMatches(final Class<T> ofType, final Filter<? super T> filter) {
+ return getContainer().allMatches(ofType, filter);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#allMatches(Class, Object)
+ */
+ protected <T> List<T> allMatches(final Class<T> ofType, final T pattern) {
+ return getContainer().allMatches(ofType, pattern);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#allMatches(Class, String)
+ */
+ protected <T> List<T> allMatches(final Class<T> ofType, final String title) {
+ return getContainer().allMatches(ofType, title);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#allMatches(Query)
+ */
+ protected <T> List<T> allMatches(final Query<T> query) {
+ return getContainer().allMatches(query);
+ }
+
+ // }}
+
+ // {{ firstMatch
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#firstMatch(Class, Filter)
+ */
+ protected <T> T firstMatch(final Class<T> ofType, final Filter<T> filter) {
+ return getContainer().firstMatch(ofType, filter);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#firstMatch(Class, Object)
+ */
+ protected <T> T firstMatch(final Class<T> ofType, final T pattern) {
+ return getContainer().firstMatch(ofType, pattern);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#firstMatch(Class, String)
+ */
+ protected <T> T firstMatch(final Class<T> ofType, final String title) {
+ return getContainer().firstMatch(ofType, title);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#firstMatch(Query)
+ */
+ protected <T> T firstMatch(final Query<T> query) {
+ return getContainer().firstMatch(query);
+ }
+
+ // }}
+
+ // {{ uniqueMatch
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#uniqueMatch(Class, Filter)
+ */
+ protected <T> T uniqueMatch(final Class<T> ofType, final Filter<T> filter) {
+ return getContainer().uniqueMatch(ofType, filter);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#uniqueMatch(Class, String)
+ */
+ protected <T> T uniqueMatch(final Class<T> ofType, final String title) {
+ return getContainer().uniqueMatch(ofType, title);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#uniqueMatch(Class, Object)
+ */
+ protected <T> T uniqueMatch(final Class<T> ofType, final T pattern) {
+ return getContainer().uniqueMatch(ofType, pattern);
+ }
+
+ /**
+ * Convenience method that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#uniqueMatch(Query)
+ */
+ protected <T> T uniqueMatch(final Query<T> query) {
+ return getContainer().uniqueMatch(query);
+ }
+
+ // }}
+
+ // {{ isValid, validate
+ /**
+ * Convenience methods that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#isValid(Object)
+ */
+ protected boolean isValid(final Object domainObject) {
+ return getContainer().isValid(domainObject);
+ }
+
+ /**
+ * Convenience methods that delegates to {@link DomainObjectContainer}.
+ *
+ * @see DomainObjectContainer#validate(Object)
+ */
+ protected String validate(final Object domainObject) {
+ return getContainer().validate(domainObject);
+ }
+
+ // }}
+
+ // {{ isPersistent, persist, remove
+ /**
+ * Whether the provided object is persistent.
+ */
+ @Hidden
+ protected boolean isPersistent(final Object domainObject) {
+ return getContainer().isPersistent(domainObject);
+ }
+
+ /**
+ * Save provided object to the persistent object store.
+ *
+ * <p>
+ * If the object {@link #isPersistent(Object) is persistent} already, then
+ * will throw an exception.
+ *
+ * @see #persistIfNotAlready(Object)
+ */
+ @Hidden
+ protected <T> T persist(final T transientDomainObject) {
+ getContainer().persist(transientDomainObject);
+ return transientDomainObject;
+ }
+
+ /**
+ * Saves the object, but only if not already {@link #isPersistent()
+ * persistent}.
+ *
+ * @see #isPersistent()
+ * @see #persist(Object)
+ */
+ @Hidden
+ protected <T> T persistIfNotAlready(final T domainObject) {
+ getContainer().persistIfNotAlready(domainObject);
+ return domainObject;
+ }
+
+ /**
+ * Delete the provided object from the persistent object store.
+ */
+ protected <T> T remove(final T persistentDomainObject) {
+ getContainer().remove(persistentDomainObject);
+ return persistentDomainObject;
+ }
+
+ // }}
+
+ // {{ Error/Warning Methods
+ /**
+ * Display the specified message to the user, in a non-intrusive fashion.
+ */
+ protected void informUser(final String message) {
+ getContainer().informUser(message);
+ }
+
+ /**
+ * Display the specified message as a warning to the user, in a more visible
+ * fashion, but without requiring explicit acknowledgement.
+ */
+ protected void warnUser(final String message) {
+ getContainer().warnUser(message);
+ }
+
+ /**
+ * Display the specified message as an error to the user, ensuring that it
+ * is acknowledged.
+ */
+ protected void raiseError(final String message) {
+ getContainer().raiseError(message);
+ }
+
+ // }}
+
+ // {{ Security Methods
+ protected UserMemento getUser() {
+ return getContainer().getUser();
+ }
+
+ // }}
+
+ // {{ Injected: Container
+ /**
+ * @uml.property name="container"
+ * @uml.associationEnd
+ */
+ private DomainObjectContainer container;
+
+ /**
+ * This field is not persisted, nor displayed to the user.
+ *
+ * @uml.property name="container"
+ */
+ @Hidden
+ protected DomainObjectContainer getContainer() {
+ return this.container;
+ }
+
+ /**
+ * Injected by the application container itself.
+ *
+ * @uml.property name="container"
+ */
+ public final void setContainer(final DomainObjectContainer container) {
+ this.container = container;
+ }
+ // }}
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractDomainObject.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractDomainObject.java b/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractDomainObject.java
new file mode 100644
index 0000000..0d25e4c
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractDomainObject.java
@@ -0,0 +1,120 @@
+/*
+ * 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;
+
+import org.apache.isis.applib.annotation.Hidden;
+
+/**
+ * Convenience super class for all domain objects that wish to interact with the
+ * container.
+ *
+ * <p>
+ * Subclassing is NOT mandatory; the methods in this superclass can be pushed
+ * down into domain objects and another superclass used if required.
+ *
+ * @see org.apache.isis.applib.DomainObjectContainer
+ */
+public abstract class AbstractDomainObject extends AbstractContainedObject {
+
+ // {{ resolve, objectChanged
+ /**
+ * Resolve this object, populating references to other objects.
+ */
+ @Hidden
+ protected void resolve() {
+ getContainer().resolve(this);
+ }
+
+ /**
+ * Resolve this object if the referenced object is still unknown.
+ */
+ @Hidden
+ protected void resolve(final Object referencedObject) {
+ getContainer().resolve(this, referencedObject);
+ }
+
+ /**
+ * Notifies the container that this object has changed, so that it can be
+ * persisted.
+ */
+ @Hidden
+ protected void objectChanged() {
+ getContainer().objectChanged(this);
+ }
+
+ // }}
+
+ // {{ isPersistent, makePersistent (overloads)
+ /**
+ * Whether this object is persistent.
+ *
+ * @deprecated - instead use {@link #isPersistent(Object)}.
+ */
+ @Deprecated
+ @Hidden
+ protected boolean isPersistent() {
+ return isPersistent(this);
+ }
+
+ /**
+ * Save this object to the persistent object store.
+ *
+ * <p>
+ * If the object {@link #isPersistent(Object) is persistent} already, then
+ * will throw an exception.
+ *
+ * @see #persistIfNotAlready(Object)
+ *
+ * @deprecated - instead use {@link #persist(Object)}.
+ */
+ @Deprecated
+ @Hidden
+ protected void makePersistent() {
+ persist(this);
+ }
+
+ /**
+ * Saves the object, but only if not already {@link #isPersistent(Object)
+ * persistent}.
+ *
+ * @see #isPersistent(Object)
+ * @see #persist(Object)
+ *
+ * @deprecated - instead use {@link #persistIfNotAlready(Object)}.
+ */
+ @Deprecated
+ @Hidden
+ protected void makePersistentIfNotAlready() {
+ persistIfNotAlready(this);
+ }
+
+ /**
+ * Delete this object from the persistent object store.
+ *
+ * @deprecated - instead use {@link #remove(Object)}.
+ */
+ @Deprecated
+ @Hidden
+ protected void disposeInstance() {
+ remove(this);
+ }
+ // }}
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractFactoryAndRepository.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractFactoryAndRepository.java b/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractFactoryAndRepository.java
new file mode 100644
index 0000000..bbe3162
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractFactoryAndRepository.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+public abstract class AbstractFactoryAndRepository extends AbstractService {
+
+ // {{ newPersistenceInstance, newInstance
+ /**
+ * Returns a new instance of the specified class that will have been
+ * persisted.
+ *
+ * <p>
+ * This method isn't quite deprecated, but generally consider using
+ * {@link #newTransientInstance(Class)} instead.
+ */
+ protected <T> T newPersistentInstance(final Class<T> ofClass) {
+ return getContainer().newPersistentInstance(ofClass);
+ }
+
+ /**
+ * Returns a new instance of the specified class that has the sane persisted
+ * state as the specified object.
+ *
+ * <p>
+ * This method isn't quite deprecated, but generally consider using
+ * {@link #newTransientInstance(Class)} instead.
+ */
+ protected <T> T newInstance(final Class<T> ofClass, final Object object) {
+ return getContainer().newInstance(ofClass, object);
+ }
+ // }}
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractService.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractService.java b/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractService.java
new file mode 100644
index 0000000..fa65b82
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/AbstractService.java
@@ -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.
+ */
+
+package org.apache.isis.applib;
+
+import org.apache.isis.applib.annotation.Hidden;
+
+public abstract class AbstractService extends AbstractContainedObject {
+
+ @Hidden
+ public String getId() {
+ return getClassName();
+ }
+
+ protected String getClassName() {
+ return getClass().getName();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java b/framework/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
new file mode 100644
index 0000000..2945c71
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
@@ -0,0 +1,48 @@
+/*
+ * 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;
+
+/**
+ * Indicates that a problem has occurred within the application, as opposed to
+ * within a supporting framework or system.
+ */
+public class ApplicationException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+ private Throwable cause;
+
+ public ApplicationException(final String msg) {
+ super(msg);
+ }
+
+ public ApplicationException(final Throwable cause) {
+ this(cause.getMessage());
+ this.cause = cause;
+ }
+
+ public ApplicationException(final String msg, final Throwable cause) {
+ this(msg);
+ this.cause = cause;
+ }
+
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/Defaults.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/Defaults.java b/framework/core/applib/src/main/java/org/apache/isis/applib/Defaults.java
new file mode 100755
index 0000000..eebad2a
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/Defaults.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+import java.util.Calendar;
+
+import org.joda.time.DateTimeZone;
+
+public class Defaults {
+ static {
+ setTimeZone(DateTimeZone.UTC);
+ }
+
+ static DateTimeZone timeZone = DateTimeZone.UTC;
+
+ public static DateTimeZone getTimeZone() {
+ return timeZone;
+ }
+
+ public static void setTimeZone(final DateTimeZone timezone) {
+ timeZone = timezone;
+ calendar = Calendar.getInstance(timezone.toTimeZone());
+ }
+
+ private static Calendar calendar;
+
+ public static Calendar getCalendar() {
+ return calendar;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java b/framework/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java
new file mode 100644
index 0000000..f7b379f
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java
@@ -0,0 +1,431 @@
+/*
+ * 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;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Aggregated;
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.applib.query.Query;
+import org.apache.isis.applib.security.UserMemento;
+
+/**
+ * Represents a container that the domain objects work within. It provides
+ * access to the persistence mechanism and user interface.
+ */
+public interface DomainObjectContainer {
+
+ // ////////////////////////////////////////////////////////////////
+ // titleOf
+ // ////////////////////////////////////////////////////////////////
+
+ String titleOf(Object domainObject);
+
+ // ////////////////////////////////////////////////////////////////
+ // resolve, objectChanged
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Ensure that the specified object is completely loaded into memory.
+ *
+ * <p>
+ * This forces the lazy loading mechanism to load the object if it is not
+ * already loaded.
+ */
+ void resolve(Object domainObject);
+
+ /**
+ * Ensure that the specified object is completely loaded into memory, though
+ * only if the supplied field reference is <tt>null</tt>.
+ *
+ * <p>
+ * This forces the lazy loading mechanism to load the object if it is not
+ * already loaded.
+ */
+ void resolve(Object domainObject, Object field);
+
+ /**
+ * Flags that the specified object's state has changed and its changes need
+ * to be saved.
+ */
+ void objectChanged(Object domainObject);
+
+ // ////////////////////////////////////////////////////////////////
+ // flush, commit
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Flush all changes to the object store.
+ *
+ * <p>
+ * Typically only for use by tests.
+ *
+ * @return <tt>true</tt>
+ */
+ boolean flush();
+
+ /**
+ * Commit all changes to the object store.
+ *
+ * <p>
+ * Typically only for use by tests.
+ */
+ void commit();
+
+ // ////////////////////////////////////////////////////////////////
+ // new{Transient/Persistent}Instance
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Create a new instance of the specified class, but do not persist it.
+ *
+ * <p>
+ * If the type is annotated with {@link Aggregated}, then as per
+ * {@link #newAggregatedInstance(Object, Class)}. Otherwise will be an
+ * aggregate root.
+ *
+ * @see #newPersistentInstance(Class)
+ * @see #newAggregatedInstance(Object, Class)
+ */
+ <T> T newTransientInstance(Class<T> ofType);
+
+ /**
+ * Create a new instance that will be persisted as part of the specified
+ * parent (ie will be a part of a larger aggregate).
+ */
+ <T> T newAggregatedInstance(Object parent, Class<T> ofType);
+
+ /**
+ * Returns a new instance of the specified class that will have been
+ * persisted.
+ */
+ <T> T newPersistentInstance(final Class<T> ofType);
+
+ /**
+ * Returns a new instance of the specified class that has the sane persisted
+ * state as the specified object.
+ */
+ <T> T newInstance(final Class<T> ofType, final Object object);
+
+ // ////////////////////////////////////////////////////////////////
+ // isValid, validate
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Whether the object is in a valid state, that is that none of the
+ * validation of properties, collections and object-level is vetoing.
+ *
+ * @see #validate(Object)
+ */
+ boolean isValid(Object domainObject);
+
+ /**
+ * The reason, if any why the object is in a invalid state
+ *
+ * <p>
+ * Checks the validation of all of the properties, collections and
+ * object-level.
+ *
+ * @see #isValid(Object)
+ */
+ String validate(Object domainObject);
+
+ // ////////////////////////////////////////////////////////////////
+ // isPersistent, persist, remove
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Determines if the specified object is persistent (that it is stored
+ * permanently outside of the virtual machine).
+ */
+ boolean isPersistent(Object domainObject);
+
+ /**
+ * Make the specified transient object persistent.
+ *
+ * <p>
+ * Throws an exception if object is already persistent.
+ *
+ * @see #isPersistent(Object)
+ * @see #persistIfNotAlready(Object)
+ */
+ void persist(Object transientDomainObject);
+
+ /**
+ * Make the specified object persistent if not already.
+ *
+ * <p>
+ * Does nothing otherwise.
+ *
+ * @see #isPersistent(Object)
+ * @see #persist(Object)
+ */
+ void persistIfNotAlready(Object domainObject);
+
+ /**
+ * Removes (deletes) the persisted object.
+ *
+ * @param persistentDomainObject
+ */
+ void remove(Object persistentDomainObject);
+
+ /**
+ * Removes (deletes) the domain object but only if is persistent.
+ *
+ * @param domainObject
+ */
+ void removeIfNotAlready(Object domainObject);
+
+ // ////////////////////////////////////////////////////////////////
+ // info, warn, error
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Make the specified message available to the user. Note this will probably
+ * be displayed in transitory fashion, so is only suitable for useful but
+ * optional information.
+ *
+ * @see #warnUser(String)
+ * @see #raiseError(String)
+ */
+ void informUser(String message);
+
+ /**
+ * Warn the user about a situation with the specified message. The container
+ * should guarantee to display this warning to the user, and will typically
+ * require acknowledgement.
+ *
+ * @see #raiseError(String)
+ * @see #informUser(String)
+ */
+ void warnUser(String message);
+
+ /**
+ * Notify the user of an application error with the specified message. Note
+ * this will probably be displayed in an alarming fashion, so is only
+ * suitable for errors. The user will typically be required to perform
+ * additional steps after the error (eg to inform the helpdesk).
+ *
+ * @see #warnUser(String)
+ * @see #informUser(String)
+ */
+ void raiseError(String message);
+
+ // ////////////////////////////////////////////////////////////////
+ // properties
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Get the configuration property with the specified name.
+ */
+ String getProperty(String name);
+
+ /**
+ * Get the configuration property with the specified name and if it doesn't
+ * exist then return the specified default value.
+ */
+ String getProperty(String name, String defaultValue);
+
+ /**
+ * Get the names of all the available properties.
+ */
+ List<String> getPropertyNames();
+
+ // ////////////////////////////////////////////////////////////////
+ // security
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Get the details about the current user.
+ *
+ * @uml.property name="user"
+ * @uml.associationEnd
+ */
+ UserMemento getUser();
+
+ // ////////////////////////////////////////////////////////////////
+ // allInstances, allMatches, firstMatch, uniqueMatch
+ // ////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns all the instances of the specified type (including subtypes).
+ *
+ * <p>
+ * If there are no instances the list will be empty. This method creates a
+ * new {@link List} object each time it is called so the caller is free to
+ * use or modify the returned {@link List}, but the changes will not be
+ * reflected back to the repository.
+ *
+ * <p>
+ * This method should only be called where the number of instances is known
+ * to be relatively low.
+ */
+ public <T> List<T> allInstances(Class<T> ofType);
+
+ /**
+ * Returns all the instances of the specified type (including subtypes) that
+ * the filter object accepts.
+ *
+ * <p>
+ * If there are no instances the list will be empty. This method creates a
+ * new {@link List} object each time it is called so the caller is free to
+ * use or modify the returned {@link List}, but the changes will not be
+ * reflected back to the repository.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #allMatches(Query)} for production code.
+ */
+ public <T> List<T> allMatches(final Class<T> ofType, final Filter<? super T> filter);
+
+ /**
+ * Returns all the instances of the specified type (including subtypes) that
+ * have the given title.
+ *
+ * <p>
+ * If there are no instances the list will be empty. This method creates a
+ * new {@link List} object each time it is called so the caller is free to
+ * use or modify the returned {@link List}, but the changes will not be
+ * reflected back to the repository.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #allMatches(Query)} for production code.
+ */
+ public <T> List<T> allMatches(Class<T> ofType, String title);
+
+ /**
+ * Returns all the instances of the specified type (including subtypes) that
+ * match the given object: where any property that is set will be tested and
+ * properties that are not set will be ignored.
+ *
+ * <p>
+ * If there are no instances the list will be empty. This method creates a
+ * new {@link List} object each time it is called so the caller is free to
+ * use or modify the returned {@link List}, but the changes will not be
+ * reflected back to the repository.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #allMatches(Query)} for production code.
+ */
+ <T> List<T> allMatches(Class<T> ofType, T pattern);
+
+ /**
+ * Returns all the instances that match the given {@link Query}.
+ *
+ * <p>
+ * If there are no instances the list will be empty. This method creates a
+ * new {@link List} object each time it is called so the caller is free to
+ * use or modify the returned {@link List}, but the changes will not be
+ * reflected back to the repository.
+ */
+ <T> List<T> allMatches(Query<T> query);
+
+ /**
+ * Returns the first instance of the specified type (including subtypes)
+ * that matches the supplied {@link Filter}, or <tt>null</tt> if none.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #firstMatch(Query)} for production code.
+ */
+ public <T> T firstMatch(final Class<T> ofType, final Filter<T> filter);
+
+ /**
+ * Returns the first instance of the specified type (including subtypes)
+ * that matches the supplied title, or <tt>null</tt> if none.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #firstMatch(Query)} for production code.
+ */
+ <T> T firstMatch(Class<T> ofType, String title);
+
+ /**
+ * Returns the first instance of the specified type (including subtypes)
+ * that matches the supplied object as a pattern, or <tt>null</tt> if none.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #firstMatch(Query)} for production code.
+ */
+ <T> T firstMatch(Class<T> ofType, T pattern);
+
+ /**
+ * Returns the first instance that matches the supplied query, or
+ * <tt>null</tt> if none.
+ */
+ <T> T firstMatch(Query<T> query);
+
+ /**
+ * Find the only instance of the specified type (including subtypes) that
+ * has the specified title.
+ *
+ * <p>
+ * If no instance is found then <tt>null</tt> will be return, while if there
+ * is more that one instances a run-time exception will be thrown.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #uniqueMatch(Query)} for production code.
+ */
+ public <T> T uniqueMatch(final Class<T> ofType, final Filter<T> filter);
+
+ /**
+ * Find the only instance of the specified type (including subtypes) that
+ * has the specified title.
+ *
+ * <p>
+ * If no instance is found then <tt>null</tt> will be returned, while if
+ * there is more that one instances a run-time exception will be thrown.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #uniqueMatch(Query)} for production code.
+ */
+ <T> T uniqueMatch(Class<T> ofType, String title);
+
+ /**
+ * Find the only instance of the patterned object type (including subtypes)
+ * that matches the set fields in the pattern object: where any property
+ * that is set will be tested and properties that are not set will be
+ * ignored.
+ *
+ * <p>
+ * If no instance is found then null will be return, while if there is more
+ * that one instances a run-time exception will be thrown.
+ *
+ * <p>
+ * This method is useful during exploration/prototyping, but you may want to
+ * use {@link #uniqueMatch(Query)} for production code.
+ */
+ <T> T uniqueMatch(Class<T> ofType, T pattern);
+
+ /**
+ * Find the only instance that matches the provided query.
+ *
+ * <p>
+ * If no instance is found then null will be return, while if there is more
+ * that one instances a run-time exception will be thrown.
+ */
+ <T> T uniqueMatch(Query<T> query);
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/Identifier.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/Identifier.java b/framework/core/applib/src/main/java/org/apache/isis/applib/Identifier.java
new file mode 100644
index 0000000..258de6f
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/Identifier.java
@@ -0,0 +1,441 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+
+public class Identifier implements Comparable<Identifier> {
+
+ private static final List<String> EMPTY_LIST_OF_STRINGS = Collections.<String> emptyList();
+
+ /**
+ * What type of feature this identifies.
+ */
+ public static enum Type {
+ CLASS, PROPERTY_OR_COLLECTION, ACTION
+ }
+
+ public static enum Depth {
+ CLASS {
+ @Override
+ public String toIdentityString(final Identifier identifier) {
+ return identifier.toClassIdentityString();
+ }
+ },
+ CLASS_MEMBERNAME {
+ @Override
+ public String toIdentityString(final Identifier identifier) {
+ return identifier.toClassAndNameIdentityString();
+ }
+ },
+ CLASS_MEMBERNAME_PARAMETERS {
+ @Override
+ public String toIdentityString(final Identifier identifier) {
+ return identifier.toFullIdentityString();
+ }
+ },
+ MEMBERNAME_ONLY {
+ @Override
+ public String toIdentityString(final Identifier identifier) {
+ return identifier.toNameIdentityString();
+ }
+ },
+ PARAMETERS_ONLY {
+ @Override
+ public String toIdentityString(final Identifier identifier) {
+ return identifier.toParmsIdentityString();
+ }
+ };
+ public abstract String toIdentityString(Identifier identifier);
+ }
+
+ public static Depth CLASS = Depth.CLASS;
+ public static Depth CLASS_MEMBERNAME = Depth.CLASS_MEMBERNAME;
+ public static Depth CLASS_MEMBERNAME_PARAMETERS = Depth.CLASS_MEMBERNAME_PARAMETERS;
+ public static Depth MEMBERNAME_ONLY = Depth.MEMBERNAME_ONLY;
+ public static Depth PARAMETERS_ONLY = Depth.PARAMETERS_ONLY;
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // Factory methods
+ // ///////////////////////////////////////////////////////////////////////////
+
+ public static Identifier classIdentifier(final Class<?> cls) {
+ return classIdentifier(cls.getName());
+ }
+
+ public static Identifier classIdentifier(final String className) {
+ return new Identifier(className, "", EMPTY_LIST_OF_STRINGS, Type.CLASS);
+ }
+
+ public static Identifier propertyOrCollectionIdentifier(final Class<?> declaringClass, final String propertyOrCollectionName) {
+ return propertyOrCollectionIdentifier(declaringClass.getCanonicalName(), propertyOrCollectionName);
+ }
+
+ public static Identifier propertyOrCollectionIdentifier(final String declaringClassName, final String propertyOrCollectionName) {
+ return new Identifier(declaringClassName, propertyOrCollectionName, EMPTY_LIST_OF_STRINGS, Type.PROPERTY_OR_COLLECTION);
+ }
+
+ public static Identifier actionIdentifier(final Class<?> declaringClass, final String actionName, final Class<?>... parameterClasses) {
+ return actionIdentifier(declaringClass.getCanonicalName(), actionName, classNamesOf(parameterClasses));
+ }
+
+ public static Identifier actionIdentifier(final String declaringClassName, final String actionName, final Class<?>... parameterClasses) {
+ return actionIdentifier(declaringClassName, actionName, classNamesOf(parameterClasses));
+ }
+
+ public static Identifier actionIdentifier(final String declaringClassName, final String actionName, final List<String> parameterClassNames) {
+ return new Identifier(declaringClassName, actionName, parameterClassNames, Type.ACTION);
+ }
+
+ /**
+ * Helper, used within contructor chaining
+ */
+ private static List<String> classNamesOf(final Class<?>[] parameterClasses) {
+ if (parameterClasses == null) {
+ return EMPTY_LIST_OF_STRINGS;
+ }
+ final List<String> parameterClassNames = Lists.newArrayList();
+ for (final Class<?> parameterClass : parameterClasses) {
+ parameterClassNames.add(parameterClass.getName());
+ }
+ return parameterClassNames;
+ }
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // Instance variables
+ // ///////////////////////////////////////////////////////////////////////////
+
+ private final String className;
+ private final String memberName;
+ private final List<String> parameterNames;
+ private final Type type;
+ private String identityString;
+
+ /**
+ * Caching of {@link #toString()}, for performance.
+ */
+ private String asString = null;
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // Constructor
+ // ///////////////////////////////////////////////////////////////////////////
+
+ private Identifier(final String className, final String memberName, final List<String> parameterNames, final Type type) {
+ this.className = className;
+ this.memberName = memberName;
+ this.parameterNames = Collections.unmodifiableList(parameterNames);
+ this.type = type;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getClassNaturalName() {
+ final String className = getClassName();
+ final String isolatedName = className.substring(className.lastIndexOf('.') + 1);
+ return NameUtils.naturalName(isolatedName);
+ }
+
+ public String getMemberName() {
+ return memberName;
+ }
+
+ public String getMemberNaturalName() {
+ return NameUtils.naturalName(memberName);
+ }
+
+ public List<String> getMemberParameterNames() {
+ return parameterNames;
+ }
+
+ public List<String> getMemberParameterNaturalNames() {
+ return NameUtils.naturalNames(parameterNames);
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ /**
+ * Convenience method.
+ *
+ * @return
+ */
+ public boolean isPropertyOrCollection() {
+ return type == Type.PROPERTY_OR_COLLECTION;
+ }
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // toXxxString
+ // ///////////////////////////////////////////////////////////////////////////
+
+ public String toIdentityString(final Depth depth) {
+ return depth.toIdentityString(this);
+ }
+
+ public String toClassIdentityString() {
+ return toClassIdentityString(new StringBuilder()).toString();
+ }
+
+ public StringBuilder toClassIdentityString(final StringBuilder buf) {
+ return buf.append(className);
+ }
+
+ public String toNameIdentityString() {
+ return toNameIdentityString(new StringBuilder()).toString();
+ }
+
+ public StringBuilder toNameIdentityString(final StringBuilder buf) {
+ return buf.append(memberName);
+ }
+
+ public String toClassAndNameIdentityString() {
+ return toClassAndNameIdentityString(new StringBuilder()).toString();
+ }
+
+ public StringBuilder toClassAndNameIdentityString(final StringBuilder buf) {
+ final StringBuilder builder = toClassIdentityString(buf).append("#").append(memberName);
+ if (type == Type.ACTION) {
+ builder.append("()");
+ }
+ return builder;
+ }
+
+ public String toParmsIdentityString() {
+ return toParmsIdentityString(new StringBuilder()).toString();
+ }
+
+ public StringBuilder toParmsIdentityString(final StringBuilder buf) {
+ if (type == Type.ACTION) {
+ appendParameterNamesTo(buf);
+ }
+ return buf;
+ }
+
+ private void appendParameterNamesTo(final StringBuilder buf) {
+ buf.append('(');
+ Joiner.on(',').appendTo(buf, parameterNames);
+ buf.append(')');
+ }
+
+ public String toNameParmsIdentityString() {
+ return getMemberName() + toParmsIdentityString();
+ }
+
+ public StringBuilder toNameParmsIdentityString(final StringBuilder buf) {
+ buf.append(getMemberName());
+ toParmsIdentityString(buf);
+ return buf;
+ }
+
+ public String toFullIdentityString() {
+ if (identityString == null) {
+ if (memberName.length() == 0) {
+ identityString = toClassIdentityString();
+ } else {
+ final StringBuilder buf = new StringBuilder();
+ toClassIdentityString(buf).append("#").append(memberName);
+ toParmsIdentityString(buf);
+ identityString = buf.toString();
+ }
+ }
+ return identityString;
+ }
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // compareTo
+ // ///////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public int compareTo(final Identifier o2) {
+ return toString().compareTo(o2.toString());
+ }
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // equals, hashCode
+ // ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * REVIEW: why not just compare the {@link #toString()} representations?
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Identifier)) {
+ return false;
+ }
+ final Identifier other = (Identifier) obj;
+ return equals(other);
+ }
+
+ public boolean equals(final Identifier other) {
+ return equals(other.className, className) && equals(other.memberName, other.memberName) && equals(other.parameterNames, parameterNames);
+ }
+
+ private boolean equals(final String a, final String b) {
+ if (a == b) {
+ return true;
+ }
+
+ return a != null && a.equals(b);
+ }
+
+ private boolean equals(final List<String> a, final List<String> b) {
+ if (a == null && b == null) {
+ return true;
+ } else if (a == null && b != null) {
+ return false;
+ } else if (a != null && b == null) {
+ return false;
+ } else if (a != null && b != null) {
+ return a.equals(b);
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // toString
+ // ///////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public String toString() {
+ if (asString == null) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append(className);
+ buf.append('#');
+ buf.append(memberName);
+ appendParameterNamesTo(buf);
+ asString = buf.toString();
+ }
+ return asString;
+ }
+
+ /**
+ * Factory method.
+ *
+ * @see #toIdentityString(int)
+ */
+ public static Identifier fromIdentityString(final String asString) {
+ if (asString == null) {
+ throw new IllegalArgumentException("expected: non-null identity string");
+ }
+
+ final int indexOfHash = asString.indexOf("#");
+ final int indexOfOpenBracket = asString.indexOf("(");
+ final int indexOfCloseBracket = asString.indexOf(")");
+ final String className = asString.substring(0, indexOfHash == -1 ? asString.length() : indexOfHash);
+ if (indexOfHash == -1 || indexOfHash == (asString.length() - 1)) {
+ return classIdentifier(className);
+ }
+ String name = null;
+ if (indexOfOpenBracket == -1) {
+ name = asString.substring(indexOfHash + 1);
+ return propertyOrCollectionIdentifier(className, name);
+ }
+ final List<String> parmList = new ArrayList<String>();
+ name = asString.substring(indexOfHash + 1, indexOfOpenBracket);
+ final String allParms = asString.substring(indexOfOpenBracket + 1, indexOfCloseBracket).trim();
+ if (allParms.length() > 0) {
+ // use StringTokenizer for .NET compatibility
+ final StringTokenizer tokens = new StringTokenizer(allParms, ",", false);
+ while (tokens.hasMoreTokens()) {
+ final String nextParam = tokens.nextToken();
+ parmList.add(nextParam);
+ }
+ }
+ return actionIdentifier(className, name, parmList);
+ }
+
+}
+
+/**
+ * Not public API, provides a number of utilities to represent formal
+ * {@link Identifier} names more naturally.
+ */
+class NameUtils {
+ private static final char SPACE = ' ';
+
+ /**
+ * Returns a word spaced version of the specified name, so there are spaces
+ * between the words, where each word starts with a capital letter. E.g.,
+ * "NextAvailableDate" is returned as "Next Available Date".
+ */
+ public static String naturalName(final String name) {
+
+ final int length = name.length();
+
+ if (length <= 1) {
+ return name.toUpperCase();// ensure first character is upper case
+ }
+
+ final StringBuffer naturalName = new StringBuffer(length);
+
+ char previousCharacter;
+ char character = Character.toUpperCase(name.charAt(0));// ensure first
+ // character is
+ // upper case
+ naturalName.append(character);
+ char nextCharacter = name.charAt(1);
+
+ for (int pos = 2; pos < length; pos++) {
+ previousCharacter = character;
+ character = nextCharacter;
+ nextCharacter = name.charAt(pos);
+
+ if (previousCharacter != SPACE) {
+ if (Character.isUpperCase(character) && !Character.isUpperCase(previousCharacter)) {
+ naturalName.append(SPACE);
+ }
+ if (Character.isUpperCase(character) && Character.isLowerCase(nextCharacter) && Character.isUpperCase(previousCharacter)) {
+ naturalName.append(SPACE);
+ }
+ if (Character.isDigit(character) && !Character.isDigit(previousCharacter)) {
+ naturalName.append(SPACE);
+ }
+ }
+ naturalName.append(character);
+ }
+ naturalName.append(nextCharacter);
+ return naturalName.toString();
+ }
+
+ public static List<String> naturalNames(final List<String> names) {
+ final List<String> naturalNames = Lists.newArrayList();
+ for (final String name : names) {
+ naturalNames.add(NameUtils.naturalName(name));
+ }
+ return Collections.unmodifiableList(naturalNames);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java b/framework/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java
new file mode 100644
index 0000000..c308ca8
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.applib;
+
+/**
+ * Indicates that the persistence of an object failed.
+ */
+public class PersistFailedException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+ private Throwable cause;
+
+ public PersistFailedException() {
+ super();
+ }
+
+ public PersistFailedException(final String msg) {
+ super(msg);
+ }
+
+ public PersistFailedException(final Throwable cause) {
+ this(cause.getMessage());
+ this.cause = cause;
+ }
+
+ public PersistFailedException(final String msg, final Throwable cause) {
+ this(msg);
+ this.cause = cause;
+ }
+
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java b/framework/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java
new file mode 100644
index 0000000..786fcc2
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.applib;
+
+/**
+ * Indicates that a repository method has failed.
+ */
+public class RepositoryException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+ private Throwable cause;
+
+ public RepositoryException() {
+ super();
+ }
+
+ public RepositoryException(final String msg) {
+ super(msg);
+ }
+
+ public RepositoryException(final Throwable cause) {
+ this(cause.getMessage());
+ this.cause = cause;
+ }
+
+ public RepositoryException(final String msg, final Throwable cause) {
+ this(msg);
+ this.cause = cause;
+ }
+
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/AbstractValueSemanticsProvider.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/AbstractValueSemanticsProvider.java b/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/AbstractValueSemanticsProvider.java
new file mode 100644
index 0000000..bd1ba51
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/AbstractValueSemanticsProvider.java
@@ -0,0 +1,74 @@
+/*
+ * 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.adapters;
+
+public abstract class AbstractValueSemanticsProvider<T> implements ValueSemanticsProvider<T> {
+
+ private boolean immutable;
+ private boolean equalByContent;
+
+ /**
+ * Defaults {@link #isImmutable()} to <tt>true</tt> and
+ * {@link #isEqualByContent()} to <tt>true</tt> also.
+ */
+ public AbstractValueSemanticsProvider() {
+ this(true, true);
+ }
+
+ public AbstractValueSemanticsProvider(final boolean immutable, final boolean equalByContent) {
+ this.immutable = immutable;
+ this.equalByContent = equalByContent;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public EncoderDecoder<T> getEncoderDecoder() {
+ return (EncoderDecoder<T>) (this instanceof EncoderDecoder ? this : null);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Parser<T> getParser() {
+ return (Parser<T>) (this instanceof Parser ? this : null);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public DefaultsProvider<T> getDefaultsProvider() {
+ return (DefaultsProvider<T>) (this instanceof DefaultsProvider ? this : null);
+ }
+
+ /**
+ * Defaults to <tt>true</tt> if no-arg constructor is used.
+ */
+ @Override
+ public boolean isEqualByContent() {
+ return equalByContent;
+ }
+
+ /**
+ * Defaults to <tt>true</tt> if no-arg constructor is used.
+ */
+ @Override
+ public boolean isImmutable() {
+ return immutable;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/DefaultsProvider.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/DefaultsProvider.java b/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/DefaultsProvider.java
new file mode 100644
index 0000000..d73ab08
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/DefaultsProvider.java
@@ -0,0 +1,55 @@
+/*
+ * 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.adapters;
+
+/**
+ * Provides a mechanism for providing a default value for an object.
+ *
+ * <p>
+ * This interface is used in two complementary ways:
+ * <ul>
+ * <li>As one option, it allows objects to take control of their own default
+ * values, by implementing directly. However, the instance is used as a factory
+ * for itself. The framework will instantiate an instance, invoke the
+ * appropriate method method, and use the returned object. The instantiated
+ * instance itself will be discarded.</li>
+ * <li>Alternatively, an implementor of this interface can be nominated in the
+ * {@link org.apache.isis.applib.annotations.Defaulted} annotation, allowing a
+ * class that needs to have a default to indicate where its default comes from.</li>
+ *
+ * <p>
+ * Whatever the class that implements this interface, it must also expose either
+ * a <tt>public</tt> no-arg constructor, or (for implementations that also are
+ * <tt>Facet</tt>s) a <tt>public</tt> constructor that accepts a single
+ * <tt>FacetHolder</tt>. This constructor allows the framework to instantiate
+ * the object reflectively.
+ *
+ * @see Parser
+ * @see EncoderDecoder
+ * @see ValueSemanticsProvider
+ */
+public interface DefaultsProvider<T> {
+
+ /**
+ * The default, if any (as a pojo).
+ */
+ T getDefaultValue();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/EncoderDecoder.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/EncoderDecoder.java b/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/EncoderDecoder.java
new file mode 100644
index 0000000..2c70d24
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/EncoderDecoder.java
@@ -0,0 +1,71 @@
+/*
+ * 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.adapters;
+
+/**
+ * Provides a mechanism for encoding/decoding objects.
+ *
+ * <p>
+ * This interface is used in two complementary ways:
+ * <ul>
+ * <li>As one option, it allows objects to take control of their own
+ * encoding/decoding, by implementing directly. However, the instance is used as
+ * a factory for itself. The framework will instantiate an instance, invoke the
+ * appropriate method method, and use the returned object. The instantiated
+ * instance itself will be discarded.</li>
+ * <li>Alternatively, an implementor of this interface can be nominated in the
+ * {@link org.apache.isis.applib.annotation.Encodable} annotation, allowing a
+ * class that needs to be encodeable to indicate how it can be encoded/decoded.</li>
+ *
+ * <p>
+ * Whatever the class that implements this interface, it must also expose either
+ * a <tt>public</tt> no-arg constructor, or (for implementations that also are
+ * <tt>Facet</tt>s) a <tt>public</tt> constructor that accepts a single
+ * <tt>FacetHolder</tt>. This constructor allows the framework to instantiate
+ * the object reflectively.
+ *
+ * @see Parser
+ * @see DefaultsProvider
+ * @see ValueSemanticsProvider
+ */
+public interface EncoderDecoder<T> {
+
+ /**
+ * Returns the provided object as an encoded string.
+ *
+ * <p>
+ * Even if the class is self-encodeable, note that this method is always
+ * called on a new instance of the object created via the no-arg
+ * constructor. That is, the object shouldn't encode itself, it should
+ * encode the object provided to it.
+ */
+ String toEncodedString(T toEncode);
+
+ /**
+ * Converts an encoded string to an instance of the object.
+ *
+ * <p>
+ * Note that here the implementing class is acting as a factory for itself.
+ *
+ * @see #toEncodedString(% toEncode)
+ */
+ T fromEncodedString(String encodedString);
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/EncodingException.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/EncodingException.java b/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/EncodingException.java
new file mode 100644
index 0000000..625d059
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/adapters/EncodingException.java
@@ -0,0 +1,44 @@
+/*
+ * 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.adapters;
+
+/**
+ * Indicates that encoding or decoding has failed.
+ */
+public class EncodingException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public EncodingException() {
+ super();
+ }
+
+ public EncodingException(final String msg) {
+ super(msg);
+ }
+
+ public EncodingException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+ public EncodingException(final Throwable cause) {
+ super(cause);
+ }
+
+}