[[default]]
= `default...()`

:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.



The `default...()` supporting method is called for action parameters to return the initial argument value.
This may be some sensible default (eg today's date, or 0 or 1), or -- for an action that is modifying the state of an object -- might default to the current value of a corresponding property.

The method is _also_ called for properties in the case when an object is newly instantiated using xref:refguide:applib:index/services/repository/RepositoryService.adoc[RepositoryService#detachedEntity(...)] or xref:refguide:applib:index/services/factory/FactoryService.adoc[FactoryService#create(...)].
This is a much less common use case.
If a default is not specified then properties are initialized to a default based on their type (eg 0 or `false`).

The signature of the supporting method depends on whether it is for an action parameter or a property.

== Parameters

For an action parameter in (0-based position n), and of type `T`, the signature is:

[source,java]
----
public T defaultNXxx() {
    // ...
}
----

For example:

[source,java]
----
import lombok.Getter;
import lombok.Setter;

public class ShoppingCartItem {

    @Property(editing=Editing.DISABLED)
    @Getter @Setter
    private Product product;

    @Property(editing=Editing.DISABLED)
    @Getter @Setter
    private int quantity;

    @Action(semantics=SemanticsOf.IDEMPOTENT)
    public ShoppingCartItem updateProduct(
                                Product product,
                                final Integer quantity) {
        // ...
    }

    public Product default0UpdateProduct() {    // <.>
        return getProduct();
    }
    public int default1UpdateProduct() {        // <.>
        return getQuantity();
    }

    // ...
}
----
<.> default the 0-th parameter using the current value of the `product` property
<.> default the 1-th parameter using the current value of the `quantity` property


If implemented as a mixin xref:userguide:fun:mixins.adoc#contributed-action[contributed action], the code would look something like:

Defaults are also supported (of course) for xref:userguide:fun:mixins.adoc#contributed-action[contributed actions].
For example, here is a contributed action for updating category/subcategory of a `ToDoItem`:

[source,java]
----
public class ToDoItem {

    @Action(semantics = SemanticsOf.IDEMPOTENT)
    @ActionLayout(
            describedAs = "Update category and subcategory"
    )
    public class updateCategory {
        public ToDoItem act(
                final Category category,
                @Nullable
                final Subcategory subcategory) {
            item.setCategory(category);
            item.setSubcategory(subcategory);
            return ToDoItem.this;
        }
        // ...
        public Category default1UpdateCategory(        // <.>
                final Categorized item) {
            return ToDoItem.this.getCategory();
        }
        public Subcategory default2UpdateCategory(     // <.>
                final Categorized item) {
            return ToDoItem.this.getSubcategory();
        }
    }
}
----
<.> defaults the 0-th parameter using the item's `category` property
<.> defaults the 1-th parameter using the item's `subcategory` property

=== Dependent Defaults

Action parameters also support the notion of dependent defaults, whereby the value of a default is dependent upon the value of some other previous argument.

In this example we can default the `gross` argument based on the previous `net` and `vat` arguments:

[source,java]
----
public int add(final Integer net, final Integer vat, final Integer gross) {
    return net + vat;
}

public Integer default2Add(final Integer net, final Integer val) {
    if(net == null || val == null) { return null; }
    return net + val;
}
----

By default, this default will be re-evaluated every time the value of an earlier parameter (parameters #0 or #1 in the above example) are changed.

However, suppose that an end-user changes parameter 0 (which defaults parameter 1), then changes parameter 1 itself, then goes back to change parameter 0.
This could end up with their changes to parameter 1 being overwritten.
This is possibly less than desirable.

The xref:refguide:applib:index/annotation/Action.adoc#dependent-defaults-policy[@Action#dependentDefaultsPolicy()] parameter can be used to change this behaviour; if set to `PRESERVE_CHANGES` then the value of a parameter will never be overwritten if the end-user has changed it.

If you prefer, the xref:refguide:config:sections/isis.applib.adoc#isis.applib.annotation.action.dependent-defaults-policy[isis.applib.annotation.action.dependent-defaults-policy] configuration property can be used to change the behaviour for _all_ actions.

== Properties

For a property of type `T`, the signature is:

[source,java]
----
public T defaultXxx() {
    // ...
}
----

For example:

[source,java]
----
import lombok.Getter;
import lombok.Setter;

public class ShoppingCartItem {

    @Getter @Setter
    private int quantity;

    public int defaultQuantity() {
        return 1;
    }

    // ...
}
----

=== Alternatives

There are, in fact, two other ways to set properties of a newly instantiated object to default values.

The first is to use the xref:refguide:applib-methods:lifecycle.adoc#created[created()] callback, called by the framework when xref:refguide:applib:index/services/repository/RepositoryService.adoc[RepositoryService#detachedEntity(...)] or xref:refguide:applib:index/services/factory/FactoryService.adoc[FactoryService#create(...)] is called.
This method is called after any services have been injected into the domain object.

The second is more straightforward: simply initialize properties in the constructor.
However, this cannot use any injected services as they will not have been initialized.

