| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <title>Customizing the Prog Model :: Apache Isis</title> |
| <link rel="canonical" href="https://isis.apache.org/userguide/2.0.0-M3/btb/programming-model.html"> |
| <meta name="generator" content="Antora 2.2.0"> |
| <link rel="stylesheet" href="../../../_/css/site.css"> |
| <link rel="stylesheet" href="../../../_/css/site-custom.css"> |
| <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,700,700i|Raleway:300,400,500,700,800|Montserrat:300,400,700" rel="stylesheet"> |
| <link rel="home" href="https://isis.apache.org" title="Apache Isis"> |
| <link rel="next" href="../flyway/about.html" title="Flyway"> |
| <link rel="prev" href="hints-and-tips.html" title="Hints-n-Tips"> |
| </head> |
| <body class="article"> |
| <header class="header"> |
| <nav class="navbar"> |
| <div class="navbar-brand"> |
| <a class="navbar-item" href="https://isis.apache.org"> |
| <span class="icon"> |
| <img src="../../../_/img/isis-logo-48x48.png"></img> |
| </span> |
| <span>Apache Isis</span> |
| </a> |
| <button class="navbar-burger" data-target="topbar-nav"> |
| <span></span> |
| <span></span> |
| <span></span> |
| </button> |
| </div> |
| <div id="topbar-nav" class="navbar-menu"> |
| <a class="navbar-end"> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Quick Start</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">Starter Apps</span> |
| <a class="navbar-item" href="../../../docs/latest/starters/helloworld.html">Hello World</a> |
| <a class="navbar-item" href="../../../docs/latest/starters/simpleapp.html">Simple App</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Demos & Tutorials</span> |
| <a class="navbar-item" href="../../../docs/latest/demo/about.html">Demo App</a> |
| <a class="navbar-item" href="https://danhaywood.gitlab.io/isis-petclinic-tutorial-docs/petclinic/1.16.2/intro.html">Petclinic (tutorial)</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Resources</span> |
| <a class="navbar-item" href="../../../docs/latest/resources/cheatsheet.html">Cheatsheet</a> |
| <a class="navbar-item" href="../../../docs/latest/resources/icons.html">Icons</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Guides</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">Development</span> |
| <a class="navbar-item" href="../../../setupguide/latest/about.html">Setup Guide</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Core</span> |
| <a class="navbar-item" href="../../../userguide/latest/about.html">User Guide</a> |
| <a class="navbar-item" href="../../../refguide/latest/about.html">Reference Guide</a> |
| <a class="navbar-item" href="../../../testing/latest/about.html">Testing Guide</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Libraries</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">For Use in Apps</span> |
| <a class="navbar-item" href="../../../subdomains/latest/about.html">Subdomain Libraries</a> |
| <a class="navbar-item" href="../../../valuetypes/latest/about.html">Value Types</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Integrate between Apps</span> |
| <a class="navbar-item" href="../../../mappings/latest/about.html">Bounded Context Mapping Libraries</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Other</span> |
| <a class="navbar-item" href="../../../incubator/latest/about.html">Incubator</a> |
| <a class="navbar-item" href="../../../legacy/latest/about.html">Legacy</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Components</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">Viewers</span> |
| <a class="navbar-item" href="../../../vw/latest/about.html">Wicket UI</a> |
| <a class="navbar-item" href="../../../vro/latest/about.html">Restful Objects (REST)</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Security</span> |
| <a class="navbar-item" href="../../../security/latest/about.html">Security Guide</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Persistence</span> |
| <a class="navbar-item" href="../../../pjdo/latest/about.html">DataNucleus (JDO)</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Extensions</span> |
| <a class="navbar-item" href="../../../extensions/latest/about.html">Extensions Catalog</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Support</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">Contact</span> |
| <a class="navbar-item" href="../../../docs/latest/support/slack-channel.html">Slack</a> |
| <a class="navbar-item" href="../../../docs/latest/support/mailing-list.html">Mailing Lists</a> |
| <a class="navbar-item" href="https://issues.apache.org/jira/browse/ISIS">JIRA</a> |
| <a class="navbar-item" href="https://stackoverflow.com/questions/tagged/isis">Stack Overflow</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Releases</span> |
| <a class="navbar-item" href="../../../docs/latest/downloads/how-to.html">Downloads</a> |
| <a class="navbar-item" href="../../../relnotes/latest/about.html">Release Notes</a> |
| <a class="navbar-item" href="../../../docs/latest/archive/1-x.html">Archive (1.x)</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Framework</span> |
| <a class="navbar-item" href="../../../conguide/latest/about.html">Contributors' Guide</a> |
| <a class="navbar-item" href="../../../comguide/latest/about.html">Committers' Guide</a> |
| <a class="navbar-item" href="../../../core/latest/about.html">Core Design</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">ASF</a> |
| <div class="navbar-dropdown"> |
| <a class="navbar-item" href="http://www.apache.org/">Apache Homepage</a> |
| <a class="navbar-item" href="https://www.apache.org/events/current-event">Events</a> |
| <a class="navbar-item" href="https://www.apache.org/licenses/">Licenses</a> |
| <a class="navbar-item" href="https://www.apache.org/security/">Security</a> |
| <a class="navbar-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a> |
| <a class="navbar-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a> |
| <hr class="navbar-divider"/> |
| <a class="navbar-item" href="https://whimsy.apache.org/board/minutes/Isis.html">PMC board minutes</a> |
| </div> |
| </div> |
| <a class="navbar-item" href="../../../docs/latest/about.html"> |
| <span class="icon"> |
| <img src="../../../_/img/home.png"></img> |
| </span> |
| </a> |
| </div> |
| </div> |
| </nav> |
| </header> |
| <div class="body "> |
| <div class="nav-container" data-component="userguide" data-version="2.0.0-M3"> |
| <aside class="nav"> |
| <div class="panels"> |
| <div class="nav-panel-pagination"> |
| <a class="page-previous" rel="prev" href="hints-and-tips.html" title="Hints-n-Tips"><span></span></a> |
| <a class="page-next" rel="next" |
| href="../flyway/about.html" title="Flyway"><span></span></a> |
| <!-- |
| page.parent doesn't seem to be set... |
| <a class="page-parent" rel="prev" href="about.html" title="Hints-n-Tips"><span></span></a> |
| --> |
| </div> |
| <div class="nav-panel-menu is-active" data-panel="menu"> |
| <nav class="nav-menu"> |
| <h3 class="title"><a href="../about.html">User Guide</a></h3> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="0"> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/concepts-patterns.html">Concepts & Patterns</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/overview.html">Overview</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/domain-entities-and-services.html">Domain Entities & Services</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/object-members.html">Object Members</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/ui.html">UI Layout & Hints</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/business-rules.html">Business Rules</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/drop-downs-and-defaults.html">Drop downs and Defaults</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/meta-annotations.html">Meta-annotations</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/view-models.html">View Models</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/mixins.html">Mixins</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../fun/modules.html">Modules</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="about.html">Beyond the Basics</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="i18n.html">i18n</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="headless-access.html">Headless Access</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="hints-and-tips.html">Hints-n-Tips</a> |
| </li> |
| <li class="nav-item is-current-page" data-depth="2"> |
| <a class="nav-link" href="programming-model.html">Programming Model</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Extensions</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../flyway/about.html">Flyway</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </nav> |
| </div> |
| <div class="nav-panel-explore" data-panel="explore"> |
| <div class="context"> |
| <span class="title">User Guide</span> |
| <span class="version">2.0.0-M3</span> |
| </div> |
| <ul class="components"> |
| <li class="component"> |
| <span class="title"> </span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../docs/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">BC Mappings Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../mappings/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Committers' Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../comguide/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Contributors' Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../conguide/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Design Docs</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../core/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Extensions Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../extensions/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Incubator Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../incubator/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">JDO/DataNucleus</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../pjdo/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Legacy Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../legacy/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Reference Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../refguide/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Release Notes</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../relnotes/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Restful Objects Viewer</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../vro/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Security Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../security/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Setup Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../setupguide/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Subdomains Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../subdomains/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Testing Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../testing/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component is-current"> |
| <span class="title">User Guide</span> |
| <ul class="versions"> |
| <li class="version is-current is-latest"> |
| <a href="../about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Value Types Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../valuetypes/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Wicket Viewer</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../vw/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </aside> |
| </div> |
| <main role="main"> |
| <div class="toolbar" role="navigation"> |
| <button class="nav-toggle"></button> |
| <a href="../../../docs/2.0.0-M3/about.html" class="home-link"></a> |
| <nav class="breadcrumbs" aria-label="breadcrumbs"> |
| <ul> |
| <li><a href="../about.html">User Guide</a></li> |
| <li><a href="about.html">Beyond the Basics</a></li> |
| <li><a href="programming-model.html">Programming Model</a></li> |
| </ul> |
| </nav> |
| <div class="edit-this-page"><a href="https://github.com/apache/isis/edit/2.0.0-M3/api/adoc/userguide/modules/btb/pages/programming-model.adoc">Edit</a></div> |
| </div> |
| <article class="doc"> |
| <a name="section-top"></a> |
| <h1 class="page">Customizing the Prog Model</h1> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This chapter explains the main APIs to extend or alter the programming conventions that Apache Isis understands to |
| build up its metamodel.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="custom-validator"><a class="anchor" href="#custom-validator"></a>Custom validator</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Apache Isis' programming model includes a validator component that detects and prevents (by failing fast) a number of situations where the domain model is logically inconsistent.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, the validator will detect any orphaned supporting methods (eg <code>hideXxx()</code>) if the corresponding property or action has been renamed or deleted but the supporting method was not also updated. |
| Another example is that a class cannot have a title specified both using <code>title()</code> method and also using <code>@Title</code> annotation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can also impose your own application-specific rules by installing your own metamodel validator. |
| To give just one example, you could impose naming standards such as ensuring that a domain-specific abbreviation such as "ISBN" is always consistently capitalized wherever it appears in a class member.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="api-and-implementation"><a class="anchor" href="#api-and-implementation"></a>API and Implementation</h3> |
| <div class="paragraph"> |
| <p>There are several ways to go about implementing a validator.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="metamodelvalidator"><a class="anchor" href="#metamodelvalidator"></a><code>MetaModelValidator</code></h4> |
| <div class="paragraph"> |
| <p>Any custom validator must implement Apache Isis' internal <code>MetaModelValidator</code> interface, so the simplest option is just to implement <code>MetaModelValidator</code> directly:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">package org.apache.isis.core.metamodel.specloader.validator; |
| |
| public interface MetaModelValidator { |
| |
| default void onFailure( |
| @NonNull FacetHolder facetHolder, <i class="conum" data-value="1"></i><b>(1)</b> |
| @NonNull Identifier deficiencyOrigin, <i class="conum" data-value="2"></i><b>(2)</b> |
| @NonNull String deficiencyMessageFormat, |
| Object ...args) { |
| |
| val deficiencyMessage = |
| String.format(deficiencyMessageFormat, args); |
| |
| DeficiencyFacet.appendTo( <i class="conum" data-value="3"></i><b>(3)</b> |
| facetHolder, deficiencyOrigin, deficiencyMessage); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="colist arabic"> |
| <table> |
| <tr> |
| <td><i class="conum" data-value="1"></i><b>1</b></td> |
| <td>represents an element of the metamodel, either an <code>ObjectSpecification</code> (domain class or mixin), or an <code>ObjectMember</code> (property, collection or action), or an <code>ObjectActionParameter</code>.</td> |
| </tr> |
| <tr> |
| <td><i class="conum" data-value="2"></i><b>2</b></td> |
| <td>identifier of the element</td> |
| </tr> |
| <tr> |
| <td><i class="conum" data-value="3"></i><b>3</b></td> |
| <td>appends the message into the <code>DeficiencyFacet</code> associated with the element.</td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>If the <code>onFailure</code> is called, then a message explaining the deficiency is stored.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The framework also provides a <code>MetaModelValidatorAbstract</code> that implements this interface. |
| However, it is the responsibility of the validator itself to figure out how to iterate over the entire model.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Since this is a common use case, the framework provides a more convenient and fine-grained "Visitor" API, discussed next.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="visitor"><a class="anchor" href="#visitor"></a><code>Visitor</code></h4> |
| <div class="paragraph"> |
| <p>More often than not, you’ll want to visit every element in the metamodel, and so for this you can instead subclass from <code>MetaModelValidatorVisiting.Visitor</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">package org.apache.isis.core.metamodel.specloader.validator; |
| |
| public final class MetaModelValidatorVisiting |
| extends MetaModelValidatorAbstract { |
| |
| public interface Visitor { |
| public boolean visit( <i class="conum" data-value="1"></i><b>(1)</b> |
| ObjectSpecification objectSpec, <i class="conum" data-value="2"></i><b>(2)</b> |
| ValidationFailures validationFailures); <i class="conum" data-value="3"></i><b>(3)</b> |
| } |
| |
| // ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="colist arabic"> |
| <table> |
| <tr> |
| <td><i class="conum" data-value="1"></i><b>1</b></td> |
| <td>return <code>true</code> continue visiting specs.</td> |
| </tr> |
| <tr> |
| <td><i class="conum" data-value="2"></i><b>2</b></td> |
| <td><code>ObjectSpecification</code> is the internal API representing a class</td> |
| </tr> |
| <tr> |
| <td><i class="conum" data-value="3"></i><b>3</b></td> |
| <td>add any metamodel violations to the <code>ValidationFailures</code> parameter</td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>If you have more than one rule then each can live in its own visitor.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="summarizingvisitor"><a class="anchor" href="#summarizingvisitor"></a><code>SummarizingVisitor</code></h4> |
| <div class="paragraph"> |
| <p>As a slight refinement, you can also subclass from <code>MetaModelValidatorVisiting.SummarizingVisitor</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">package org.apache.isis.core.metamodel.specloader.validator; |
| |
| public final class MetaModelValidatorVisiting |
| extends MetaModelValidatorAbstract { |
| |
| public interface SummarizingVisitor extends Visitor { |
| public void summarize(ValidationFailures validationFailures); |
| } |
| |
| // ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A <code>SummarizingVisitor</code> will be called once after every element in the metamodel has been visited. |
| This is great for performing checks on the metamodel as a whole.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="configuration"><a class="anchor" href="#configuration"></a>Configuration</h3> |
| <div class="paragraph"> |
| <p>Once you have implemented your validator, you must register it with the framework. |
| This is most easily done by implementing service that implements <code>MetaModelRefiner</code> service.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, some folk advocate that pattern names such as "Repository" or "Factory" should not appear in class names because they are not part of the <a href="../fun/concepts-patterns.html#ubiquitous-language" class="page">ubiquitous language</a>. |
| Such a rule could be verified using this implementation:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Service |
| public static class NoRepositorySuffixRefiner implements MetaModelRefiner { |
| @Override |
| public void refineProgrammingModel(ProgrammingModel programmingModel) { |
| programmingModel.addValidator(new MetaModelValidatorVisiting.Visitor() { |
| @Override |
| public boolean visit(ObjectSpecification objectSpec, MetaModelValidator validator) { |
| if(objectSpec.getSingularName().endsWith("Repository")) { |
| validator.onFailure(objectSpec, objectSpec.getIdentifier(), "Domain services may not have the suffix 'Repository'"); |
| } |
| return true; |
| } |
| }); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="finetuning"><a class="anchor" href="#finetuning"></a>Finetuning</h2> |
| <div class="sectionbody"> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-warning" title="Warning"></i> |
| </td> |
| <td class="content"> |
| TODO - v2 - not yet reviewed/updated. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>The core metamodel defines APIs and implementations for building the Apache Isis metamodel: a description of the set of entities, domain services and values that make up the domain model.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The description of each domain class consists of a number of elements:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java">ObjectSpecification</a></dt> |
| <dd> |
| <p>Analogous to <code>java.lang.Class</code>; holds information about the class itself and holds collections of each of the three types of class' members (below);</p> |
| </dd> |
| <dt class="hdlist1"><a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java">OneToOneAssociation</a></dt> |
| <dd> |
| <p>Represents a class member that is a single-valued property of the class. |
| The property’s type is either a reference to another entity, or is a value type.</p> |
| </dd> |
| <dt class="hdlist1"><a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToManyAssociation.java">OneToManyAssociation</a></dt> |
| <dd> |
| <p>Represents a class member that is a collection of references to other entities. |
| Note that Apache Isis does not currently support collections of values.</p> |
| </dd> |
| <dt class="hdlist1"><a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java">ObjectAction</a></dt> |
| <dd> |
| <p>Represents a class member that is an operation that can be performed on the action. |
| Returns either a single value, a collection of entities, or is <code>void</code>.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The metamodel is built up through the <a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodel/ProgrammingModel.java">ProgrammingModel</a>, which defines an API for registering a set of <a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactory.java">FacetFactory</a>s. |
| Two special <code>FacetFactory</code> implementations - <a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessorFactory.java">PropertyAccessorFacetFactory</a> and <a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessorFactory.java">CollectionAccessorFacetFactory</a> - are used to identify the class members. |
| Pretty much all the other <code>FacetFactory</code>s are responsible for installing <a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/Facet.java">Facet</a>s onto the metamodel elements.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There are many many such <code>Facet</code>s, and are used to do such things get values from properties or collections, modify properties or collections, invoke action, hide or disable class members, provide UI hints for class members, and so on. |
| In short, the <code>FacetFactory</code>s registered defines the Apache Isis programming conventions.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="modifying-the-prog-model"><a class="anchor" href="#modifying-the-prog-model"></a>Modifying the Prog. Model</h3> |
| <div class="paragraph"> |
| <p>The default implementation of <code>ProgrammingModel</code> is <a href="https://github.com/apache/isis/blob/master/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java">ProgrammingModelFacetsJava5</a>, which registers a large number of <code>FacetFactory</code>s.</p> |
| </div> |
| <div class="paragraph"> |
| <p>By editing <code>application.properties</code> you can modify the programming conventions either by (a) using the default programming model, but tweaking it to include new `FacetFactory`s or exclude existing, or (b) by specifying a completely different programming model implementation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Let’s see how this is done.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="including-or-excluding-facets"><a class="anchor" href="#including-or-excluding-facets"></a>Including or excluding facets</h4> |
| <div class="paragraph"> |
| <p>Suppose that you wanted to completely remove support for some existing facet, eg to support the "persisting()" and "persisted()" callback methods. |
| This would be done using:</p> |
| </div> |
| <div class="paragraph"> |
| <p>xref:refguide:config:sections/isis.core.meta-model.introspector.adoc#</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">isis.reflector.facets.exclude=\ |
| org.apache.isis.core.metamodel.facets.object.callbacks.PersistCallbackFacetFactory</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Or, suppose you wanted to use add some custom facet factory of your own, use:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">isis.reflector.facets.include=com.mycompany.isis.facets.MyCoolFacetFactory</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>To include/exclude more than one <code>FacetFactory</code>, specify as a comma-separated list.</p> |
| </div> |
| <div class="admonitionblock tip"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-tip" title="Tip"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>This <a href="http://isis.markmail.org/thread/472c3mrvcgnripst">thread</a> from the users mailing list (in Apr 2014) shows a typical customization (to enable per-instance security) (though note that <a href="about.html#multi-tenancy" class="page">Multi-Tenancy</a> is now a better solution to that particular use-case.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </article> |
| <aside class="article-aside toc" role="navigation"> |
| <p class="toc-title">On this page</p> |
| <div id="article-toc"></div> |
| </aside> |
| </main> |
| </div> |
| <footer class="footer"> |
| <div class="content"> |
| <div class="copyright"> |
| <p> |
| Copyright © 2010~2020 The Apache Software Foundation, licensed under the Apache License, v2.0. |
| <br/> |
| Apache, the Apache feather logo, Apache Isis, and the Apache Isis project logo are all trademarks of The Apache Software Foundation. |
| </p> |
| </div> |
| <div class="revision"> |
| <p>Revision: SNAPSHOT</p> |
| </div> |
| </div> |
| </footer> |
| <script src="../../../_/js/site.js"></script> |
| <script async src="../../../_/js/vendor/highlight.js"></script> |
| <script src="../../../_/js/vendor/jquery-3.4.1.min.js"></script> |
| <script src="../../../_/js/vendor/jquery-ui-1.12.1.custom.widget-only.min.js"></script> |
| <script src="../../../_/js/vendor/jquery.tocify.min.js"></script> |
| |
| <script> |
| $(function() { |
| $("#article-toc").tocify( { |
| showEffect: "slideDown", |
| hashGenerator: "pretty", |
| hideEffect: "slideUp", |
| selectors: "h2, h3", |
| scrollTo: 120, |
| smoothScroll: true, |
| theme: "jqueryui", |
| highlightOnScroll: true |
| } ); |
| }); |
| </script> |
| </body> |
| </html> |