/** * 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 org.apache.isis.applib.services.command; import java.sql.Timestamp; import org.apache.isis.applib.Identifier; import org.apache.isis.applib.annotation.Action; import org.apache.isis.applib.annotation.Command.ExecuteIn; import org.apache.isis.applib.annotation.Command.Persistence; import org.apache.isis.applib.annotation.Optional; import org.apache.isis.applib.annotation.Programmatic; import org.apache.isis.applib.clock.Clock; import org.apache.isis.applib.services.HasTransactionId; import org.apache.isis.applib.services.background.BackgroundCommandService; import org.apache.isis.applib.services.background.BackgroundService; import org.apache.isis.applib.services.bookmark.Bookmark; import org.apache.isis.applib.services.bookmark.BookmarkService; import org.apache.isis.applib.services.eventbus.ActionDomainEvent; import org.apache.isis.applib.services.iactn.Interaction; import org.apache.isis.applib.services.publish.EventMetadata; import org.apache.isis.applib.services.publish.EventPayload; import org.apache.isis.applib.services.wrapper.WrapperFactory; import org.apache.isis.schema.cmd.v1.CommandDto; /** * Represents the <i>intention to</i> invoke either an action or modify a property. This intention is reified as a * {@link Command#getMemento() memento} by way of the (internal) <tt>CommandDtoServiceInternal</tt> domain service; * typically corresponding to the XML equivalent of a {@link CommandDto}. * * <p> * The {@link Command} interface also captures details of the corresponding action invocation (or property edit), * specifically when that action/edit {@link Command#getStartedAt() started} or * {@link Command#getCompletedAt() completed}, and its result, either a {@link Command#getResult() return value} * or an {@link Command#getException() exception}. The {@link Command3} sub-interface also captures the stack * of {@link ActionDomainEvent}s. * </p> * * <p> * Note that when invoking an action, other actions may be invoked courtesy of the {@link WrapperFactory}. These * "sub-actions" do <i>not</i> modify the contents of the command object; in other words think of the command * object as representing the outer-most originating action. * </p> * * <p> * One of the responsibilities of the command is to generate unique sequence numbers for a given transactionId. * This is done by {@link #next(String)}. There are three possible sequences that might be generated: * the sequence of changed domain objects being published by the {@link org.apache.isis.applib.services.publish.PublishingService#publish(EventMetadata, EventPayload)}; the * sequence of wrapped action invocations (each being published), and finally one or more background commands * that might be scheduled via the {@link BackgroundService}. * </p> * */ public interface Command extends HasTransactionId { /** * @deprecated - in previous versions this was the value for {@link #getTargetAction()} if this command represents an edit of an object's property (rather than an action); now though the property's name is used (ie same as actions). */ @Deprecated String ACTION_IDENTIFIER_FOR_EDIT = "(edit)"; //region > user (property) /** * The user that created the command. */ String getUser(); /** * <b>NOT API</b>: intended to be called only by the framework. * * <p> * Implementation notes: set when the Isis PersistenceSession is opened. */ void setUser(String user); //endregion //region > timestamp (property) /** * The date/time at which this command was created. */ Timestamp getTimestamp(); /** * <b>NOT API</b>: intended to be called only by the framework. * * <p> * Implementation notes: set when the Isis PersistenceSession is opened. Uses the applib {@link Clock}. */ void setTimestamp(Timestamp timestamp); //endregion //region > target (property) /** * {@link Bookmark} of the target object (entity or service) on which this action was performed. * * <p> * Will only be populated if a {@link BookmarkService} has been configured. */ Bookmark getTarget(); /** * <b>NOT API</b>: intended to be called only by the framework. * * <p> * Implementation notes: set when the action is invoked (in the ActionInvocationFacet). */ void setTarget(Bookmark target); //endregion //region > memberIdentifier (property) /** * Holds a string representation of the invoked action, or the edited property, equivalent to * {@link Identifier#toClassAndNameIdentityString()}. */ String getMemberIdentifier(); /** * <b>NOT API</b>: intended to be called only by the framework. * * <p> * Implementation notes: set when the action is invoked (in <tt>ActionInvocationFacet</tt>) or in * property edited (in <tt>PropertySetterFacet</tt>). */ void setMemberIdentifier(String memberIdentifier); //endregion //region > targetClass (property) /** * A human-friendly description of the class of the target object. */ String getTargetClass(); /** * <b>NOT API</b>: intended to be called only by the framework. * * <p> * Implementation notes: set when the action is invoked (in the <tt>ActionInvocationFacet</t>). */ void setTargetClass(String targetClass); //endregion //region > targetAction (property) /** * The human-friendly name of the action invoked/property edited on the target object. * * <p> * NB: in earlier versions, if the command represented an edit of a property, then it held the special value "{@value ACTION_IDENTIFIER_FOR_EDIT}". This is NO LONGER the case; it simply holds the member. * </p> */ String getTargetAction(); /** * <b>NOT API</b>: intended to be called only by the framework. * * <p> * Implementation notes: set when the action is invoked (in the <tt>ActionInvocationFacet</tt>) or property edited * (in the <tt>PropertySetterOrClearFacet</tt>). */ void setTargetAction(String targetAction); //endregion //region > arguments (property) /** * A human-friendly description of the arguments with which the action was invoked. */ String getArguments(); /** * <b>NOT API</b>: intended to be called only by the framework. * * <p> * Implementation notes: set when the action is invoked (in the <tt>ActionInvocationFacet</tt>). */ void setArguments(final String arguments); //endregion //region > memento (property) /** * A formal (XML or similar) specification of the action to invoke/being invoked. */ String getMemento(); /** * <b>NOT API</b>: intended to be called only by the framework. * * <p> * Implementation notes: set when the action is invoked (in the <tt>ActionInvocationFacet</tt>). */ void setMemento(final String memento); //endregion //region > executeIn (property) /** * The mechanism by which this command is to be executed, either synchronously "in the * {@link ExecuteIn#FOREGROUND foreground}" or is to be executed asynchronously "in the * {@link ExecuteIn#BACKGROUND background}" through the {@link BackgroundCommandService}. */ ExecuteIn getExecuteIn(); /** * <b>NOT API</b>: intended to be called only by the framework. */ void setExecuteIn(final ExecuteIn executeIn); //endregion //region > executor (property) enum Executor { /** * Command being executed by the end-user. */ USER, /** * Command being executed by a background execution service. */ BACKGROUND, /** * Command being executed for some other reason, eg as result of redirect-after-post, or the homePage action. */ OTHER } /** * The (current) executor of this command. * * <p> * Note that (even for implementations of {@link BackgroundCommandService} that persist {@link Command}s), this * property is never (likely to be) persisted, because it is always updated to indicate how the command is * currently being executed. * * <p> * If the {@link #getExecutor() executor} matches the required {@link #getExecuteIn() execution policy}, then the * command actually is executed. The combinations are: * <ul> * <li>executor = USER, executeIn = FOREGROUND, then execute</li> * <li>executor = USER, executeIn = BACKGROUND, then persist and return persisted command as a placeholder for the result</li> * <li>executor = BACKGROUND, executeIn = FOREGROUND, then ignore</li> * <li>executor = BACKGROUND, executeIn = BACKGROUND, then execute, update the command with result</li> * </ul> * */ Executor getExecutor(); /** * <b>NOT API</b>: intended to be called only by the framework. */ void setExecutor(final Executor executor); //endregion //region > startedAt (property, deprecated) /** * For an command that has actually been executed, holds the date/time at which the {@link Interaction} that * executed the command started. * * @deprecated - see {@link Interaction#getStartedAt()}. */ @Deprecated Timestamp getStartedAt(); /** * <b>NOT API</b>: intended to be called only by the framework. * * @deprecated - see {@link Interaction#getCurrentExecution()} and {@link org.apache.isis.applib.services.iactn.Interaction.Execution#setStartedAt(Timestamp)}. */ @Deprecated void setStartedAt(Timestamp startedAt); //endregion //region > completedAt (property, deprecated) /** * For an command that has actually been executed, holds the date/time at which the {@link Interaction} that * executed the command completed. * * @deprecated - see {@link Interaction#getCurrentExecution()} and {@link org.apache.isis.applib.services.iactn.Interaction.Execution#getCompletedAt()}. */ @Deprecated Timestamp getCompletedAt(); /** * <b>NOT API</b>: intended to be called only by the framework. * * @deprecated - see {@link org.apache.isis.applib.services.iactn.Interaction.Execution#setCompletedAt(Timestamp)}. */ @Deprecated void setCompletedAt(Timestamp completedAt); //endregion //region > parent (property) /** * For actions created through the {@link BackgroundService} and {@link BackgroundCommandService}, * captures the parent action. */ Command getParent(); /** * <b>NOT API</b>: intended to be called only by the framework. */ void setParent(final Command parent); //endregion //region > exception (property, deprecated) /** * For an command that has actually been executed, holds the exception stack * trace if the action invocation/property modification threw an exception. * * @deprecated - see {@link Interaction#getCurrentExecution()} and {@link org.apache.isis.applib.services.iactn.Interaction.Execution#getThrew()} instead. */ @Deprecated @Optional String getException(); /** * <b>NOT API</b>: intended to be called only by the framework. */ void setException(String stackTrace); //endregion //region > result (property, deprecated) /** * For an command that has actually been executed, holds a {@link Bookmark} to the object returned by the corresponding action/property modification. * * @deprecated - see {@link Interaction#getCurrentExecution()} and {@link org.apache.isis.applib.services.iactn.Interaction.Execution#getReturned()} instead. */ @Deprecated Bookmark getResult(); /** * <b>NOT API</b>: intended to be called only by the framework. */ void setResult(Bookmark resultBookmark); //endregion //region > persistence (property) /** * Whether this command should ultimately be persisted (if the configured {@link BackgroundCommandService} supports * it) or not. * * <p> * If the action to be executed has been annotated with the {@link Action#command()} attribute * then (unless its {@link Action#commandPersistence()} persistence} attribute has been set to a different value * than its default of {@link org.apache.isis.applib.annotation.CommandPersistence#PERSISTED persisted}), the * {@link Command} object will be persisted. * * <p> * However, it is possible to prevent the {@link Command} object from ever being persisted by setting the * {@link org.apache.isis.applib.annotation.Action#commandPersistence() persistence} attribute to * {@link org.apache.isis.applib.annotation.CommandPersistence#NOT_PERSISTED}, or it can be set to * {@link org.apache.isis.applib.annotation.CommandPersistence#IF_HINTED}, meaning it is dependent * on whether {@link #setPersistHint(boolean) a hint has been set} by some other means. * * <p> * For example, a {@link BackgroundCommandService} implementation that creates persisted background commands ought * associate them (via its {@link Command#getParent() parent}) to an original persisted * {@link Command}. The hinting mechanism allows the service to suggest that the parent command be persisted so * that the app can then provide a mechanism to find all child background commands for that original parent command. */ Persistence getPersistence(); /** * <b>NOT API</b>: intended to be called only by the framework. */ void setPersistence(final Persistence persistence); //endregion //region > persistHint (programmatic) /** * Whether that this {@link Command} should be persisted, if possible. */ @Programmatic boolean isPersistHint(); /** * Hint that this {@link Command} should be persisted, if possible. * * <p> * <b>NOT API</b>: intended to be called only by the framework. * * @see #getPersistence() */ @Programmatic void setPersistHint(boolean persistHint); //endregion //region > next (programmatic, deprecated) /** * <b>NOT API</b>: intended to be called only by the framework. * * @deprecated - no longer used (the framework uses {@link Interaction#next(String)} instead). */ @Deprecated @Programmatic int next(final String sequenceAbbr); //endregion }