This is an automated email from the ASF dual-hosted git repository. danhaywood pushed a commit to branch CAUSEWAY-2485 in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 8693cc8e853e7b16c338c6bb1e897bbe6858fff1 Author: danhaywood <[email protected]> AuthorDate: Mon May 15 21:37:28 2023 +0100 CAUSEWAY-2485: completes Action validate demo example --- .../autocomplete/ActionAutoCompleteMenu.java | 2 +- .../ActionAutoCompletePage-description.adoc | 2 +- .../choices/ActionChoicesPage-description.adoc | 2 +- .../progmodel/defaults/ActionDefaultsMenu.java | 2 +- .../defaults/ActionDefaultsPage-description.adoc | 2 +- .../dom/domain/actions/progmodel/disable/notes.txt | 4 +- .../dom/domain/actions/progmodel/hide/notes.txt | 4 +- .../ActionValidateMenu.java} | 12 +-- ...nValidatePage-allArgsValidationDescription.adoc | 7 ++ .../validate/ActionValidatePage-description.adoc | 79 +++++++++++++++ ...nValidatePage-parameterMatchingDescription.adoc | 7 ++ ...tionValidatePage-singleValidateDescription.adoc | 6 ++ .../progmodel/validate/ActionValidatePage.java | 108 +++++++++++++++++++++ .../validate/ActionValidatePage.layout.xml | 81 ++++++++++++++++ ...ActionValidatePage_selectTvCharacterByShow.java | 65 +++++++++++++ .../ActionValidatePage_selectTvCharacters.java | 76 +++++++++++++++ ...ge_selectTvCharactersByShowAndSexUsingName.java | 90 +++++++++++++++++ ..._selectTvCharactersByShowAndSexUsingRecord.java | 99 +++++++++++++++++++ .../src/main/java/demoapp/dom/menubars.layout.xml | 1 + 19 files changed, 636 insertions(+), 13 deletions(-) diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/autocomplete/ActionAutoCompleteMenu.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/autocomplete/ActionAutoCompleteMenu.java index 94a6cffcb4..b346eb75be 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/autocomplete/ActionAutoCompleteMenu.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/autocomplete/ActionAutoCompleteMenu.java @@ -40,7 +40,7 @@ public class ActionAutoCompleteMenu { final TvCharacterPopulator tvCharacterPopulator; @Action - @ActionLayout(cssClassFa="fa-bolt") + @ActionLayout(cssClassFa="fa-wand-magic-sparkles") public ActionAutoCompletePage autoComplete(){ val page = factoryService.viewModel(new ActionAutoCompletePage()); tvCharacterPopulator.populate(page.getTvCharacters()); diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/autocomplete/ActionAutoCompletePage-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/autocomplete/ActionAutoCompletePage-description.adoc index 889f07a886..e3b96783ee 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/autocomplete/ActionAutoCompletePage-description.adoc +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/autocomplete/ActionAutoCompletePage-description.adoc @@ -14,7 +14,7 @@ There are several variations: * the parameter for which candidates are being supplied can be either a scalar or a collection * the supporting "autoComplete" method can be associated with the parameter by number, or by name * the list of candidates for a parameter can depend upon the value already selected for an earlier parameter. -** The preceding N-1 parameters are supplied to the Nth "autoComplete" supporting method. +** The preceding N-1 parameters are supplied to the N^th^ "autoComplete" supporting method. ** Or a single record-like structure can be defined and this can be passed through to all supporting methods instead. As noted above, a supporting method to return a list of candidate arguments is _always_ required for reference types. diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/choices/ActionChoicesPage-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/choices/ActionChoicesPage-description.adoc index 9d4f3cea90..e0f9e1357e 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/choices/ActionChoicesPage-description.adoc +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/choices/ActionChoicesPage-description.adoc @@ -14,7 +14,7 @@ There are several variations: * the parameter for which candidates are being supplied can be either a scalar or a collection * the supporting "choices" method can be associated with the parameter by number, or by name * the list of candidates for a parameter can depend upon the value already selected for an earlier parameter. -** The preceding N-1 parameters are supplied to the Nth "choices" supporting method. +** The preceding N-1 parameters are supplied to the N^th^ "choices" supporting method. ** Or a single record-like structure can be defined and this can be passed through to all supporting methods instead. As noted above, a supporting method to return a list of candidate arguments is _always_ required for reference types. diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsMenu.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsMenu.java index 77d84ac622..41b11fb0e2 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsMenu.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsMenu.java @@ -44,7 +44,7 @@ public class ActionDefaultsMenu { final TvCharacterPopulator tvCharacterPopulator; @Action - @ActionLayout(cssClassFa="fa-bolt") + @ActionLayout(cssClassFa="fa-heart") public ActionDefaultsPage defaults(){ val page = factoryService.viewModel(new ActionDefaultsPage()); tvCharacterPopulator.populate(page.getTvCharacters()); diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsPage-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsPage-description.adoc index 02c5d23426..7ef678a536 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsPage-description.adoc +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsPage-description.adoc @@ -8,7 +8,7 @@ There are several variations: * the parameter argument being defaulted could be either a scalar or a collection * the supporting "default" method can be associated with the parameter by number, or by name * the default for a parameter can depend upon the value already selected for an earlier parameter. -** The preceding N-1 parameters are supplied to the Nth "default" supporting method. +** The preceding N-1 parameters are supplied to the N^th^ "default" supporting method. ** Or a single record-like structure can be defined and this can be passed through to all supporting methods instead. It's common for "default" supporting method to be paired with a "choices" or "autoComplete" supporting method, but this won't always be the case. diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/disable/notes.txt b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/disable/notes.txt index e9b99e3953..953ec611dd 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/disable/notes.txt +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/disable/notes.txt @@ -1 +1,3 @@ -example of disabling, with depargs \ No newline at end of file +example of disabling, with depargs + +circle-stop diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/hide/notes.txt b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/hide/notes.txt index ebe67b80ff..ef8be9378e 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/hide/notes.txt +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/hide/notes.txt @@ -1 +1,3 @@ -example of hiding, with depargs \ No newline at end of file +example of hiding, with depargs + +eye-slash \ No newline at end of file diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsMenu.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidateMenu.java similarity index 86% copy from examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsMenu.java copy to examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidateMenu.java index 77d84ac622..3ad8375656 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/defaults/ActionDefaultsMenu.java +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidateMenu.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package demoapp.dom.domain.actions.progmodel.defaults; +package demoapp.dom.domain.actions.progmodel.validate; import javax.annotation.Priority; import javax.inject.Inject; @@ -34,19 +34,19 @@ import lombok.val; import demoapp.dom.domain.actions.progmodel.TvCharacterPopulator; -@Named("demo.ActionDefaultsMenu") +@Named("demo.ActionValidateMenu") @DomainService(nature=NatureOfService.VIEW) @Priority(PriorityPrecedence.EARLY) @RequiredArgsConstructor(onConstructor_ = { @Inject }) -public class ActionDefaultsMenu { +public class ActionValidateMenu { final FactoryService factoryService; final TvCharacterPopulator tvCharacterPopulator; @Action - @ActionLayout(cssClassFa="fa-bolt") - public ActionDefaultsPage defaults(){ - val page = factoryService.viewModel(new ActionDefaultsPage()); + @ActionLayout(cssClassFa="fa-circle-question") + public ActionValidatePage validate(){ + val page = factoryService.viewModel(new ActionValidatePage()); tvCharacterPopulator.populate(page.getTvCharacters()); return page; } diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-allArgsValidationDescription.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-allArgsValidationDescription.adoc new file mode 100644 index 0000000000..75bd342be5 --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-allArgsValidationDescription.adoc @@ -0,0 +1,7 @@ +: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 [...] + +The action above illustrates how it's possible to validate _all_ of the arguments of action together (as opposed to each, singly). + +The action provides two parameters, one listing male characters and the other female. +The validation simply requires that the same number of male and female charactes have been selected. + diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-description.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-description.adoc new file mode 100644 index 0000000000..20645b0736 --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-description.adoc @@ -0,0 +1,79 @@ +: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 [...] + +There are often business rules which determine which action arguments are valid and which are invalid. +For example, it probably is invalid to specify a negative number of product items in an order, or to specify a date of birth in the future. + +Using the "choices" or "autoComplete" supporting methods, it is sometimes possible to restrict the candidates only to those that are valid. +And the "default" supporting method can also provide a reasonable initial value (such as 1 item in an order). + +Even so, when the action is invoked, it's necessary to make sure that all of the arguments provided are valid, both individually and in combination. + +The purpose of the "validate" supporting method is to allow the action arguments to be checked before actually executing the action. +If this returns a non-null `String` (or for i18n, a non-null link:https://causeway.apache.org/refguide/2.0.0-RC1/applib/index/services/i18n/TranslatableString.html#section[TranslatableString]), then a warning is shown and the action may not be executed. + +There are several variations: + +* the parameter argument being checked could be either a scalar or a collection +* the supporting "validate" method can be associated with the parameter by number, or by name +* the validation of a parameter might depend upon the value already selected for an earlier parameter. +** A single record-like structure can be defined and this can be passed through to all supporting methods instead. +** Or, the preceding N-1 parameters are supplied to the N^th^ "validate" supporting method. + +Finally, there is also the "validate" supporting method for all of the arguments taken together. + +== How this demo works + +On the left hand side is a list of objects representing TV characters, also indicating the TV show that they appeared in. +Below is a list of selected characters, initially empty. + +In the middle are a set of actions, each of which can be used to select a TV character or characters. +In some cases a property of the main page can be used to pre-select a value, in which case it will be used as the default for the action's parameter(s). +The last parameter of each action has a validation rule that must be satisified. + +In terms of code: + +* this action allows a single TV character to be selected. +It matches the supporting "choices" method with the parameter by number. ++ +[source,java] +.ActionValidatePage_selectTvCharacterByShow.java +---- +include::ActionValidatePage_selectTvCharacterByShow.java[tags=class] +---- +<.> 0^th^ parameter has a supporting validation method to ensure that the selected argument appears in the TV show + +* this action demonstrates dependent validation, using a "record" object to group together the preceding arguments. ++ +[source,java] +.ActionValidatePage_selectTvCharactersByShowAndSexUsingRecord.java +---- +include::ActionValidatePage_selectTvCharactersByShowAndSexUsingRecord.java[tags=class] +---- +<.> the "tvCharacters" parameter argument is validated and so has a supporting "validate" method, associated by name. +<.> the "Parameters" record object groups together the preceding arguments, passed into the "validate" method +<.> the preceding parameter values are accessed and used for the validation. + +* alternatively, this action implements the same behaviour but _without_ a "record" object, instead just passing through the N-1 arguments. ++ +[source,java] +.ActionValidatePage_selectTvCharactersByShowAndSexUsingName.java +---- +include::ActionValidatePage_selectTvCharactersByShowAndSexUsingName.java[tags=class] +---- +<.> the "tvCharacters" parameter argument is validated and so has a supporting "validate" method, associated by name. +<.> the N-1 arguments are passed into the "validate" method and can be used for validation +<.> the argument actually being validated. + ++ +WARNING: this version currently fails; being tracked with link:https://issues.apache.org/jira/browse/CAUSEWAY-3462[CAUSEWAY-3462]. + +* the final example demonstrates validating _all_ of the arguments or an action together. ++ +[source,java] +.ActionValidatePage_selectTvCharacters.java +---- +include::ActionValidatePage_selectTvCharacters.java[tags=class] +---- +<.> the set of parameters for the action method and the "validate" method are the same. +Note also that the "validate" method is named after the action, not after a parameter of the action. +<.> the validation accesses all of the parameters diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-parameterMatchingDescription.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-parameterMatchingDescription.adoc new file mode 100644 index 0000000000..853627127f --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-parameterMatchingDescription.adoc @@ -0,0 +1,7 @@ +: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 [...] + +The action in this section uses a "record" structure to represent the set of parameters accepted by the action. +With this coding convention it's idiomatic to associate the supporting method by *name* rather than number. + +Use the properties below to preselect a TV show and character sex. +The chosen TV characters must all match this show/sex. diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-singleValidateDescription.adoc b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-singleValidateDescription.adoc new file mode 100644 index 0000000000..1482dc3a7f --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage-singleValidateDescription.adoc @@ -0,0 +1,6 @@ +: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 [...] + +The action above illustrates how to validate a scalar (single-valued) action parameter. +The validation requires that the TV character selected must appear in the TV show specified in the property below. + +The action associates the supporting "validate" methods with the parameter by number (`defaultNAct`). diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage.java new file mode 100644 index 0000000000..c80427d9e8 --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage.java @@ -0,0 +1,108 @@ +/* + * 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.actions.progmodel.validate; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import javax.inject.Inject; +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.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +import org.apache.causeway.applib.annotation.Collection; +import org.apache.causeway.applib.annotation.CollectionLayout; +import org.apache.causeway.applib.annotation.DomainObject; +import org.apache.causeway.applib.annotation.Editing; +import org.apache.causeway.applib.annotation.LabelPosition; +import org.apache.causeway.applib.annotation.Nature; +import org.apache.causeway.applib.annotation.ObjectSupport; +import org.apache.causeway.applib.annotation.Optionality; +import org.apache.causeway.applib.annotation.Property; +import org.apache.causeway.applib.annotation.PropertyLayout; +import org.apache.causeway.valuetypes.asciidoc.applib.value.AsciiDoc; + +import lombok.Getter; +import lombok.Setter; + +import demoapp.dom._infra.asciidocdesc.HasAsciiDocDescription; +import demoapp.dom._infra.resources.AsciiDocReaderService; +import demoapp.dom.domain.actions.progmodel.TvCharacter; +import demoapp.dom.domain.actions.progmodel.TvShow; + +@XmlRootElement(name = "Demo") +@XmlType +@XmlAccessorType(XmlAccessType.FIELD) +@Named("demo.ActionValidate") +@DomainObject(nature=Nature.VIEW_MODEL, editing=Editing.ENABLED) +public class ActionValidatePage implements HasAsciiDocDescription { + + @ObjectSupport public String title() { + return "Action Validates"; + } + + + @Property + @PropertyLayout(labelPosition=LabelPosition.NONE) + public AsciiDoc getSingleValidateDescription() { + return asciiDocReaderService.readFor(this, "singleValidateDescription"); + } + @Property(editing = Editing.ENABLED, optionality = Optionality.OPTIONAL) + @Getter @Setter + private TvShow selectedTvShow; + + @Property + @PropertyLayout(labelPosition=LabelPosition.NONE) + public AsciiDoc getParameterMatchingDescription() { + return asciiDocReaderService.readFor(this, "parameterMatchingDescription"); + } + @Property(editing = Editing.ENABLED, optionality = Optionality.OPTIONAL) + @Getter @Setter + private TvShow preselectTvShow2; + @Property(editing = Editing.ENABLED, optionality = Optionality.OPTIONAL) + @Getter @Setter + private TvCharacter.Sex preselectCharacterSex2; + + @Property + @PropertyLayout(labelPosition=LabelPosition.NONE) + public AsciiDoc getAllArgsValidationDescription() { + return asciiDocReaderService.readFor(this, "allArgsValidationDescription"); + } + + + @Collection + @CollectionLayout + @Getter + private final Set<TvCharacter> tvCharacters = new LinkedHashSet<>(); + + @Collection + @CollectionLayout + @Getter + private final Set<TvCharacter> selectedTvCharacters = new LinkedHashSet<>(); + + @Inject @XmlTransient AsciiDocReaderService asciiDocReaderService; + +} + diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage.layout.xml new file mode 100644 index 0000000000..59c4784113 --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage.layout.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- 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. --> +<bs3:grid + xsi:schemaLocation="https://causeway.apache.org/applib/layout/component https://causeway.apache.org/applib/layout/component/component.xsd https://causeway.apache.org/applib/layout/grid/bootstrap3 https://causeway.apache.org/applib/layout/grid/bootstrap3/bootstrap3.xsd" + xmlns:bs3="https://causeway.apache.org/applib/layout/grid/bootstrap3" + xmlns:cpt="https://causeway.apache.org/applib/layout/component" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <bs3:row> + <bs3:col span="10" unreferencedActions="true"> + <cpt:domainObject /> + </bs3:col> + <bs3:col span="2"> + <cpt:fieldSet name="" id="sources" /> + </bs3:col> + </bs3:row> + <bs3:row> + + <bs3:col span="6"> + <bs3:row> + <bs3:col span="12"> + <bs3:row> + <bs3:col span="6"> + <cpt:collection id="tvCharacters"/> + <cpt:collection id="selectedTvCharacters"/> + </bs3:col> + <bs3:col span="6"> + <cpt:fieldSet name="Single Validate" id="single-choices"> + <cpt:action id="selectTvCharacterByShow"/> + <cpt:property id="singleValidateDescription"/> + <cpt:property id="selectedTvShow"/> + </cpt:fieldSet> + <cpt:fieldSet name="Parameter Matching" id="parameter-matching"> + <cpt:action id="selectTvCharactersByShowAndSexUsingRecord"/> + <cpt:action id="selectTvCharactersByShowAndSexUsingName"/> + <cpt:property id="parameterMatchingDescription"/> + <cpt:property id="preselectCharacterSex2"/> + <cpt:property id="preselectTvShow2"/> + </cpt:fieldSet> + <cpt:fieldSet name="All args validation" id="all-arg-validation"> + <cpt:action id="selectTvCharacters"/> + <cpt:property id="allArgsValidationDescription"/> + </cpt:fieldSet> + </bs3:col> + </bs3:row> + </bs3:col> + </bs3:row> + <cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/> + </bs3:col> + + <bs3:col span="6"> + <cpt:fieldSet name="Description" id="description" > + <cpt:action id="clearHints" position="PANEL" /> + <cpt:action id="rebuildMetamodel" position="PANEL"/> + <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="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> + </bs3:col> + + </bs3:row> + <bs3:row> + <bs3:col span="12" unreferencedCollections="true"/> + </bs3:row> + +</bs3:grid> diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharacterByShow.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharacterByShow.java new file mode 100644 index 0000000000..52d54ec7f9 --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharacterByShow.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package demoapp.dom.domain.actions.progmodel.validate; + +import java.util.Collection; +import java.util.stream.Collectors; + +import org.apache.causeway.applib.annotation.Action; +import org.apache.causeway.applib.annotation.MemberSupport; +import org.apache.causeway.applib.annotation.Optionality; +import org.apache.causeway.applib.annotation.Parameter; +import org.apache.causeway.applib.annotation.SemanticsOf; + +import lombok.RequiredArgsConstructor; + +import demoapp.dom.domain.actions.progmodel.TvCharacter; +import demoapp.dom.domain.actions.progmodel.TvShow; + +//tag::class[] +@Action(semantics = SemanticsOf.IDEMPOTENT) +@RequiredArgsConstructor +public class ActionValidatePage_selectTvCharacterByShow { + + private final ActionValidatePage page; + + @MemberSupport public ActionValidatePage act( + @Parameter(optionality = Optionality.MANDATORY) + final TvCharacter tvCharacter // <.> + ) { + page.getSelectedTvCharacters().clear(); + page.getSelectedTvCharacters().add(tvCharacter); + return page; + } + + @MemberSupport public Collection<TvCharacter> choices0Act() { + return page.getTvCharacters(); + } + @MemberSupport public String validate0Act( // <1> + final TvCharacter tvCharacter + ) { + TvShow selectedTvShow = page.getSelectedTvShow(); + return selectedTvShow == null || + tvCharacter.getTvShow() == selectedTvShow + ? null + : "TV character doesn't appear in that show"; + } +} +//end::class[] + diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharacters.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharacters.java new file mode 100644 index 0000000000..73de7ae7b5 --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharacters.java @@ -0,0 +1,76 @@ +/* + * 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.actions.progmodel.validate; + +import demoapp.dom.domain.actions.progmodel.TvCharacter; + +import lombok.RequiredArgsConstructor; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.causeway.applib.annotation.*; + +//tag::class[] +@Action(semantics = SemanticsOf.IDEMPOTENT) +@RequiredArgsConstructor +public class ActionValidatePage_selectTvCharacters { + + private final ActionValidatePage page; + + @MemberSupport public ActionValidatePage act( // <.> + @Parameter(optionality = Optionality.MANDATORY) + final List<TvCharacter> maleTvCharacters, + @Parameter(optionality = Optionality.MANDATORY) + final List<TvCharacter> femaleTvCharacters + ) { + // ... +//end::class[] + page.getSelectedTvCharacters().clear(); + page.getSelectedTvCharacters().addAll(maleTvCharacters); + page.getSelectedTvCharacters().addAll(femaleTvCharacters); + return page; +//tag::class[] + } + + @MemberSupport public Collection<TvCharacter> choicesMaleTvCharacters() { + return pageTvCharacters(TvCharacter.Sex.MALE); + } + @MemberSupport public Collection<TvCharacter> choicesFemaleTvCharacters() { + return pageTvCharacters(TvCharacter.Sex.FEMALE); + } + @MemberSupport public String validateAct( // <1> + final List<TvCharacter> maleTvCharacters, + final List<TvCharacter> femaleTvCharacters + ) { + return maleTvCharacters.size() == femaleTvCharacters.size() // <.> + ? null + : "Must have the same number of male and female characters"; + } + // ... +//end::class[] + private List<TvCharacter> pageTvCharacters(TvCharacter.Sex sex) { + return page.getTvCharacters().stream() + .filter(x -> x.getSex() == sex).collect(Collectors.toList()); + } +//tag::class[] +} +//end::class[] + diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharactersByShowAndSexUsingName.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharactersByShowAndSexUsingName.java new file mode 100644 index 0000000000..3173185cb1 --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharactersByShowAndSexUsingName.java @@ -0,0 +1,90 @@ +/* + * 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.actions.progmodel.validate; + +import demoapp.dom.domain.actions.progmodel.TvCharacter; +import demoapp.dom.domain.actions.progmodel.TvShow; + +import lombok.RequiredArgsConstructor; +import lombok.Value; +import lombok.experimental.Accessors; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.causeway.applib.annotation.*; + +//tag::class[] +@Action(semantics = SemanticsOf.SAFE) +@RequiredArgsConstructor +public class ActionValidatePage_selectTvCharactersByShowAndSexUsingName { + + private final ActionValidatePage page; + + @MemberSupport public ActionValidatePage act( + @Parameter(optionality = Optionality.MANDATORY) + final TvShow tvShow, + @Parameter(optionality = Optionality.OPTIONAL) + final TvCharacter.Sex sex, + @Parameter(optionality = Optionality.OPTIONAL) + final List<TvCharacter> tvCharacters // <.> + ) { + // ... +//end::class[] + page.getSelectedTvCharacters().clear(); + page.getSelectedTvCharacters().addAll(tvCharacters); + return page; +//tag::class[] + } + + // ... +//end::class[] + @MemberSupport public TvShow defaultTvShow() { // <1> + return page.getPreselectTvShow2(); + } + @MemberSupport public TvCharacter.Sex defaultSex() { // <2> + return page.getPreselectCharacterSex2(); + } + @MemberSupport public List<TvCharacter> choicesTvCharacters() { + return new ArrayList<>(page.getTvCharacters()); + } +//tag::class[] + @MemberSupport public String validateTvCharacters( // <1> + final TvShow tvShowSelected, // <.> + final TvCharacter.Sex sexSelected, // <2> + final List<TvCharacter> tvCharacters // <.> + ) { + // ... +//end::class[] + if (tvCharacters.isEmpty()) { + return "Must specify at least one TV character"; + } + List<TvCharacter> collect = choicesTvCharacters() + .stream() + .filter(tvCharacter -> tvShowSelected == null || tvShowSelected == tvCharacter.getTvShow()) + .filter(tvCharacter -> sexSelected == null || sexSelected == tvCharacter.getSex()) + .collect(Collectors.toList()); + return collect.containsAll(tvCharacters) + ? null + : "Not all of the characters were in that TV show/of the specified sex"; +//tag::class[] + } +} +//end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharactersByShowAndSexUsingRecord.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharactersByShowAndSexUsingRecord.java new file mode 100644 index 0000000000..81e5f346cb --- /dev/null +++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/progmodel/validate/ActionValidatePage_selectTvCharactersByShowAndSexUsingRecord.java @@ -0,0 +1,99 @@ +/* + * 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.actions.progmodel.validate; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.causeway.applib.annotation.Action; +import org.apache.causeway.applib.annotation.MemberSupport; +import org.apache.causeway.applib.annotation.Optionality; +import org.apache.causeway.applib.annotation.Parameter; +import org.apache.causeway.applib.annotation.SemanticsOf; + +import lombok.RequiredArgsConstructor; +import lombok.Value; +import lombok.val; +import lombok.experimental.Accessors; + +import demoapp.dom.domain.actions.progmodel.TvCharacter; +import demoapp.dom.domain.actions.progmodel.TvShow; + +//tag::class[] +@Action(semantics = SemanticsOf.SAFE) +@RequiredArgsConstructor +public class ActionValidatePage_selectTvCharactersByShowAndSexUsingRecord { + + private final ActionValidatePage page; + + @MemberSupport public ActionValidatePage act( + @Parameter(optionality = Optionality.MANDATORY) + final TvShow tvShow, + @Parameter(optionality = Optionality.OPTIONAL) + final TvCharacter.Sex sex, + @Parameter(optionality = Optionality.OPTIONAL) + final List<TvCharacter> tvCharacters // <.> + ) { + // ... +//end::class[] + page.getSelectedTvCharacters().clear(); + page.getSelectedTvCharacters().addAll(tvCharacters); + return page; +//tag::class[] + } + + @Value @Accessors(fluent = true) + static class Parameters { // <.> + TvShow tvShow; + TvCharacter.Sex sex; + List<TvCharacter> tvCharacters; + } + // ... +//end::class[] + @MemberSupport public TvShow defaultTvShow() { + return page.getPreselectTvShow2(); + } + @MemberSupport public TvCharacter.Sex defaultSex() { + return page.getPreselectCharacterSex2(); + } + @MemberSupport public List<TvCharacter> choicesTvCharacters() { + return new ArrayList<>(page.getTvCharacters()); + } +//tag::class[] + @MemberSupport public String validateTvCharacters( // <1> + final Parameters params // <2> + ) { + List<TvCharacter> tvCharacters = params.tvCharacters(); + if (tvCharacters.isEmpty()) { + return "Must specify at least one TV character"; + } + val tvShowSelected = params.tvShow(); // <.> + val sexSelected = params.sex; // <3> + List<TvCharacter> collect = choicesTvCharacters() + .stream() + .filter(tvCharacter -> tvShowSelected == null || tvShowSelected == tvCharacter.getTvShow()) + .filter(tvCharacter -> sexSelected == null || sexSelected == tvCharacter.getSex()) + .collect(Collectors.toList()); + return collect.containsAll(tvCharacters) + ? null + : "Not all of the characters were in that TV show/of the specified sex"; + } +} +//end::class[] diff --git a/examples/demo/domain/src/main/java/demoapp/dom/menubars.layout.xml b/examples/demo/domain/src/main/java/demoapp/dom/menubars.layout.xml index 6ae9c6ea2a..3cc84f93f5 100644 --- a/examples/demo/domain/src/main/java/demoapp/dom/menubars.layout.xml +++ b/examples/demo/domain/src/main/java/demoapp/dom/menubars.layout.xml @@ -92,6 +92,7 @@ For latest we use: https://raw.githubusercontent.com/apache/causeway/master/anto <mb3:serviceAction objectType="demo.ActionChoicesMenu" id="choices"/> <mb3:serviceAction objectType="demo.ActionAutoCompleteMenu" id="autoComplete"/> <mb3:serviceAction objectType="demo.ActionDefaultsMenu" id="defaults"/> + <mb3:serviceAction objectType="demo.ActionValidateMenu" id="validate"/> <mb3:serviceAction objectType="demo.ActionDependentArgsMenu" id="dependentArgsActions"> <cpt:named>Dependent Arguments</cpt:named> </mb3:serviceAction>
