Repository: isis
Updated Branches:
  refs/heads/maint-1.13.2 856d1117f -> fa36da4a4


ISIS-1548: extends @Mixin and @DomainObject to accept (mixin)method() 
attribute; updates facets; updates algorithm for inferring mixin name/id based 
on when the name of the method being processed matches this attribute (rather 
than hard-coded "$$" as previously).

Also, supports using "$" (as well as "_") as the separator for 
MixinType_mixinName (ie for nested static classes).

Most of the stuff in ObjectMemberAbstract, plus the three Mixin classes, 
ObjectActionMixedIn, OneToOneAssociationMixedIn, OneToManyAssociationMixedIn.


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

Branch: refs/heads/maint-1.13.2
Commit: 147f4c5d4a4eb7541b06a628b7d666bc5169c4f5
Parents: 856d111
Author: Dan Haywood <d...@haywood-associates.co.uk>
Authored: Thu Dec 1 10:19:52 2016 +0000
Committer: Dan Haywood <d...@haywood-associates.co.uk>
Committed: Thu Dec 1 10:19:52 2016 +0000

----------------------------------------------------------------------
 .../asciidoc/guides/_rgant-DomainObject.adoc    |   6 +
 .../guides/_rgant-DomainObject_mixinMethod.adoc |  40 ++++
 .../src/main/asciidoc/guides/_rgant-Mixin.adoc  |  44 ++--
 .../asciidoc/guides/_rgant-Mixin_method.adoc    |  41 ++++
 .../guides/_ugbtb_decoupling_mixins.adoc        | 231 +++++++++++++------
 .../isis/applib/annotation/DomainObject.java    |  12 +-
 .../apache/isis/applib/annotation/Mixin.java    |  23 ++
 .../facets/object/mixin/MixinFacet.java         |   7 +-
 .../facets/object/mixin/MixinFacetAbstract.java |   8 +-
 .../MixinFacetForDomainObjectAnnotation.java    |   6 +-
 .../mixin/MixinFacetForMixinAnnotation.java     |   6 +-
 .../specloader/specimpl/MixedInMember.java      |  20 +-
 .../specimpl/ObjectActionMixedIn.java           |   4 +-
 .../specimpl/ObjectMemberAbstract.java          |  32 ++-
 .../specimpl/ObjectSpecificationAbstract.java   |  20 +-
 .../specimpl/OneToManyAssociationMixedIn.java   |   4 +-
 .../specimpl/OneToOneAssociationMixedIn.java    |   4 +-
 .../application/integtests/Smoke_IntegTest.java |   6 +-
 .../modules/simple/dom/impl/SimpleObject.java   |  20 +-
 .../tests/SimpleObject_IntegTest.java           |   4 +-
 20 files changed, 367 insertions(+), 171 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject.adoc
----------------------------------------------------------------------
diff --git 
a/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject.adoc 
b/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject.adoc
index 5fa5f91..90f90b2 100644
--- a/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject.adoc
@@ -55,6 +55,12 @@ xref:rgsvc.adoc#_rgsvc_spi_AuditerService[`AuditerService`]
 |whether the object's properties and collections can be edited or not (ie 
whether the instance should be considered to be immutable)
 
 
+|xref:rgant.adoc#_rgant-DomainObject_mixinMethod[`mixinMethod()`]
+|Method name within the mixin
+|(As of `1.13.2-SNAPSHOT`) How to recognize the "reserved" method name, 
meaning that the mixin's own name will be inferred from the mixin type.
+Typical examples are "exec", "execute", "invoke", "apply" and so on.
+
+
 |xref:rgant.adoc#_rgant-DomainObject_nature[`nature()`]
 |`NOT_SPECIFIED`, `JDO_ENTITY`, `EXTERNAL_ENTITY`, `INMEMORY_ENTITY`, `MIXIN`, 
`VIEW_MODEL` (`NOT_SPECIFIED`)
 |whether the domain object logically is an entity (part of the domain layer) 
or is a view model (part of the application layer); or is a mixin.  If an 
entity, indicates how its persistence is managed.

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_mixinMethod.adoc
----------------------------------------------------------------------
diff --git 
a/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_mixinMethod.adoc
 
b/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_mixinMethod.adoc
new file mode 100644
index 0000000..cabce49
--- /dev/null
+++ 
b/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_mixinMethod.adoc
@@ -0,0 +1,40 @@
+[[_rgant-DomainObject_mixinMethod]]
+= `mixinMethod()` (`1.13.2-SNAPSHOT`)
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+
+
+The `mixinMethod()` attribute specifies the name of the method to be treated 
as a "reserved" method name, meaning that the mixin's name should instead be 
inferred from the mixin's type.
+
+For example:
+
+[source,java]
+----
+@DomainObject
+public class Customer {
+
+    @DomainObject(nature=Nature.MIXIN, mixinMethod="execute")
+    public static class _placeOrder {
+
+        Customer customer;
+        public _placeOrder(Customer customer) { this.customer = customer; }
+
+        public Customer execute(Product p, int quantity) { ... }
+        public String disableExecute() { ... }
+        public String validate0Execute() { ... }
+    }
+    ...
+)
+----
+
+This allows all mixins to follow a similar convention, with the name of the 
mixin inferred entirely from its type ("placeOrder").
+
+When invoked programmatically, the code reads:
+
+[source,java]
+----
+mixin(Customer._placeOrder.class, someCustomer).execute(someProduct, 3);
+----
+

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin.adoc 
b/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin.adoc
index 427c783..b0937e7 100644
--- a/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin.adoc
@@ -6,35 +6,29 @@
 
 
 
-The `@Mixin` annotation indicates that the class acts as a mixin, contributing 
behaviour -
-actions, (derived) properties and (derived) collections - to another domain 
object.
-
-For example:
-
-[source,java]
-----
-@Mixin
-public class DocumentHolder_documents {
-    private final DocumentHolder holder;
-    public DocumentHolder_documents(DocumentHolder holder) {
-        this.holder = holder;
-    }
-    @Action(semantics=SemanticsOf.SAFE)
-    @ActionLayout(contributed = Contributed.AS_ASSOCIATION)
-    @CollectionLayout(render = RenderType.EAGERLY)
-    public List<Document> documents() {
-        ...                                                     // <1>
-    }
-}
-----
-<1> for example, using the (non-ASF) 
http://github.com/isisaddons/isis-module-poly[Isis addons' poly] module.
+The `@Mixin` annotation indicates that the class acts as a mixin, contributing 
behaviour - actions, (derived) properties and (derived) collections - to 
another domain object.
 
+Mixins were originally introduced as a means of allowing contributions from 
one module to the types of another module; in such cases the mixin type is 
often an interface type (eg `DocumentHolder`) that might be implemented by 
numerous different concrete types.
+However, mixins are also a convenient mechanism for grouping functionality 
even for a concrete type.
 
-An alternative and equivalent approach is to use the
-xref:rgant.adoc#_rgant-DomainObject_nature[`@DomainObject#nature()`] 
annotation with a nature of `MIXIN`.
+For further discussion on using mixins, see 
xref:ugbtb.adoc#_ugbtb_decoupling_mixins[mixins] in the user guide.
 
+The table below summarizes the annotation's attributes.
+
+.`@Mixin` attributes
+[cols="2,2,4a", options="header"]
+|===
 
-For further discussion on using mixins, see 
xref:ugbtb.adoc#_ugbtb_decoupling_mixins[mixins] in the user guide.
 
+|xref:rgant.adoc#_rgant-Mixin_method[`method()`]
+|Method name within the mixin
+|(As of `1.13.2-SNAPSHOT`) How to recognize the "reserved" method name, 
meaning that the mixin's own name will be inferred from the mixin type.
+Typical examples are "exec", "execute", "invoke", "apply" and so on.
+
+|===
+
+An alternative and equivalent approach is to use the
+xref:rgant.adoc#_rgant-DomainObject_nature[`@DomainObject#nature()`] 
annotation with a nature of `MIXIN`.
 
 
+include::_rgant-Mixin_method.adoc[leveloffset=+1]

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin_method.adoc
----------------------------------------------------------------------
diff --git 
a/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin_method.adoc 
b/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin_method.adoc
new file mode 100644
index 0000000..db8e70b
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgant-Mixin_method.adoc
@@ -0,0 +1,41 @@
+[[_rgant-Mixin_method]]
+= `method()` (`1.13.2-SNAPSHOT`)
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+
+
+The `method()` attribute specifies the name of the method to be treated as a 
"reserved" method name, meaning that the mixin's name should instead be 
inferred from the mixin's type.
+
+For example:
+
+[source,java]
+----
+@DomainObject
+public class Customer {
+
+    @Mixin(method="execute")
+    public static class _placeOrder {
+
+        Customer customer;
+        public _placeOrder(Customer customer) { this.customer = customer; }
+
+        public Customer execute(Product p, int quantity) { ... }
+        public String disableExecute() { ... }
+        public String validate0Execute() { ... }
+    }
+    ...
+)
+----
+
+This allows all mixins to follow a similar convention, with the name of the 
mixin inferred entirely from its type ("placeOrder").
+
+When invoked programmatically, the code reads:
+
+[source,java]
+----
+mixin(Customer._placeOrder.class, someCustomer).execute(someProduct, 3);
+----
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_mixins.adoc
----------------------------------------------------------------------
diff --git 
a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_mixins.adoc 
b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_mixins.adoc
index 2013fc9..499733a 100644
--- a/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_mixins.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/_ugbtb_decoupling_mixins.adoc
@@ -5,129 +5,216 @@
 :_imagesdir: images/
 
 
-A mixin object allows one class to contribute behaviour - actions, (derived) 
properties and
-(derived) collections - to another domain object, either a domain entity or 
view model.
+A mixin object allows one class to contribute behaviour - actions, (derived) 
properties and (derived) collections - to another domain object, either a 
domain entity or view model.
 
-Some programming languages use the term "trait" instead of mixin, and some 
languages (such as AspectJ) define their own
-syntax for defining such constructs.  In Apache Isis a mixin is very similar 
to a domain service, however it also
-defines a single 1-arg constructor that defines the type of the domain objects 
that it contributes to.
+Some programming languages use the term "trait" instead of mixin, and some 
languages (such as AspectJ) define their own syntax for defining such 
constructs.
+In Apache Isis a mixin is very similar to a domain service, however it also 
defines a single 1-arg constructor that defines the type of the domain objects 
that it contributes to.
 
-Why do this?  The main reason is to allow the app to be decoupled, so that it 
doesn't degrade into the proverbial
-link:http://www.laputan.org/mud/mud.html#BigBallOfMud["big ball of mud"].  
Mixins (and contributions) allow dependency
-to be inverted, so that the dependencies between modules can be kept acyclic 
and under control.
+Why do this?
+Two reasons:
 
+* The main reason is to allow the app to be decoupled, so that it doesn't 
degrade into the proverbial 
link:http://www.laputan.org/mud/mud.html#BigBallOfMud["big ball of mud"].
+Mixins (and contributions) allow dependency to be inverted, so that the 
dependencies between modules can be kept acyclic and under control.
 
+* However, there is another reason: mixins are also a convenient mechanism for 
grouping functionality even for a concrete type, helping to rationalize about 
the dependency between the data and the behaviour.
 
-== Example
+Both use cases are discussed below.
 
-This is probably best explained by way of an example.  Suppose we have the 
`Customer` domain object which implements
-a `DocumentHolder` interface:
+Syntactically, a mixin is defined using either the 
xref:rgant.adoc#_rgant_Mixin[`@Mixin`] annotation or using 
xref:rgant.adoc#_rgant_DomainObject_nature[`@DomainObject#nature()`] attribute 
(specifying a nature of `Nature.MIXIN`).
+
+
+== Contributed Collection
+
+The example below shows how to contribute a collection:
 
 [source,java]
 ----
-public class Customer implements DocumentHolder {
-    ...
+@Mixin
+public class DocumentHolderDocuments {
+
+    private final DocumentHolder holder;
+    public DocumentHolderDocuments(DocumentHolder holder) { this.holder = 
holder; }
+
+    @Action(semantics=SemanticsOf.SAFE)                         // <1>
+    @ActionLayout(contributed = Contributed.AS_ASSOCIATION)     // <2>
+    @CollectionLayout(render = RenderType.EAGERLY)
+    public List<Document> documents() {                         // <3>
+        ...
+    }
+    public boolean hideDocuments() { ... }                      // <4>
 }
 ----
+<1> required; actions that have side-effects cannot be contributed as 
collections
+<2> required; otherwise the mixin will default to being rendered as an action
+<3> must accept no arguments.
+    The mixin is a collection rather than a property because the return type 
is a collection, not a scalar.
+<4> supporting methods follow the usual naming conventions.
+    (That said, in the case of collections, because the collection is 
derived/read-only, the only supporting method that is relevant is `hideXxx()`).
+
+The above will result in a contributed collection for all types that 
implement/extend from `DocumentHolder` (so is probably for a mixin across 
modules).
+
+
 
+== Contributed Property
 
-We could then imagine a mixin that would contribute behaviour to list, add and 
remove the ``Document``s for this holder:
+Contributed properties are defined similarly, for example:
 
 [source,java]
 ----
-@Mixin                                                          // <1>
-public class DocumentHolder_documents {
+@Mixin
+public class DocumentHolderMostRecentDocument {
+
     private final DocumentHolder holder;
-    public DocumentHolder_documents(DocumentHolder holder) {    // <2>
-        this.holder = holder;
-    }
-    @Action(semantics=SemanticsOf.SAFE)
-    @ActionLayout(contributed = Contributed.AS_ASSOCIATION)
-    @CollectionLayout(render = RenderType.EAGERLY)
-    public List<Document> documents() {
-        ...                                                     // <3>
-    }
-    @Action(semantics=SemanticsOf.IDEMPOTENT)
-    public DocumentHolder add(Document document) {
-        ...                                                     // <4>
-    }
-    @Action(semantics=SemanticsOf.IDEMPOTENT)
-    public DocumentHolder remove(Document document) {
-        ...                                                     // <5>
+    public DocumentHolderDocuments(DocumentHolder holder) { this.holder = 
holder; }
+
+    @Action(semantics=SemanticsOf.SAFE)                         // <1>
+    @ActionLayout(contributed = Contributed.AS_ASSOCIATION)     // <2>
+    public Document> mostRecentDocument() {                     // <3>
+        ...
     }
+    public boolean hideMostRecentDocument() { ... }             // <4>
 }
 ----
-<1> alternatively can use `@DomainObject(nature=Nature.MIXIN)`
-<2> constructor indicates the type that is contributed to
-<3> implementation could, for example, use the (non-ASF)
-http://github.com/isisaddons/isis-module-poly[Isis addons' poly] module.
-<4> implementation would probably delegate to an injected repository to 
(ultimately) insert data into some table
-<5> implementation would probably delegate to an injected repository to 
(ultimately) delete data from some table
+<1> required; actions that have side-effects cannot be contributed as 
collections
+<2> required; otherwise the mixin will default to being rendered as an action
+<3> must accept no arguments.
+    The mixin is a property rather than a collection because the return type 
is a scalar.
+<4> supporting methods follow the usual naming conventions.
+    (That said, in the case of properties, because the property is 
derived/read-only, the only supporting method that is relevant is `hideXxx()`).
+
+
+== Contributed Action
 
-The above example also omits any supporting methods, eg `hideXxx()`, 
`disableXxx()`, `validateXxx()`, etc.
+Contributed properties are defined similarly, for example:
 
-In the user interface the "documents" collection, the "add" and the "delete" 
actions will appear to be part of
-`Customer`.  In essence the framework constructs a composite UI from the parts 
of multiple objects.
+[source,java]
+----
+@Mixin
+public class DocumentHolderAddDocument {
 
+    private final DocumentHolder holder;
+    public DocumentHolderDocuments(DocumentHolder holder) { this.holder = 
holder; }
 
-[TIP]
-====
-The (non-ASF) http://github.com/incodehq/incode-module-note[Incode note] and
-http://github.com/incodehq/incode-module-commchannel[Incode commchannel] 
modules are real-world examples that use this
-technique throughout.
-====
+    @Action()
+    @ActionLayout(contributed = Contributed.AS_ACTION)          // <1>
+    public Document> addDocument(Document doc) {
+        ...
+    }
+    public boolean hideAddDocument() { ... }                    // <2>
+}
+----
+<1> recommended
+<2> supporting methods follow the usual naming conventions.
 
 
+== Inferred Name
 
-== Contributing a single member
+Where the mixin follows the naming convention `SomeType_mixinName` then the 
method name can be abbreviated to "$$".
+The mixin name is everything after the last '_'.
 
-The mixin can contribute as much or as little behaviour as makes sense.  For 
example, in the example above it might be
-that ``Document``s are created through some other mechanism (eg scanned) and 
are never deleted.  In that case, the
-mixin might be simply:
+For example:
 
 [source,java]
 ----
 @Mixin
 public class DocumentHolder_documents {
-    ..
-    public List<Document> documents() { ... }
-    ...
+
+    private final DocumentHolder holder;
+    public DocumentHolder_documents(DocumentHolder holder) { this.holder = 
holder; }
+
+    @Action(semantics=SemanticsOf.SAFE)
+    @ActionLayout(contributed = Contributed.AS_ASSOCIATION)
+    @CollectionLayout(render = RenderType.EAGERLY)
+    public List<Document> $$() {                                    // <1>
+        ...
+    }
+    public boolean hide$$() { ... }                                 // <2>
 }
 ----
+<1> using "$$" as the reserved method name
+<2> supporting methods as usual
+
+As of `1.13.2-SNAPSHOT`, "$" is also recognized as a separator between the 
mixin type and mixin name.
+This is useful for mixins implemented as nested static types, discussed below.
+
 
+== As Nested Static Classes
 
-For the case where there is only a single member being contributed, the 
special name "__" (that is, two underscores)
-can be used instead.  In this case, the contributee member's name will be 
inferred from the mixin's class name.  If the
-class name itself contains an underscore, then the last part of the class name 
will be used.
+As noted in the introduction, while mixins were originally introduced as a 
means of allowing contributions from one module to the types of another module, 
they are also a convenient mechanism for grouping functionality/behaviour 
against a concrete type.
+All the methods and supporting methods end up in a single construct, and the 
dependency between that functionality and the rest of the object is made more 
explicit.
 
-Thus, for a mixin whose class name is `DocumentHolder_documents`, the 
effective member name is `documents`.  We could
-therefore rewrite the mixin as:
+When using mixins in this fashion, it is idiomatic to write the mixin as a 
nested static class, using the naming convention described above to reduce 
duplication.
+
+For example:
 
 [source,java]
 ----
-@Mixin
-public class DocumentHolder_documents {
-    ..
-    public List<Document> __() { ... }
-    ...
+public class Customer {
+
+    @Mixin
+    public static class _placeOrder {                                          
  // <1>
+
+        private final Customer customer;
+        public documents(Customer customer) { this.customer = customer; }      
 // <2>
+
+        @Action
+        @ActionLayout(contributed = Contributed.AS_ACTION)
+        public List<Order> $$(Product p, int quantity) {                       
 // <3>
+            ...
+        }
+        public boolean hide$$() { ... }                                        
 // <4>
+        public String validate0$$(Product p) { ...  }
+    }
 }
 ----
+<1> must start with an "_" (the effective name of the class is 
`Customer$_placeOrder`.
+<2> typically contributed to concrete class
+<3> using the "$$" reserved name
+<4> supporting methods as usual
+
 
-The benefit of this is marginal unless there are supporting methods, in which 
case the removal of boilerplate is welcome:
+As of `1.13.2-SNAPSHOT`, the leading "_" can be omitted because "$" is also 
recognized as an identifier.
+Moreover, the mixin class can be capitalized if desired.
+Thus:
 
 [source,java]
 ----
-@Mixin
-public class DocumentHolder_documents {
-    ..
-    public List<Document> __() { ... }
-    public boolean hide__() { ... }
-    public String disable__() { ... }
-    ...
+public class Customer {
+
+    @Mixin
+    public static class PlaceOrder {                                           
 // <1>
+
+        private final Customer customer;
+        public documents(Customer customer) { this.customer = customer; }      
 // <2>
+
+        @Action
+        @ActionLayout(contributed = Contributed.AS_ACTION)
+        public List<Order> $$(Product p, int quantity) {                       
 // <3>
+            ...
+        }
+        public boolean hide$$() { ... }                                        
 // <4>
+        public String validate0$$(Product p) { ...  }
+    }
 }
 ----
 
 
+In other words, all of the following are allowed (in `1.13.2-SNAPSHOT`):
+
+* `public static class Documents { ... }`
+* `public static class documents { ... }`
+* `public static class _Documents { ... }`
+* `public static class _documents { ... }`
+
+(As of `1.13.2-SNAPSHOT`), the reserved method name "$$" can also be changed 
using xref:rgant.adoc#_rgant_Mixin_method[`@Mixin#method()`] or 
xref:rgant.adoc#_rgant_DomainObject_mixinMethod[`@DomainObject#mixinMethod()`].
+
+
+
+
+
+
+
+
 == Programmatic usage
 
 When a domain object is rendered, the framework will automatically instantiate 
all required mixins and delegate to them

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObject.java
----------------------------------------------------------------------
diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObject.java 
b/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObject.java
index 5f68984..cf0cd58 100644
--- 
a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObject.java
+++ 
b/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObject.java
@@ -156,6 +156,16 @@ public @interface DomainObject {
     Nature nature() default Nature.NOT_SPECIFIED;
 
 
+
+    /**
+     * Equivalent to {@link Mixin#method()}.
+     *
+     * <p>
+     *     Applicable only if {@link #nature()} is {@link Nature#MIXIN}.
+     * </p>
+     */
+    String mixinMethod() default Mixin.DEFAULT_METHOD_NAME;
+
     // //////////////////////////////////////
 
 
@@ -236,6 +246,4 @@ public @interface DomainObject {
      * </p>
      */
     Class<? extends ObjectRemovingEvent<?>> removingLifecycleEvent() default 
ObjectRemovingEvent.Default.class;
-
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/applib/src/main/java/org/apache/isis/applib/annotation/Mixin.java
----------------------------------------------------------------------
diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/annotation/Mixin.java 
b/core/applib/src/main/java/org/apache/isis/applib/annotation/Mixin.java
index 7f4f646..7392063 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Mixin.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Mixin.java
@@ -34,5 +34,28 @@ import java.lang.annotation.Target;
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Mixin {
 
+    /**
+     * The default of {@link Mixin#method()}).
+     */
+    String DEFAULT_METHOD_NAME = "$$";
+
+    /**
+     * Specifies the name of the verb to use within the mixin, eg "exec", 
"invoke", "apply" and so on,
+     *
+     * <p>
+     *     This makes it easier to avoid silly spelling mistakes in supporting 
methods, with the name of the member
+     *     in essence specified in only just one place, namely the mixin 
class' name.
+     * </p>
+     * 
+     * <p>
+     *     If not specified, then the default value {@link 
#DEFAULT_METHOD_NAME} is used instead.
+     * </p>
+     *
+     * <p>
+     *     Remarks: originally intended to use a single (or perhaps two) 
underscore, however these may will not be
+     *     valid identifiers after Java 8.
+     * </p>
+     */
+    String method() default DEFAULT_METHOD_NAME;
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
index bce8da3..4bce13b 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
@@ -22,7 +22,7 @@ package org.apache.isis.core.metamodel.facets.object.mixin;
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.Nature;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.SingleValueFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 /**
@@ -31,7 +31,7 @@ import 
org.apache.isis.core.metamodel.spec.ObjectSpecification;
  * {@link DomainObject#nature()} of {@link Nature#MIXIN}) and which have a 
1-arg constructor accepting an object
  * (being the object this is a mix-in for).
  */
-public interface MixinFacet extends Facet {
+public interface MixinFacet extends SingleValueFacet<String> {
 
     boolean isMixinFor(Class<?> candidateDomainType);
 
@@ -49,4 +49,7 @@ public interface MixinFacet extends Facet {
      * Returns the mixin around the provided domain object
      */
     Object instantiate(Object domainPojo);
+
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
index 09fc8a0..b719f39 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
@@ -28,10 +28,10 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
+import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
 
-public abstract class MixinFacetAbstract extends MarkerFacetAbstract 
implements MixinFacet {
+public abstract class MixinFacetAbstract extends 
SingleValueFacetAbstract<String> implements MixinFacet {
 
     private final Class<?> mixinType;
     private final Class<?> constructorType;
@@ -43,10 +43,10 @@ public abstract class MixinFacetAbstract extends 
MarkerFacetAbstract implements
 
     public MixinFacetAbstract(
             final Class<?> mixinType,
-            final Class<?> constructorType,
+            final String value, final Class<?> constructorType,
             final FacetHolder holder,
             final ServicesInjector servicesInjector) {
-        super(type(), holder);
+        super(type(), value, holder);
         this.mixinType = mixinType;
         this.constructorType = constructorType;
         this.servicesInjector = servicesInjector;

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForDomainObjectAnnotation.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForDomainObjectAnnotation.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForDomainObjectAnnotation.java
index aac7d79..041d57a 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForDomainObjectAnnotation.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForDomainObjectAnnotation.java
@@ -35,10 +35,10 @@ public class MixinFacetForDomainObjectAnnotation extends 
MixinFacetAbstract {
 
     private MixinFacetForDomainObjectAnnotation(
             final Class<?> mixinType,
-            final Class<?> constructorType,
+            final String value, final Class<?> constructorType,
             final FacetHolder holder,
             final ServicesInjector servicesInjector) {
-        super(mixinType, constructorType, holder, servicesInjector);
+        super(mixinType, value, constructorType, holder, servicesInjector);
     }
 
     public static MixinFacet create(
@@ -58,7 +58,7 @@ public class MixinFacetForDomainObjectAnnotation extends 
MixinFacetAbstract {
                 continue;
             }
             final Class<?> constructorType = constructorTypes[0];
-            return new MixinFacetForDomainObjectAnnotation(candidateMixinType, 
constructorType, facetHolder,
+            return new MixinFacetForDomainObjectAnnotation(candidateMixinType, 
domainObject.mixinMethod(), constructorType, facetHolder,
                     servicesInjector);
         }
         return null;

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForMixinAnnotation.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForMixinAnnotation.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForMixinAnnotation.java
index a575ddf..d042eed 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForMixinAnnotation.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetForMixinAnnotation.java
@@ -34,10 +34,10 @@ public class MixinFacetForMixinAnnotation extends 
MixinFacetAbstract {
 
     private MixinFacetForMixinAnnotation(
             final Class<?> mixinType,
-            final Class<?> constructorType,
+            final String value, final Class<?> constructorType,
             final FacetHolder holder,
             final ServicesInjector servicesInjector) {
-        super(mixinType, constructorType, holder, servicesInjector);
+        super(mixinType, value, constructorType, holder, servicesInjector);
     }
 
     public static MixinFacet create(
@@ -54,7 +54,7 @@ public class MixinFacetForMixinAnnotation extends 
MixinFacetAbstract {
                 continue;
             }
             final Class<?> constructorType = constructorTypes[0];
-            return new MixinFacetForMixinAnnotation(candidateMixinType, 
constructorType, facetHolder, servicesInjector);
+            return new MixinFacetForMixinAnnotation(candidateMixinType, 
mixin.method(), constructorType, facetHolder, servicesInjector);
         }
         return null;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/MixedInMember.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/MixedInMember.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/MixedInMember.java
index 7b8faf4..46795b1 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/MixedInMember.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/MixedInMember.java
@@ -16,7 +16,7 @@
  */
 package org.apache.isis.core.metamodel.specloader.specimpl;
 
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.applib.annotation.Mixin;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 
 /**
@@ -25,23 +25,7 @@ import 
org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 public interface MixedInMember extends ObjectMember {
 
     /**
-     * If the mixin uses a method of precisely this name, then the 
corresponding {@link ObjectMember#getName() name} and
-     * {@link ObjectMember#getId() id} will instead be inferred from the mixin 
class' {@link ObjectSpecification#getShortIdentifier() name}.
-     *
-     * <p>
-     *     This makes it easier to avoid silly spelling mistakes in supporting 
methods, with the name of the member
-     *     in essence specified in only just one place, namely the mixin 
class' name.
-     * </p>
-     *
-     * <p>
-     *     Remarks: originally intended to use a single (or perhaps two) 
underscore, however these may not be valid
-     *     identifiers after Java 8.
-     * </p>
-     */
-    public static final String DEFAULT_MEMBER_NAME = "$$";
-
-    /**
-     * The id if it was originally {@link #DEFAULT_MEMBER_NAME the default 
member name}.
+     * The id if it was originally {@link Mixin#DEFAULT_METHOD_NAME the 
default member name}.
      */
     String getOriginalId();
 

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
index 96bd8ea..752ffaa 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
@@ -18,7 +18,6 @@ package org.apache.isis.core.metamodel.specloader.specimpl;
 
 import java.util.List;
 
-import com.google.common.base.Objects;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 
@@ -72,6 +71,7 @@ public class ObjectActionMixedIn extends ObjectActionDefault 
implements MixedInM
 
     public ObjectActionMixedIn(
             final Class<?> mixinType,
+            final String mixinMethodName,
             final ObjectActionDefault mixinAction,
             final ObjectSpecification mixedInType,
             final ServicesInjector objectMemberDependencies) {
@@ -87,7 +87,7 @@ public class ObjectActionMixedIn extends ObjectActionDefault 
implements MixedInM
         // adjust name if necessary
         final String name = getName();
 
-        if(Strings.isNullOrEmpty(name) || Objects.equal(name, 
DEFAULT_MEMBER_NAME)) {
+        if(Strings.isNullOrEmpty(name) || 
name.equalsIgnoreCase(mixinMethodName)) {
             String memberName = determineNameFrom(mixinAction);
             FacetUtil.addFacet(new NamedFacetInferred(memberName, 
facetHolder));
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
index d45479f..3d7dab1 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
@@ -20,8 +20,7 @@
 package org.apache.isis.core.metamodel.specloader.specimpl;
 
 import java.util.List;
-
-import com.google.common.base.Objects;
+import java.util.Objects;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.When;
@@ -335,7 +334,7 @@ public abstract class ObjectMemberAbstract implements 
ObjectMember {
     }
 
     static String determineIdFrom(final ObjectActionDefault mixinAction) {
-        final String id = compress(suffix(mixinAction));
+        final String id = 
StringExtensions.asCamelLowerFirst(compress(suffix(mixinAction)));
         return id;
     }
 
@@ -348,17 +347,26 @@ public abstract class ObjectMemberAbstract implements 
ObjectMember {
     }
 
     static String suffix(final String singularName) {
-        if (singularName.endsWith("_")) {
-            if (Objects.equal(singularName, "_")) {
-                return singularName;
-            }
-            return singularName;
+        final String deriveFromUnderscore = derive(singularName, "_");
+        if(!Objects.equals(singularName, deriveFromUnderscore)) {
+            return deriveFromUnderscore;
         }
-        final int indexOfUnderscore = singularName.lastIndexOf('_');
-        if (indexOfUnderscore == -1) {
-            return singularName;
+        final String deriveFromDollar = derive(singularName, "$");
+        if(!Objects.equals(singularName, deriveFromDollar)) {
+            return deriveFromDollar;
         }
-        return singularName.substring(indexOfUnderscore + 1);
+        return singularName;
+    }
+
+    private static String derive(final String singularName, final String 
separator) {
+        final int indexOfSeparator = singularName.lastIndexOf(separator);
+        return occursNotAtEnd(singularName, indexOfSeparator)
+                ? singularName.substring(indexOfSeparator + 1)
+                : singularName;
+    }
+
+    private static boolean occursNotAtEnd(final String singularName, final int 
indexOfUnderscore) {
+        return indexOfUnderscore != -1 && indexOfUnderscore != 
singularName.length() - 1;
     }
 
     //endregion

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index 52cc112..808c3f0 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -994,7 +994,7 @@ public abstract class ObjectSpecificationAbstract extends 
FacetHolderImpl implem
                                 return true;
                             }
                         }),
-                        createMixedInAssociationFunctor(this, mixinType)
+                        createMixedInAssociationFunctor(this, mixinType, 
mixinFacet.value())
                 ));
 
         toAppendTo.addAll(mixedInAssociations);
@@ -1006,7 +1006,8 @@ public abstract class ObjectSpecificationAbstract extends 
FacetHolderImpl implem
 
     private Function<ObjectActionDefault, ObjectAssociation> 
createMixedInAssociationFunctor(
             final ObjectSpecification mixedInType,
-            final Class<?> mixinType) {
+            final Class<?> mixinType,
+            final String mixinMethodName) {
         return new Function<ObjectActionDefault, ObjectAssociation>(){
             @Override
             public ObjectAssociation apply(final ObjectActionDefault 
mixinAction) {
@@ -1020,10 +1021,10 @@ public abstract class ObjectSpecificationAbstract 
extends FacetHolderImpl implem
                 final ObjectSpecification returnType = 
mixinAction.getReturnType();
                 if (returnType.isNotCollection()) {
                     return new OneToOneAssociationMixedIn(
-                            mixinAction, mixedInType, mixinType, 
servicesInjector);
+                            mixinAction, mixedInType, mixinType, 
mixinMethodName, servicesInjector);
                 } else {
                     return new OneToManyAssociationMixedIn(
-                            mixinAction, mixedInType, mixinType, 
servicesInjector);
+                            mixinAction, mixedInType, mixinType, 
mixinMethodName, servicesInjector);
                 }
             }
         };
@@ -1137,11 +1138,12 @@ public abstract class ObjectSpecificationAbstract 
extends FacetHolderImpl implem
     private void addMixedInActionsIfAny(
             final Class<?> mixinType,
             final List<ObjectAction> mixedInActionsToAppendTo) {
-        final ObjectSpecification specification = 
getSpecificationLoader().loadSpecification(mixinType);
-        if (specification == this) {
+
+        final ObjectSpecification mixinSpec = 
getSpecificationLoader().loadSpecification(mixinType);
+        if (mixinSpec == this) {
             return;
         }
-        final MixinFacet mixinFacet = specification.getFacet(MixinFacet.class);
+        final MixinFacet mixinFacet = mixinSpec.getFacet(MixinFacet.class);
         if(mixinFacet == null) {
             // this shouldn't happen; perhaps it would be more correct to 
throw an exception?
             return;
@@ -1151,7 +1153,7 @@ public abstract class ObjectSpecificationAbstract extends 
FacetHolderImpl implem
         }
 
         final List<ObjectAction> actions = Lists.newArrayList();
-        final List<ObjectAction> mixinActions = 
specification.getObjectActions(ActionType.ALL, Contributed.INCLUDED, Filters
+        final List<ObjectAction> mixinActions = 
mixinSpec.getObjectActions(ActionType.ALL, Contributed.INCLUDED, Filters
                 .<ObjectAction>any());
         for (final ObjectAction mixinTypeAction : mixinActions) {
             if (isAlwaysHidden(mixinTypeAction)) {
@@ -1167,7 +1169,7 @@ public abstract class ObjectSpecificationAbstract extends 
FacetHolderImpl implem
             }
 
             ObjectActionMixedIn mixedInAction =
-                    new ObjectActionMixedIn(mixinType, mixinAction, this, 
servicesInjector);
+                    new ObjectActionMixedIn(mixinType, mixinFacet.value(), 
mixinAction, this, servicesInjector);
             facetProcessor.processMemberOrder(metadataProperties, 
mixedInAction);
             actions.add(mixedInAction);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java
index 0e66c97..d82e7d5 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java
@@ -18,7 +18,6 @@ package org.apache.isis.core.metamodel.specloader.specimpl;
 
 import java.util.List;
 
-import com.google.common.base.Objects;
 import com.google.common.base.Strings;
 
 import org.apache.isis.applib.Identifier;
@@ -87,6 +86,7 @@ public class OneToManyAssociationMixedIn extends 
OneToManyAssociationDefault imp
             final ObjectActionDefault mixinAction,
             final ObjectSpecification mixedInType,
             final Class<?> mixinType,
+            final String mixinMethodName,
             final ServicesInjector servicesInjector) {
         super(mixinAction.getFacetedMethod(),
                 typeOfSpec(mixinAction, servicesInjector),
@@ -120,7 +120,7 @@ public class OneToManyAssociationMixedIn extends 
OneToManyAssociationDefault imp
         // adjust name if necessary
         final String name = getName();
 
-        if(Strings.isNullOrEmpty(name) || Objects.equal(name, 
DEFAULT_MEMBER_NAME)) {
+        if(Strings.isNullOrEmpty(name) || 
name.equalsIgnoreCase(mixinMethodName)) {
             String memberName = 
ObjectActionMixedIn.determineNameFrom(mixinAction);
             FacetUtil.addFacet(new NamedFacetInferred(memberName, 
facetHolder));
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
index e48a44d..668465e 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
@@ -18,7 +18,6 @@ package org.apache.isis.core.metamodel.specloader.specimpl;
 
 import java.util.List;
 
-import com.google.common.base.Objects;
 import com.google.common.base.Strings;
 
 import org.apache.isis.applib.Identifier;
@@ -72,6 +71,7 @@ public class OneToOneAssociationMixedIn extends 
OneToOneAssociationDefault imple
             final ObjectActionDefault mixinAction,
             final ObjectSpecification mixedInType,
             final Class<?> mixinType,
+            final String mixinMethodName,
             final ServicesInjector servicesInjector) {
         super(mixinAction.getFacetedMethod(), mixinAction.getReturnType(), 
servicesInjector);
 
@@ -99,7 +99,7 @@ public class OneToOneAssociationMixedIn extends 
OneToOneAssociationDefault imple
         // adjust name if necessary
         final String name = getName();
 
-        if(Strings.isNullOrEmpty(name) || Objects.equal(name, 
DEFAULT_MEMBER_NAME)) {
+        if(Strings.isNullOrEmpty(name) || 
name.equalsIgnoreCase(mixinMethodName)) {
             String memberName = 
ObjectActionMixedIn.determineNameFrom(mixinAction);
             FacetUtil.addFacet(new NamedFacetInferred(memberName, 
facetHolder));
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/example/application/simpleapp/application/src/test/java/domainapp/application/integtests/Smoke_IntegTest.java
----------------------------------------------------------------------
diff --git 
a/example/application/simpleapp/application/src/test/java/domainapp/application/integtests/Smoke_IntegTest.java
 
b/example/application/simpleapp/application/src/test/java/domainapp/application/integtests/Smoke_IntegTest.java
index fb9c12c..4b514e8 100644
--- 
a/example/application/simpleapp/application/src/test/java/domainapp/application/integtests/Smoke_IntegTest.java
+++ 
b/example/application/simpleapp/application/src/test/java/domainapp/application/integtests/Smoke_IntegTest.java
@@ -42,7 +42,7 @@ public class Smoke_IntegTest extends 
DomainAppIntegTestAbstract {
     SimpleObjectMenu menu;
 
     @Test
-    public void create_() throws Exception {
+    public void create() throws Exception {
 
         // given
         DomainAppTearDown fs = new DomainAppTearDown();
@@ -81,7 +81,7 @@ public class Smoke_IntegTest extends 
DomainAppIntegTestAbstract {
 
 
         // when
-        wrap(mixin(SimpleObject._updateName.class, fred)).$$("Freddy");
+        wrap(mixin(SimpleObject.updateName.class, fred)).exec("Freddy");
         transactionService.flushTransaction();
 
         // then
@@ -97,7 +97,7 @@ public class Smoke_IntegTest extends 
DomainAppIntegTestAbstract {
 
 
         // when
-        wrap(mixin(SimpleObject._delete.class, fred)).$$();
+        wrap(mixin(SimpleObject.delete.class, fred)).exec();
         transactionService.flushTransaction();
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
----------------------------------------------------------------------
diff --git 
a/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
 
b/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
index da27e46..23b3c54 100644
--- 
a/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
+++ 
b/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
@@ -140,15 +140,15 @@ public class SimpleObject implements 
Comparable<SimpleObject> {
     //endregion
 
     //region > updateName (action)
-    @Mixin
-    public static class _updateName {
+    @Mixin(method = "exec")
+    public static class updateName {
 
         public static class ActionDomainEvent extends 
SimpleModuleDomSubmodule.ActionDomainEvent<SimpleObject> {
         }
 
         private final SimpleObject simpleObject;
 
-        public _updateName(final SimpleObject simpleObject) {
+        public updateName(final SimpleObject simpleObject) {
             this.simpleObject = simpleObject;
         }
 
@@ -161,7 +161,7 @@ public class SimpleObject implements 
Comparable<SimpleObject> {
         @ActionLayout(
                 contributed = Contributed.AS_ACTION
         )
-        public SimpleObject $$(
+        public SimpleObject exec(
                 @Parameter(maxLength = SimpleObject.NameType.Meta.MAX_LEN)
                 @ParameterLayout(named = "Name")
                 final String name) {
@@ -169,11 +169,11 @@ public class SimpleObject implements 
Comparable<SimpleObject> {
             return simpleObject;
         }
 
-        public String default0$$() {
+        public String default0Exec() {
             return simpleObject.getName();
         }
 
-        public TranslatableString validate0$$(final String name) {
+        public TranslatableString validate0Exec(final String name) {
             return name != null && name.contains("!") ? 
TranslatableString.tr("Exclamation mark is not allowed") : null;
         }
 
@@ -181,14 +181,14 @@ public class SimpleObject implements 
Comparable<SimpleObject> {
     //endregion
 
     //region > delete (action)
-    @Mixin
-    public static class _delete {
+    @Mixin(method = "exec")
+    public static class delete {
 
         public static class ActionDomainEvent extends 
SimpleModuleDomSubmodule.ActionDomainEvent<SimpleObject> {
         }
 
         private final SimpleObject simpleObject;
-        public _delete(final SimpleObject simpleObject) {
+        public delete(final SimpleObject simpleObject) {
             this.simpleObject = simpleObject;
         }
 
@@ -199,7 +199,7 @@ public class SimpleObject implements 
Comparable<SimpleObject> {
         @ActionLayout(
                 contributed = Contributed.AS_ACTION
         )
-        public void $$() {
+        public void exec() {
             final String title = titleService.titleOf(simpleObject);
             messageService.informUser(String.format("'%s' deleted", title));
             repositoryService.remove(simpleObject);

http://git-wip-us.apache.org/repos/asf/isis/blob/147f4c5d/example/application/simpleapp/module-simple/src/test/java/domainapp/modules/simple/integtests/tests/SimpleObject_IntegTest.java
----------------------------------------------------------------------
diff --git 
a/example/application/simpleapp/module-simple/src/test/java/domainapp/modules/simple/integtests/tests/SimpleObject_IntegTest.java
 
b/example/application/simpleapp/module-simple/src/test/java/domainapp/modules/simple/integtests/tests/SimpleObject_IntegTest.java
index 29d0bba..f6ac63e 100644
--- 
a/example/application/simpleapp/module-simple/src/test/java/domainapp/modules/simple/integtests/tests/SimpleObject_IntegTest.java
+++ 
b/example/application/simpleapp/module-simple/src/test/java/domainapp/modules/simple/integtests/tests/SimpleObject_IntegTest.java
@@ -87,7 +87,7 @@ public class SimpleObject_IntegTest extends 
SimpleModuleIntegTestAbstract {
         public void can_be_updated_directly() throws Exception {
 
             // when
-            wrap(mixin(SimpleObject._updateName.class, simpleObject)).$$("new 
name");
+            wrap(mixin(SimpleObject.updateName.class, simpleObject)).exec("new 
name");
             transactionService.nextTransaction();
 
             // then
@@ -102,7 +102,7 @@ public class SimpleObject_IntegTest extends 
SimpleModuleIntegTestAbstract {
             expectedExceptions.expectMessage("Exclamation mark is not 
allowed");
 
             // when
-            wrap(mixin(SimpleObject._updateName.class, simpleObject)).$$("new 
name!");
+            wrap(mixin(SimpleObject.updateName.class, simpleObject)).exec("new 
name!");
         }
     }
 

Reply via email to