This is an automated email from the ASF dual-hosted git repository. danhaywood pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 6e1bd09f5159765cd829c6e816b2dadc68534123 Author: danhaywood <[email protected]> AuthorDate: Sun Apr 2 19:08:46 2023 +0100 CAUSEWAY-2485: wip, @DomainObject#xxxDomainEvent --- .../ActionDomainEventPage-description.adoc | 2 +- .../ActionDomainEventPage_controlStrategy.java | 1 + .../ActionDomainEventPage_updateText.java | 9 +- ...tionDomainEventPage_updateTextNotAnnotated.java | 10 +- .../collections/Collection/CollectionMenu.java | 2 - .../domainEvent/CollectionDomainEventPage.java | 1 - .../child/CollectionDomainEventChildVm.java | 6 +- .../child/CollectionDomainEventChildVm.layout.xml | 18 +-- .../objects/DomainObject/DomainObjectMenu.java | 7 +- .../DomainObjectXxxDomainEventControlStrategy.java | 166 +++++++++++++++++++++ ...mainObjectXxxDomainEventControlSubscriber.java} | 33 ++-- ...DomainObjectXxxDomainEventPage-description.adoc | 124 ++++++++++----- .../DomainObjectXxxDomainEventPage.java | 77 ++++++++-- .../DomainObjectXxxDomainEventPage.layout.xml | 33 +++- ...tXxxDomainEventPage_changeControlStrategy.java} | 39 ++--- ...nObjectXxxDomainEventPage_controlStrategy.java} | 15 +- ...nObjectXxxDomainEventPage_updateTextMixin.java} | 21 +-- ...ainObjectXxxDomainEventChildVm-description.adoc | 4 + .../DomainObjectXxxDomainEventChildVm.java} | 36 +++-- .../DomainObjectXxxDomainEventChildVm.layout.xml} | 13 +- 20 files changed, 462 insertions(+), 155 deletions(-) diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage-description.adoc index 561ed4096f..7c6d8b547e 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage-description.adoc +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage-description.adoc @@ -7,7 +7,7 @@ Domain service subscribers can influence this interaction, either by: * disabling the action * validating arguments of the action invocation * performing arbitrary operations before the action has been invoked (including modifying the argument values to be used) -* performing arbitrary operations after the action has been modified (including changing the apparent return value of the action) +* performing arbitrary operations after the action has been invoked (including changing the apparent return value of the action) The link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/Action.html#domainevent[@Action#actionDomainEvent] element specifies the class to be emitted; the class specified must be a subclass of the abstract link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/events/domain/ActionDomainEvent.html[ActionDomainEvent] class. diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java index b7825b38fe..1bd693de15 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java @@ -32,6 +32,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class ActionDomainEventPage_controlStrategy { + @SuppressWarnings("unused") private final ActionDomainEventPage page; public ActionDomainEventControlStrategy prop() { diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateText.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateText.java index a74663ce36..119f510e14 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateText.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateText.java @@ -19,7 +19,6 @@ package demoapp.dom.domain.actions.Action.domainEvent; import org.apache.causeway.applib.annotation.Action; -import org.apache.causeway.applib.annotation.ActionLayout; import org.apache.causeway.applib.annotation.MemberSupport; import org.apache.causeway.applib.events.domain.ActionDomainEvent; @@ -36,14 +35,14 @@ public class ActionDomainEventPage_updateText { // ... //end::class[] - private final ActionDomainEventPage actionDomainEventVm; + private final ActionDomainEventPage page; @MemberSupport public ActionDomainEventPage act(final String text) { - actionDomainEventVm.setText(text); - return actionDomainEventVm; + page.setText(text); + return page; } @MemberSupport public String default0Act() { - return actionDomainEventVm.getText(); + return page.getText(); } //tag::class[] } diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateTextNotAnnotated.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateTextNotAnnotated.java index 03c15987ae..67d34c5f06 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateTextNotAnnotated.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateTextNotAnnotated.java @@ -21,9 +21,7 @@ package demoapp.dom.domain.actions.Action.domainEvent; import lombok.RequiredArgsConstructor; import org.apache.causeway.applib.annotation.Action; -import org.apache.causeway.applib.annotation.ActionLayout; import org.apache.causeway.applib.annotation.MemberSupport; -import org.apache.causeway.applib.events.domain.ActionDomainEvent; //tag::class[] @@ -33,14 +31,14 @@ public class ActionDomainEventPage_updateTextNotAnnotated { // ... //end::class[] - private final ActionDomainEventPage actionDomainEventVm; + private final ActionDomainEventPage page; @MemberSupport public ActionDomainEventPage act(final String text) { - actionDomainEventVm.setText(text); - return actionDomainEventVm; + page.setText(text); + return page; } @MemberSupport public String default0Act() { - return actionDomainEventVm.getText(); + return page.getText(); } //tag::class[] } diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/CollectionMenu.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/CollectionMenu.java index 658f10c044..3063227745 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/CollectionMenu.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/CollectionMenu.java @@ -53,11 +53,9 @@ public class CollectionMenu { page.addChild("#1"); page.addChild("#2"); page.addChild("#3"); - page.addOtherChild("#1"); page.addOtherChild("#2"); page.addOtherChild("#3"); - return page; } diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/CollectionDomainEventPage.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/CollectionDomainEventPage.java index 9f2959eb81..ffa669142a 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/CollectionDomainEventPage.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/CollectionDomainEventPage.java @@ -47,7 +47,6 @@ import org.apache.causeway.applib.events.domain.CollectionDomainEvent; public class CollectionDomainEventPage implements HasAsciiDocDescription { // ... //end::class[] - int lastChildNumberAdded; @ObjectSupport public String title() { return "@Collection#domainEvent"; diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/child/CollectionDomainEventChildVm.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/child/CollectionDomainEventChildVm.java index 214021f40b..1d5540ac9f 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/child/CollectionDomainEventChildVm.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/child/CollectionDomainEventChildVm.java @@ -37,12 +37,11 @@ import lombok.NoArgsConstructor; import lombok.Setter; //tag::class[] -@XmlRootElement(name = "child") +@XmlRootElement(name = "demo.CollectionDomainEventChildVm") @XmlType @XmlAccessorType(XmlAccessType.FIELD) @Named("demo.CollectionDomainEventChildVm") -@DomainObject( - nature=Nature.VIEW_MODEL) +@DomainObject(nature=Nature.VIEW_MODEL) @NoArgsConstructor public class CollectionDomainEventChildVm implements HasAsciiDocDescription { @@ -54,7 +53,6 @@ public class CollectionDomainEventChildVm implements HasAsciiDocDescription { //tag::class[] @Title @Property() - @PropertyLayout(fieldSetId = "properties", sequence = "1") @XmlElement(required = true) @Getter @Setter private String value; diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/child/CollectionDomainEventChildVm.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/child/CollectionDomainEventChildVm.layout.xml index 5f64b9631a..a5d295bce2 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/child/CollectionDomainEventChildVm.layout.xml +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/collections/Collection/domainEvent/child/CollectionDomainEventChildVm.layout.xml @@ -28,25 +28,25 @@ <bs3:col span="6"> <bs3:row> <bs3:col span="12"> - <cpt:fieldSet name="Properties" id="properties"/> + <cpt:fieldSet name="Properties" id="properties"> + <cpt:property id="value"/> + </cpt:fieldSet> <cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/> </bs3:col> </bs3:row> - <bs3:row> - <bs3:col span="12"> - <cpt:collection id="events"/> - </bs3:col> - </bs3:row> </bs3:col> <bs3:col span="6"> <cpt:fieldSet name="Description" id="description" > <cpt:action id="clearHints" position="PANEL" /> - <cpt:action id="downloadLayoutXml" position="PANEL_DROPDOWN"/> <cpt:action id="rebuildMetamodel" position="PANEL"/> - <cpt:action id="downloadMetamodelXml" position="PANEL_DROPDOWN"/> + <cpt:action id="downloadLayout" position="PANEL_DROPDOWN"/> <cpt:action id="inspectMetamodel" position="PANEL_DROPDOWN"/> + <cpt:action id="downloadMetamodelXml" position="PANEL_DROPDOWN"/> + <cpt:action id="downloadJdoMetamodel" position="PANEL_DROPDOWN"/> <cpt:action id="recentCommands" position="PANEL_DROPDOWN"/> - <cpt:action id="downloadJdoMetadata" position="PANEL_DROPDOWN"/> + <cpt:action id="recentExecutions" position="PANEL_DROPDOWN"/> + <cpt:action id="recentAuditTrailEntries" position="PANEL_DROPDOWN"/> + <cpt:action id="impersonateWithRoles" position="PANEL_DROPDOWN"/> <cpt:action id="openRestApi" position="PANEL_DROPDOWN" /> <cpt:property id="description"/> </cpt:fieldSet> diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/DomainObjectMenu.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/DomainObjectMenu.java index 29aa7593b0..541f28f8e6 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/DomainObjectMenu.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/DomainObjectMenu.java @@ -29,6 +29,7 @@ import demoapp.dom.domain.objects.DomainObject.nature.DomainObjectNaturePage; import demoapp.dom.domain.objects.DomainObject.xxxDomainEvent.DomainObjectXxxDomainEventPage; import demoapp.dom.domain.objects.DomainObject.xxxLifecycleEvent.DomainObjectXxxLifecyleEventPage; import lombok.RequiredArgsConstructor; +import lombok.val; import javax.inject.Inject; import javax.inject.Named; @@ -94,7 +95,11 @@ public class DomainObjectMenu { @Action(semantics = SemanticsOf.SAFE) @ActionLayout(cssClassFa="fa-asterisk", describedAs = "Default class of the domain event emitted when interacting with the domain object's actions, properties or collections") public DomainObjectXxxDomainEventPage domainEvents() { - return new DomainObjectXxxDomainEventPage(); + val page = new DomainObjectXxxDomainEventPage("change me"); + page.addChild("#1"); + page.addChild("#2"); + page.addChild("#3"); + return page; } @Action(semantics = SemanticsOf.SAFE) diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventControlStrategy.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventControlStrategy.java new file mode 100644 index 0000000000..78ff55b70a --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventControlStrategy.java @@ -0,0 +1,166 @@ +/* + * 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 demoapp.dom.domain.objects.DomainObject.xxxDomainEvent; + +import lombok.val; + +import java.util.List; + +import org.apache.causeway.applib.events.domain.AbstractDomainEvent; +import org.apache.causeway.applib.events.domain.ActionDomainEvent; +import org.apache.causeway.applib.services.message.MessageService; +import org.apache.causeway.applib.services.registry.ServiceRegistry; + +// tag::class[] +enum DomainObjectXxxDomainEventControlStrategy { + + DO_NOTHING{ + @Override + void on(DomainObjectXxxDomainEventPage.DomainEventMarker ev, ServiceRegistry serviceRegistry) { + } + }, + // ... +// end::class[] + +// tag::hide[] + HIDE { + @Override + void on(DomainObjectXxxDomainEventPage.DomainEventMarker ev, ServiceRegistry serviceRegistry) { + if (ev instanceof AbstractDomainEvent) { + AbstractDomainEvent domainEvent = (AbstractDomainEvent) ev; + switch (domainEvent.getEventPhase()) { + case HIDE: + domainEvent.hide(); + break; + } + } + } + }, +// end::hide[] +// tag::disable[] + DISABLE { + @Override + void on(DomainObjectXxxDomainEventPage.DomainEventMarker ev, ServiceRegistry serviceRegistry) { + if (ev instanceof AbstractDomainEvent) { + AbstractDomainEvent domainEvent = (AbstractDomainEvent) ev; + switch (domainEvent.getEventPhase()) { + case DISABLE: + domainEvent.disable("ControlStrategy set to DISABLE"); + break; + } + } + } + }, +// end::disable[] +// tag::validate[] + VALIDATE_MUST_BE_UPPER_CASE{ + @Override + void on(DomainObjectXxxDomainEventPage.DomainEventMarker ev, ServiceRegistry serviceRegistry) { + if (ev instanceof DomainObjectXxxDomainEventPage.ActionEvent) { + val actionEvent = (DomainObjectXxxDomainEventPage.ActionEvent) ev; + switch (actionEvent.getEventPhase()) { + case VALIDATE: + String argument = (String) actionEvent.getArguments().get(0); + if (!argument.toUpperCase().equals(argument)) { + actionEvent.invalidate("must be upper case"); + } + break; + } + } + if (ev instanceof DomainObjectXxxDomainEventPage.PropertyEvent) { + val propertyEvent = (DomainObjectXxxDomainEventPage.PropertyEvent) ev; + switch (propertyEvent.getEventPhase()) { + case VALIDATE: + Object newValue = propertyEvent.getNewValue(); + if(!newValue.toString().toUpperCase().equals(newValue)) { + propertyEvent.invalidate("must be upper case"); + } + break; + } + } + } + }, +// end::validate[] +// tag::executing[] + EXECUTING_FORCE_UPPER_CASE{ + @Override + void on(DomainObjectXxxDomainEventPage.DomainEventMarker ev, ServiceRegistry serviceRegistry) { + if (ev instanceof DomainObjectXxxDomainEventPage.ActionEvent) { + val actionEvent = (DomainObjectXxxDomainEventPage.ActionEvent) ev; + switch (actionEvent.getEventPhase()) { + case EXECUTING: + List<Object> arguments = actionEvent.getArguments(); + String newValue = ((String) arguments.get(0)).toUpperCase(); + arguments.set(0, newValue); + break; + } + } + if (ev instanceof DomainObjectXxxDomainEventPage.PropertyEvent) { + val propertyEvent = (DomainObjectXxxDomainEventPage.PropertyEvent) ev; + switch (propertyEvent.getEventPhase()) { + case EXECUTING: + String newValue = propertyEvent.getNewValue().toString().toUpperCase(); + propertyEvent.setNewValue(newValue); + break; + } + } + } + }, +// end::executing[] +// tag::executed[] + EXECUTED_ANNOUNCE{ + @Override + void on(DomainObjectXxxDomainEventPage.DomainEventMarker ev, ServiceRegistry serviceRegistry) { + if (ev instanceof DomainObjectXxxDomainEventPage.ActionEvent) { + val actionEvent = (DomainObjectXxxDomainEventPage.ActionEvent) ev; + switch (actionEvent.getEventPhase()) { + case EXECUTED: + serviceRegistry + .lookupService(MessageService.class) + .ifPresent(ms -> + ms.informUser("Changed using updateText") + ); + break; + } + } + if (ev instanceof DomainObjectXxxDomainEventPage.PropertyEvent) { + val propertyEvent = (DomainObjectXxxDomainEventPage.PropertyEvent) ev; + switch (propertyEvent.getEventPhase()) { + case EXECUTED: + serviceRegistry + .lookupService(MessageService.class) + .ifPresent(ms -> + ms.informUser( + String.format("Changed from %s to %s" + , propertyEvent.getOldValue() + , propertyEvent.getNewValue())) + + ); + break; + } + } + } + } +// end::executed[] + +// tag::class[] + ; + abstract void on(DomainObjectXxxDomainEventPage.DomainEventMarker ev, ServiceRegistry serviceRegistry); +} +// end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventControlSubscriber.java similarity index 52% copy from examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventControlSubscriber.java index b7825b38fe..6c40104b3c 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventControlSubscriber.java @@ -16,28 +16,29 @@ * specific language governing permissions and limitations * under the License. */ -package demoapp.dom.domain.actions.Action.domainEvent; +package demoapp.dom.domain.objects.DomainObject.xxxDomainEvent; + +import lombok.RequiredArgsConstructor; import javax.inject.Inject; -import org.apache.causeway.applib.annotation.Property; -import org.apache.causeway.applib.annotation.PropertyLayout; +import org.apache.causeway.applib.services.registry.ServiceRegistry; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; -import lombok.RequiredArgsConstructor; +// tag::class[] +@Service +@RequiredArgsConstructor(onConstructor_ = {@Inject}) +class DomainObjectXxxDomainEventControlSubscriber { + final ServiceRegistry serviceRegistry; -//tag::class[] -@Property() -@PropertyLayout(fieldSetId = "contributed", sequence = "1") -@RequiredArgsConstructor -public class ActionDomainEventPage_controlStrategy { + DomainObjectXxxDomainEventControlStrategy controlStrategy = + DomainObjectXxxDomainEventControlStrategy.DO_NOTHING; // <.> - private final ActionDomainEventPage page; - - public ActionDomainEventControlStrategy prop() { - return eventActionDomainEventControlService.controlStrategy; + @EventListener(DomainObjectXxxDomainEventPage.DomainEventMarker.class) // <.> + public void on(DomainObjectXxxDomainEventPage.DomainEventMarker ev) { + controlStrategy.on(ev, serviceRegistry); // <.> } - - @Inject ActionDomainEventControlSubscriber eventActionDomainEventControlService; } -//end::class[] +// end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage-description.adoc index 21d6014a98..7f436d8809 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage-description.adoc +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage-description.adoc @@ -1,61 +1,111 @@ :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 ag [...] -[#actionDomainEvent] -== actionDomainEvent +Usually a domain event is emitted by the framework to emit whenever the user interacts with an object member, in other words an action, property or collection. +Domain service subscribers can influence this interaction, either by: -Indicates that an invocation of _any_ action of the domain object (that do not themselves specify their own `@Action(domainEvent=...)` should be posted to the _org.apache.causeway.applib.services.eventbus.EventBusService event bus_ using the specified custom (subclass of) https://causeway.apache.org/refguide/${CAUSEWAY_VERSION}/applib/index/events/domain/ActionDomainEvent.html[ActionDomainEvent] . +* hiding the action, property or collection +* disabling the action or property. +(This does not apply to collections as they cannot be modified directly). +* validating arguments of the action invocation or property edit +* performing arbitrary operations before the action has been invoked / property edited (including modifying the argument values to be used) +* performing arbitrary operations after the action has been invoked / property edited -For example: +Most commonly the domain event to emit is specified at the member level, using link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/Action.html#domainevent[@Action#actionDomainEvent], link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/Property.html#domainevent[@Property#actionDomainEvent] or link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/Collection.html#domainevent[@Collection#actionDomainEvent]. +But as a fallback the `domainEvent` can also be at the class level using link:https://causeway.apache.org/refguide/2.0.0-SNAPSHOT/applib/index/annotation/DomainObject.html#actiondomainevent[@DomainObject#actionDomainEvent]. ----- - -@DomainObject(actionDomainEvent=SomeObject.GenericActionDomainEvent.class) -public class SomeObject{ - public static class GenericActionDomainEvent extends ActionDomainEvent<Object> { ... } - - public void changeStartDate(final Date startDate) { ...} - ... -} ----- - -This will result in all actions as a more specific type to use) to emit this event. -This subclass must provide a no-arg constructor; the fields are set reflectively. It must also use `Object` as its generic type. This is to allow mixins to also emit the same event. +=== How this demo works -[#propertyDomainEvent] -== propertyDomainEvent +This page object has a single (editable) property, `text`, an action to update it, and a collection. +None of these domain members are annotated with a domainEvent directly, but their containing page object _is_ annotated. -Indicates that changes to _any_ property of the domain object (that do not themselves specify their own `@Property(domainEvent=...)` should be posted to the _org.apache.causeway.applib.services.eventbus.EventBusService event bus_ using the specified custom (subclass of) https://causeway.apache.org/refguide/${CAUSEWAY_VERSION}/applib/index/events/domain/PropertyDomainEvent.html[PropertyDomainEvent] . +The interactions with these members can be controlled using the "change control strategy" action, influencing whether they are hidden, disabled, and so on. -For example: +In terms of code: +* this page object defines a set of domain event classes: ++ +[source,java] +.DomainObjectXxxDomainEventPage.java ---- - -@DomainObject(propertyDomainEvent=SomeObject.GenericPropertyDomainEvent.class) -public class SomeObject{ - - public LocalDate getStartDate() { ...} -} +include::DomainObjectXxxDomainEventPage.java[tags=class] +---- +<.> the action domain event class to emit (if not annotated at the member level) +<.> the property domain event class to emit (if not annotated at the member level) +<.> the collection domain event class to emit (if not annotated at the member level) +<.> marker interface. +All the domain event classes implement this interface, and the subscriber (see below) subscribes on this type +<.> the property can be edited directly (and can also be modified using a action (see below) + +* the mixin action to update the property ++ +[source,java] +.DomainObjectXxxDomainEventPage_updateText.java +---- +include::DomainObjectXxxDomainEventPage_updateText.java[tags=class] ---- -This subclass must provide a no-arg constructor; the fields are set reflectively. It must also use `Object` as its generic type. This is to allow mixins to also emit the same event. -[#collectionDomainEvent] -== collectionDomainEvent +* the subscriber that listens to the events: ++ +[source,java] +.DomainObjectXxxDomainEventControlSubscriber.java +---- +include::DomainObjectXxxDomainEventControlSubscriber.java[tags=class] +---- +<.> currently selected strategy +<.> listens to the custom event (marker interface) +<.> dispatches to the currently selected control strategy (see below) + +* the action that selects the strategy in effect: ++ +[source,java] +.DomainObjectXxxDomainEventPage_changeControlStrategy +---- +include::DomainObjectXxxDomainEventPage_changeControlStrategy.java[tags=class] +---- -Indicates that changes to _any_ collection of the domain object (that do not themselves specify their own `@Collection(domainEvent=...)` should be posted to the https://causeway.apache.org/refguide/${CAUSEWAY_VERSION}/applib/index/services/eventbus/EventBusService.html[EventBusService] event bus_ using a custom (subclass of) https://causeway.apache.org/refguide/${CAUSEWAY_VERSION}/applib/index/events/domain/CollectionDomainEvent.html[CollectionDomainEvent] . +* the different strategies: -For example: +** do nothing ++ +[source,java] +---- +include::DomainObjectXxxDomainEventControlStrategy.java[tags=class] +---- +** hide ++ +[source,java,indent=0] +---- +include::DomainObjectXxxDomainEventControlStrategy.java[tags=hide] ---- -@DomainObject(collectionDomainEvent=Order.GenericCollectionDomainEvent.class) -public class Order { +** disable ++ +[source,java,indent=0] +---- +include::DomainObjectXxxDomainEventControlStrategy.java[tags=disable] +---- - public SortedSet<OrderLine> getLineItems() { ...} -} +** validate ++ +[source,java,indent=0] +---- +include::DomainObjectXxxDomainEventControlStrategy.java[tags=validate] ---- -This subclass must provide a no-arg constructor; the fields are set reflectively. It must also use `Object` as its generic type. This is to allow mixins to also emit the same event. +** executing ++ +[source,java,indent=0] +---- +include::DomainObjectXxxDomainEventControlStrategy.java[tags=executing] +---- +** executed ++ +[source,java,indent=0] +---- +include::DomainObjectXxxDomainEventControlStrategy.java[tags=executed] +---- diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.java index d2884b23ba..c3e0ca9487 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.java @@ -19,29 +19,84 @@ package demoapp.dom.domain.objects.DomainObject.xxxDomainEvent; import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription; +import demoapp.dom.domain.objects.DomainObject.xxxDomainEvent.child.DomainObjectXxxDomainEventChildVm; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; import javax.inject.Named; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.*; -import org.apache.causeway.applib.annotation.DomainObject; -import org.apache.causeway.applib.annotation.Nature; -import org.apache.causeway.applib.annotation.ObjectSupport; +import org.apache.causeway.applib.annotation.*; +import org.apache.causeway.applib.events.domain.ActionDomainEvent; +import org.apache.causeway.applib.events.domain.CollectionDomainEvent; +import org.apache.causeway.applib.events.domain.PropertyDomainEvent; -//tag::class[] -@XmlRootElement(name = "root") +@XmlRootElement(name = "demo.DomainObjectxxxDomainEventPage") @XmlType @XmlAccessorType(XmlAccessType.FIELD) -@Named("demo.DomainObjectXxxDomainEventPage") +@Named("demo.DomainObjectxxxDomainEventPage") +@NoArgsConstructor +//tag::class[] +// ... @DomainObject( - nature = Nature.VIEW_MODEL) + actionDomainEvent = DomainObjectXxxDomainEventPage.ActionEvent.class, // <.> + propertyDomainEvent = DomainObjectXxxDomainEventPage.PropertyEvent.class, // <.> + collectionDomainEvent = DomainObjectXxxDomainEventPage.CollectionEvent.class, // <.> + nature=Nature.VIEW_MODEL +) public class DomainObjectXxxDomainEventPage implements HasAsciiDocDescription { + public interface DomainEventMarker {} // <.> + + public static class ActionEvent // <1> + extends ActionDomainEvent<DomainObjectXxxDomainEventPage> + implements DomainEventMarker {} + + public static class PropertyEvent // <2> + extends PropertyDomainEvent<DomainObjectXxxDomainEventPage, Object> + implements DomainEventMarker {} + + public static class CollectionEvent // <3> + extends CollectionDomainEvent<DomainObjectXxxDomainEventPage, Object> + implements DomainEventMarker {} + // ... + +//end::class[] + public DomainObjectXxxDomainEventPage(final String text) { + this.text = text; + } + @ObjectSupport public String title() { return "@DomainObject#xxxDomainEvent"; } + public void addChild(String value) { + this.getChildren().add(new DomainObjectXxxDomainEventChildVm(value)); + } + +//tag::class[] + @Property(editing = Editing.ENABLED) // <.> + @XmlElement(required = true) + @Getter @Setter + private String text; + + public DomainObjectXxxDomainEventPage updateTextDirectly(String text) { + setText(text); + return this; + } + public String default0UpdateTextDirectly() { + return getText(); + } + + + @Collection + @XmlElementWrapper(name = "children") + @XmlElement(name = "child") + @Getter @Setter + private List<DomainObjectXxxDomainEventChildVm> children = new ArrayList<>(); } //end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.layout.xml index 2ca31ba597..ad7315e077 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.layout.xml +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.layout.xml @@ -18,7 +18,6 @@ <bs3:row> <bs3:col span="10" unreferencedActions="true"> <cpt:domainObject /> - <cpt:action id="toggleEvents"/> </bs3:col> <bs3:col span="2"> <cpt:fieldSet name="" id="sources" /> @@ -27,10 +26,34 @@ <bs3:row> <bs3:col span="6"> - <cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/> - <cpt:collection id="objects"> - <cpt:action id="updateName"/> - </cpt:collection> + <bs3:row> + <bs3:col span="12"> + <cpt:fieldSet name="Object" id="object"> + <cpt:property id="text"> + <cpt:action id="updateText"> + <cpt:named>update</cpt:named> + </cpt:action> + </cpt:property> + </cpt:fieldSet> + </bs3:col> + </bs3:row> + <bs3:row> + <bs3:col span="12"> + <cpt:collection id="children"/> + </bs3:col> + </bs3:row> + <bs3:row> + <bs3:col span="12"> + <cpt:fieldSet name="Control" id="contributed"> + <cpt:property id="controlStrategy"> + <cpt:action id="changeControlStrategy"> + <cpt:named>Change</cpt:named> + </cpt:action> + </cpt:property> + </cpt:fieldSet> + <cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/> + </bs3:col> + </bs3:row> </bs3:col> <bs3:col span="6"> <cpt:fieldSet name="Description" id="description" > diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateText.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_changeControlStrategy.java similarity index 55% copy from examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateText.java copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_changeControlStrategy.java index a74663ce36..f4aaf5d27b 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateText.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_changeControlStrategy.java @@ -16,35 +16,40 @@ * specific language governing permissions and limitations * under the License. */ -package demoapp.dom.domain.actions.Action.domainEvent; +package demoapp.dom.domain.objects.DomainObject.xxxDomainEvent; + +import lombok.RequiredArgsConstructor; + +import javax.inject.Inject; import org.apache.causeway.applib.annotation.Action; -import org.apache.causeway.applib.annotation.ActionLayout; import org.apache.causeway.applib.annotation.MemberSupport; +import org.apache.causeway.applib.annotation.SemanticsOf; import org.apache.causeway.applib.events.domain.ActionDomainEvent; -import lombok.RequiredArgsConstructor; - //tag::class[] -@Action(domainEvent = ActionDomainEventPage_updateText.DomainEvent.class) // <.> +@Action( + domainEvent = DomainObjectXxxDomainEventPage_changeControlStrategy.DomainEvent.class, // <.> + semantics = SemanticsOf.IDEMPOTENT +) @RequiredArgsConstructor -public class ActionDomainEventPage_updateText { +public class DomainObjectXxxDomainEventPage_changeControlStrategy { - public static class DomainEvent // <.> - extends ActionDomainEvent<ActionDomainEventPage> {} - // ... -//end::class[] + public static class DomainEvent // <1> + extends ActionDomainEvent<DomainObjectXxxDomainEventPage> {} - private final ActionDomainEventPage actionDomainEventVm; + private final DomainObjectXxxDomainEventPage page; - @MemberSupport public ActionDomainEventPage act(final String text) { - actionDomainEventVm.setText(text); - return actionDomainEventVm; + @MemberSupport public DomainObjectXxxDomainEventPage act( + DomainObjectXxxDomainEventControlStrategy controlStrategy) { + subscriber.controlStrategy = controlStrategy; + return page; } - @MemberSupport public String default0Act() { - return actionDomainEventVm.getText(); + @MemberSupport public DomainObjectXxxDomainEventControlStrategy default0Act() { + return subscriber.controlStrategy; } -//tag::class[] + + @Inject DomainObjectXxxDomainEventControlSubscriber subscriber; } //end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_controlStrategy.java similarity index 78% copy from examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_controlStrategy.java index b7825b38fe..c1c5cb1e36 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_controlStrategy.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_controlStrategy.java @@ -16,28 +16,29 @@ * specific language governing permissions and limitations * under the License. */ -package demoapp.dom.domain.actions.Action.domainEvent; +package demoapp.dom.domain.objects.DomainObject.xxxDomainEvent; + +import lombok.RequiredArgsConstructor; import javax.inject.Inject; import org.apache.causeway.applib.annotation.Property; import org.apache.causeway.applib.annotation.PropertyLayout; -import lombok.RequiredArgsConstructor; - //tag::class[] @Property() @PropertyLayout(fieldSetId = "contributed", sequence = "1") @RequiredArgsConstructor -public class ActionDomainEventPage_controlStrategy { +public class DomainObjectXxxDomainEventPage_controlStrategy { - private final ActionDomainEventPage page; + private final DomainObjectXxxDomainEventPage page; - public ActionDomainEventControlStrategy prop() { + public DomainObjectXxxDomainEventControlStrategy prop() { return eventActionDomainEventControlService.controlStrategy; } - @Inject ActionDomainEventControlSubscriber eventActionDomainEventControlService; + @Inject + DomainObjectXxxDomainEventControlSubscriber eventActionDomainEventControlService; } //end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateTextNotAnnotated.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_updateTextMixin.java similarity index 64% copy from examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateTextNotAnnotated.java copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_updateTextMixin.java index 03c15987ae..637b77236c 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/Action/domainEvent/ActionDomainEventPage_updateTextNotAnnotated.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage_updateTextMixin.java @@ -16,32 +16,27 @@ * specific language governing permissions and limitations * under the License. */ -package demoapp.dom.domain.actions.Action.domainEvent; +package demoapp.dom.domain.objects.DomainObject.xxxDomainEvent; import lombok.RequiredArgsConstructor; import org.apache.causeway.applib.annotation.Action; -import org.apache.causeway.applib.annotation.ActionLayout; import org.apache.causeway.applib.annotation.MemberSupport; -import org.apache.causeway.applib.events.domain.ActionDomainEvent; //tag::class[] -@Action() // <.> +@Action() @RequiredArgsConstructor -public class ActionDomainEventPage_updateTextNotAnnotated { - // ... -//end::class[] +public class DomainObjectXxxDomainEventPage_updateTextMixin { - private final ActionDomainEventPage actionDomainEventVm; + private final DomainObjectXxxDomainEventPage page; - @MemberSupport public ActionDomainEventPage act(final String text) { - actionDomainEventVm.setText(text); - return actionDomainEventVm; + @MemberSupport public DomainObjectXxxDomainEventPage act(final String text) { + page.setText(text); + return page; } @MemberSupport public String default0Act() { - return actionDomainEventVm.getText(); + return page.getText(); } -//tag::class[] } //end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm-description.adoc new file mode 100644 index 0000000000..3bae8376bb --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm-description.adoc @@ -0,0 +1,4 @@ +: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 ag [...] + +This is a child object used in the demonstration of `DomainObject#domainEvent()`. + diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm.java similarity index 58% copy from examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.java copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm.java index d2884b23ba..0392275c19 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm.java @@ -16,32 +16,38 @@ * specific language governing permissions and limitations * under the License. */ -package demoapp.dom.domain.objects.DomainObject.xxxDomainEvent; +package demoapp.dom.domain.objects.DomainObject.xxxDomainEvent.child; import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import javax.inject.Named; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.*; -import org.apache.causeway.applib.annotation.DomainObject; -import org.apache.causeway.applib.annotation.Nature; -import org.apache.causeway.applib.annotation.ObjectSupport; +import org.apache.causeway.applib.annotation.*; //tag::class[] -@XmlRootElement(name = "root") +@XmlRootElement(name = "demo.DomainObjectXxxDomainEventChildVm") @XmlType @XmlAccessorType(XmlAccessType.FIELD) -@Named("demo.DomainObjectXxxDomainEventPage") -@DomainObject( - nature = Nature.VIEW_MODEL) -public class DomainObjectXxxDomainEventPage implements HasAsciiDocDescription { +@Named("demo.DomainObjectXxxDomainEventChildVm") +@DomainObject(nature=Nature.VIEW_MODEL) +@NoArgsConstructor +public class DomainObjectXxxDomainEventChildVm implements HasAsciiDocDescription { - @ObjectSupport public String title() { - return "@DomainObject#xxxDomainEvent"; +//end::class[] + public DomainObjectXxxDomainEventChildVm(final String value) { + this.value = value; } +//tag::class[] + @Title + @Property() + @XmlElement(required = true) + @Getter @Setter + private String value; + } //end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm.layout.xml similarity index 91% copy from examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.layout.xml copy to examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm.layout.xml index 2ca31ba597..a5d295bce2 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/DomainObjectXxxDomainEventPage.layout.xml +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObject/xxxDomainEvent/child/DomainObjectXxxDomainEventChildVm.layout.xml @@ -18,7 +18,6 @@ <bs3:row> <bs3:col span="10" unreferencedActions="true"> <cpt:domainObject /> - <cpt:action id="toggleEvents"/> </bs3:col> <bs3:col span="2"> <cpt:fieldSet name="" id="sources" /> @@ -27,10 +26,14 @@ <bs3:row> <bs3:col span="6"> - <cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/> - <cpt:collection id="objects"> - <cpt:action id="updateName"/> - </cpt:collection> + <bs3:row> + <bs3:col span="12"> + <cpt:fieldSet name="Properties" id="properties"> + <cpt:property id="value"/> + </cpt:fieldSet> + <cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/> + </bs3:col> + </bs3:row> </bs3:col> <bs3:col span="6"> <cpt:fieldSet name="Description" id="description" >
