001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.isis.core.metamodel.spec.feature; 021 022import java.util.List; 023import com.google.common.base.Predicate; 024import com.google.common.base.Strings; 025import org.apache.isis.applib.annotation.ActionSemantics; 026import org.apache.isis.applib.annotation.Bulk; 027import org.apache.isis.applib.annotation.When; 028import org.apache.isis.applib.annotation.Where; 029import org.apache.isis.applib.filter.Filter; 030import org.apache.isis.applib.value.Blob; 031import org.apache.isis.applib.value.Clob; 032import org.apache.isis.core.commons.authentication.AuthenticationSession; 033import org.apache.isis.core.metamodel.adapter.ObjectAdapter; 034import org.apache.isis.core.metamodel.consent.Consent; 035import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod; 036import org.apache.isis.core.metamodel.facetapi.Facet; 037import org.apache.isis.core.metamodel.facetapi.FacetFilters; 038import org.apache.isis.core.metamodel.facets.hide.HiddenFacet; 039import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet; 040import org.apache.isis.core.metamodel.facets.named.NamedFacet; 041import org.apache.isis.core.metamodel.interactions.AccessContext; 042import org.apache.isis.core.metamodel.interactions.ActionInvocationContext; 043import org.apache.isis.core.metamodel.interactions.ValidatingInteractionAdvisor; 044import org.apache.isis.core.metamodel.spec.ActionType; 045import org.apache.isis.core.metamodel.spec.ObjectSpecification; 046import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacet; 047 048public interface ObjectAction extends ObjectMember { 049 050 // ////////////////////////////////////////////////////// 051 // semantics, realTarget, getOnType 052 // ////////////////////////////////////////////////////// 053 054 /** 055 * The semantics of this action. 056 */ 057 ActionSemantics.Of getSemantics(); 058 059 /** 060 * Returns the specification for the type of object that this action can be 061 * invoked upon. 062 */ 063 ObjectSpecification getOnType(); 064 065 066 boolean promptForParameters(ObjectAdapter target); 067 068 // ////////////////////////////////////////////////////////////////// 069 // Type 070 // ////////////////////////////////////////////////////////////////// 071 072 ActionType getType(); 073 074 // ////////////////////////////////////////////////////////////////// 075 // ReturnType 076 // ////////////////////////////////////////////////////////////////// 077 078 /** 079 * Returns the specifications for the return type. 080 */ 081 ObjectSpecification getReturnType(); 082 083 /** 084 * Returns <tt>true</tt> if the represented action returns a non-void object, 085 * else returns false. 086 */ 087 boolean hasReturn(); 088 089 // ////////////////////////////////////////////////////////////////// 090 // execute 091 // ////////////////////////////////////////////////////////////////// 092 093 /** 094 * Invokes the action's method on the target object given the specified set 095 * of parameters. 096 */ 097 ObjectAdapter execute(ObjectAdapter target, ObjectAdapter[] parameters); 098 099 // ////////////////////////////////////////////////////////////////// 100 // valid 101 // ////////////////////////////////////////////////////////////////// 102 103 /** 104 * Creates an {@link ActionInvocationContext interaction context} 105 * representing an attempt to invoke this action. 106 * 107 * <p> 108 * Typically it is easier to just call 109 * {@link #isProposedArgumentSetValid(ObjectAdapter, ObjectAdapter[]) 110 * 111 * @link #isProposedArgumentSetValidResultSet(ObjectAdapter, 112 * ObjectAdapter[])}; this is provided as API for symmetry with 113 * interactions (such as {@link AccessContext} accesses) have no 114 * corresponding vetoing methods. 115 */ 116 public ActionInvocationContext createActionInvocationInteractionContext(AuthenticationSession session, InteractionInvocationMethod invocationMethod, ObjectAdapter targetObject, ObjectAdapter[] proposedArguments); 117 118 /** 119 * Whether the provided argument set is valid, represented as a 120 * {@link Consent}. 121 */ 122 Consent isProposedArgumentSetValid(ObjectAdapter object, ObjectAdapter[] proposedArguments); 123 124 // ////////////////////////////////////////////////////// 125 // Parameters (declarative) 126 // ////////////////////////////////////////////////////// 127 128 /** 129 * Returns the number of parameters used by this method. 130 */ 131 int getParameterCount(); 132 133 /** 134 * Returns set of parameter information. 135 * 136 * <p> 137 * Implementations may build this array lazily or eagerly as required. 138 * 139 * @return 140 */ 141 List<ObjectActionParameter> getParameters(); 142 143 /** 144 * Returns the {@link ObjectSpecification type} of each of the 145 * {@link #getParameters() parameters}. 146 */ 147 List<ObjectSpecification> getParameterTypes(); 148 149 /** 150 * Returns set of parameter information matching the supplied filter. 151 * 152 * @return 153 */ 154 List<ObjectActionParameter> getParameters( 155 @SuppressWarnings("deprecation") Filter<ObjectActionParameter> filter); 156 157 /** 158 * Returns the parameter with provided id. 159 */ 160 ObjectActionParameter getParameterById(String paramId); 161 162 /** 163 * Returns the parameter with provided name. 164 */ 165 ObjectActionParameter getParameterByName(String paramName); 166 167 // ////////////////////////////////////////////////////// 168 // Parameters (per instance) 169 // ////////////////////////////////////////////////////// 170 171 /** 172 * Returns the defaults references/values to be used for the action. 173 */ 174 ObjectAdapter[] getDefaults(ObjectAdapter target); 175 176 /** 177 * Returns a list of possible references/values for each parameter, which 178 * the user can choose from. 179 */ 180 ObjectAdapter[][] getChoices(ObjectAdapter target); 181 182 183 // ////////////////////////////////////////////////////// 184 // Utils 185 // ////////////////////////////////////////////////////// 186 187 public static final class Utils { 188 189 private Utils() { 190 } 191 192 public static String nameFor(final ObjectAction objAction) { 193 final String actionName = objAction.getName(); 194 if (actionName != null) { 195 return actionName; 196 } 197 final NamedFacet namedFacet = objAction.getFacet(NamedFacet.class); 198 if (namedFacet != null) { 199 return namedFacet.value(); 200 } 201 return "(no name)"; 202 } 203 } 204 205 206 // ////////////////////////////////////////////////////// 207 // Predicates 208 // ////////////////////////////////////////////////////// 209 210 public static final class Predicates { 211 212 private Predicates(){} 213 214 public static final Predicate<ObjectAction> VISIBLE_AT_LEAST_SOMETIMES = 215 org.apache.isis.applib.filter.Filters.asPredicate(Filters.VISIBLE_AT_LEAST_SOMETIMES); 216 217 public static Predicate<ObjectAction> dynamicallyVisible(final AuthenticationSession session, final ObjectAdapter target, final Where where) { 218 return org.apache.isis.applib.filter.Filters.asPredicate(Filters.dynamicallyVisible(session, target, where)); 219 } 220 221 public static Predicate<ObjectAction> withId(final String actionId) { 222 return org.apache.isis.applib.filter.Filters.asPredicate(Filters.withId(actionId)); 223 } 224 225 public static Predicate<ObjectAction> withNoValidationRules() { 226 return org.apache.isis.applib.filter.Filters.asPredicate(Filters.withNoValidationRules()); 227 } 228 229 public static Predicate<ObjectAction> ofType(final ActionType type) { 230 return org.apache.isis.applib.filter.Filters.asPredicate(Filters.ofType(type)); 231 } 232 233 public static Predicate<ObjectAction> bulk() { 234 return org.apache.isis.applib.filter.Filters.asPredicate(Filters.bulk()); 235 } 236 237 public static Predicate<ObjectAction> notBulkOnly() { 238 return org.apache.isis.applib.filter.Filters.asPredicate(Filters.notBulkOnly()); 239 } 240 241 public static Predicate<ObjectAction> memberOrderOf(ObjectAssociation association) { 242 return org.apache.isis.applib.filter.Filters.asPredicate(Filters.memberOrderOf(association)); 243 } 244 } 245 246 247 // ////////////////////////////////////////////////////// 248 // Filters 249 // ////////////////////////////////////////////////////// 250 251 252 public static final class Filters { 253 254 private Filters(){} 255 256 /** 257 * @deprecated -use {@link com.google.common.base.Predicate equivalent} 258 */ 259 @Deprecated 260 public static final Filter<ObjectAction> VISIBLE_AT_LEAST_SOMETIMES = new Filter<ObjectAction>() { 261 @Override 262 public boolean accept(final ObjectAction action) { 263 final HiddenFacet hiddenFacet = action.getFacet(HiddenFacet.class); 264 return hiddenFacet == null || hiddenFacet.when() != When.ALWAYS || hiddenFacet.where() != Where.ANYWHERE; 265 } 266 }; 267 268 /** 269 * @deprecated -use {@link com.google.common.base.Predicate equivalent} 270 */ 271 @Deprecated 272 public static Filter<ObjectAction> dynamicallyVisible(final AuthenticationSession session, final ObjectAdapter target, final Where where) { 273 return new Filter<ObjectAction>() { 274 @Override 275 public boolean accept(final ObjectAction objectAction) { 276 final Consent visible = objectAction.isVisible(session, target, where); 277 return visible.isAllowed(); 278 } 279 }; 280 } 281 282 /** 283 * @deprecated -use {@link com.google.common.base.Predicate equivalent} 284 */ 285 @Deprecated 286 public static Filter<ObjectAction> withId(final String actionId) { 287 return new Filter<ObjectAction>(){ 288 @Override 289 public boolean accept(ObjectAction objectAction) { 290 return objectAction.getId().equals(actionId); 291 } 292 }; 293 } 294 295 /** 296 * @deprecated -use {@link com.google.common.base.Predicate equivalent} 297 */ 298 @Deprecated 299 public static Filter<ObjectAction> withNoValidationRules() { 300 return new Filter<ObjectAction>(){ 301 @Override 302 public boolean accept(final ObjectAction objectAction) { 303 final List<Facet> validatingFacets = objectAction.getFacets(FacetFilters.isA(ValidatingInteractionAdvisor.class)); 304 return validatingFacets.isEmpty(); 305 }}; 306 } 307 308 /** 309 * @deprecated -use {@link com.google.common.base.Predicate equivalent} 310 */ 311 @Deprecated 312 public static Filter<ObjectAction> ofType(final ActionType type) { 313 return new Filter<ObjectAction>(){ 314 @Override 315 public boolean accept(ObjectAction oa) { 316 return oa.getType() == type; 317 } 318 }; 319 } 320 321 /** 322 * @deprecated -use {@link com.google.common.base.Predicate equivalent} 323 */ 324 @Deprecated 325 public static Filter<ObjectAction> bulk() { 326 return new Filter<ObjectAction>(){ 327 328 @Override 329 public boolean accept(ObjectAction oa) { 330 if( !oa.containsDoOpFacet(BulkFacet.class)) { 331 return false; 332 } 333 if (oa.getParameterCount() != 0) { 334 return false; 335 } 336 337 // currently don't support returning Blobs or Clobs 338 // (because haven't figured out how to rerender the current page, but also to do a download) 339 ObjectSpecification returnSpec = oa.getReturnType(); 340 if(returnSpec != null) { 341 Class<?> returnType = returnSpec.getCorrespondingClass(); 342 if(returnType == Blob.class || returnType == Clob.class) { 343 return false; 344 } 345 } 346 return true; 347 }}; 348 } 349 350 /** 351 * @deprecated -use {@link com.google.common.base.Predicate equivalent} 352 */ 353 @Deprecated 354 public static Filter<ObjectAction> notBulkOnly() { 355 return new Filter<ObjectAction>(){ 356 357 @Override 358 public boolean accept(ObjectAction t) { 359 BulkFacet facet = t.getFacet(BulkFacet.class); 360 return facet == null || facet.value() != Bulk.AppliesTo.BULK_ONLY; 361 }}; 362 } 363 364 365 @SuppressWarnings("deprecation") 366 public static Filter<ObjectAction> memberOrderOf(ObjectAssociation association) { 367 final String assocName = association.getName(); 368 final String assocId = association.getId(); 369 return new Filter<ObjectAction>() { 370 371 @Override 372 public boolean accept(ObjectAction t) { 373 final MemberOrderFacet memberOrderFacet = t.getFacet(MemberOrderFacet.class); 374 if(memberOrderFacet == null) { 375 return false; 376 } 377 final String memberOrderName = memberOrderFacet.name(); 378 if(Strings.isNullOrEmpty(memberOrderName)) { 379 return false; 380 } 381 return memberOrderName.equalsIgnoreCase(assocName) || memberOrderName.equalsIgnoreCase(assocId); 382 } 383 }; 384 } 385 } 386}