/**
   * Either creates a link for the action be rendered in a {@link ModalWindow}, or (if none can be
   * {@link ActionPromptProvider#getActionPrompt() provided}, or creates a link to the {@link
   * ActionPromptPage} (ie the {@link PageClassRegistry registered page} for {@link
   * PageType#ACTION_PROMPT action}s).
   *
   * <p>If the action's {@link ObjectAction#getSemantics() semantics} are {@link
   * ActionSemantics.Of#SAFE safe}, then concurrency checking is disabled; otherwise it is enforced.
   */
  protected AbstractLink newLink(
      final String linkId,
      final ObjectAdapter objectAdapter,
      final ObjectAction action,
      final ActionPromptProvider actionPromptProvider) {

    final ActionPrompt actionPrompt = actionPromptProvider.getActionPrompt();
    if (actionPrompt != null) {
      final ActionModel actionModel = ActionModel.create(objectAdapter, action);
      actionModel.setActionPrompt(actionPrompt);
      AjaxLink<Object> link =
          new AjaxLink<Object>(linkId) {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(AjaxRequestTarget target) {

              final ActionPanel actionPromptPanel =
                  (ActionPanel)
                      getComponentFactoryRegistry()
                          .createComponent(
                              ComponentType.ACTION_PROMPT,
                              actionPrompt.getContentId(),
                              actionModel);

              actionPrompt.setPanel(actionPromptPanel, target);
              actionPrompt.show(target);

              target.focusComponent(actionPromptPanel);
            }
          };
      link.add(new CssClassAppender("noVeil"));
      return link;

    } else {

      // use the action semantics to determine whether invoking this action will require a
      // concurrency check or not
      // if it's "safe", then we'll just continue without any checking.
      final ConcurrencyChecking concurrencyChecking =
          ConcurrencyChecking.concurrencyCheckingFor(action.getSemantics());
      final PageParameters pageParameters =
          ActionModel.createPageParameters(objectAdapter, action, concurrencyChecking);
      final Class<? extends Page> pageClass =
          getPageClassRegistry().getPageClass(PageType.ACTION_PROMPT);
      AbstractLink link = Links.newBookmarkablePageLink(linkId, pageParameters, pageClass);

      // special case handling if this a no-arg action is returning a URL
      if (action.getParameterCount() == 0) {
        addTargetBlankIfActionReturnsUrl(link, action);
      }

      return link;
    }
  }
Ejemplo n.º 2
0
 // unused
 static String roSpecForResponseOf(final ObjectAction action) {
   final ActionSemantics.Of semantics = action.getSemantics();
   switch (semantics) {
     case SAFE_AND_REQUEST_CACHEABLE:
     case SAFE:
       return "19.2";
     case IDEMPOTENT:
     case IDEMPOTENT_ARE_YOU_SURE:
       return "19.3";
     default:
       return "19.4";
   }
 }
Ejemplo n.º 3
0
  /**
   * Invokes the action for the object (checking it is visible) and then delegates to the {@link
   * org.apache.isis.viewer.restfulobjects.rendering.service.RepresentationService} to render a
   * representation of the result of that action.
   *
   * <p>The action must have {@link org.apache.isis.applib.annotation.ActionSemantics.Of#IDEMPOTENT
   * idempotent} semantics otherwise an error response is thrown.
   */
  public Response invokeActionIdempotent(
      final String actionId, final JsonRepresentation arguments) {

    final ObjectAdapterAccessHelper accessHelper =
        new ObjectAdapterAccessHelper(representationServiceContext, objectAdapter);

    final ObjectAction action =
        accessHelper.getObjectActionThatIsVisibleForIntent(
            actionId, ObjectAdapterAccessHelper.Intent.MUTATE);

    final ActionSemantics.Of actionSemantics = action.getSemantics();
    if (!actionSemantics.isIdempotentInNature()) {
      throw RestfulObjectsApplicationException.createWithMessage(
          RestfulResponse.HttpStatusCode.METHOD_NOT_ALLOWED,
          "Method not allowed; action '%s' is not idempotent",
          action.getId());
    }
    return invokeActionUsingAdapters(action, arguments, ActionResultReprRenderer.SelfLink.EXCLUDED);
  }
Ejemplo n.º 4
0
  /**
   * Synthesises {@link ObjectAssociation}s from matching {@link ObjectAction}s of any of the
   * services that accept one parameter
   */
  private List<ObjectAssociation> createContributeeAssociations(
      final ObjectAdapter serviceAdapter) {

    final ObjectSpecification specification = serviceAdapter.getSpecification();
    final List<ObjectAction> serviceActions =
        specification.getObjectActions(
            ActionType.USER, Contributed.INCLUDED, Filters.<ObjectAction>any());

    final List<ObjectActionImpl> contributedActions = Lists.newArrayList();
    for (final ObjectAction serviceAction : serviceActions) {
      if (isAlwaysHidden(serviceAction)) {
        continue;
      }
      final NotContributedFacet notContributed = serviceAction.getFacet(NotContributedFacet.class);
      if (notContributed != null && notContributed.toAssociations()) {
        continue;
      }
      if (!serviceAction.hasReturn()) {
        continue;
      }
      if (serviceAction.getParameterCount() != 1
          || contributeeParameterMatchOf(serviceAction) == -1) {
        continue;
      }
      if (!(serviceAction instanceof ObjectActionImpl)) {
        continue;
      }
      if (!serviceAction.getSemantics().isSafeInNature()) {
        continue;
      }
      contributedActions.add((ObjectActionImpl) serviceAction);
    }

    return Lists.newArrayList(
        Iterables.transform(
            contributedActions, createContributeeAssociationFunctor(serviceAdapter, this)));
  }
Ejemplo n.º 5
0
  void appendObjectActionInvokePath(
      final ObjectSpecification objectSpec, final ObjectAction objectAction) {

    final String objectType = objectTypeFor(objectSpec);
    final String actionId = objectAction.getId();

    final List<ObjectActionParameter> parameters = objectAction.getParameters();
    final Path path = new Path();
    swagger.path(
        String.format("/objects/%s/{objectId}/actions/%s/invoke", objectType, actionId), path);

    final String tag = tagFor(objectType, null);
    final Operation invokeOperation =
        new Operation()
            .tag(tag)
            .description(
                Util.roSpec("19.1") + ": (invoke) resource of " + objectType + "#" + actionId)
            .parameter(new PathParameter().name("objectId").type("string"))
            .produces("application/json;profile=urn:org.apache.isis/v1")
            .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true")
            .produces("application/json;profile=urn:org.restfulobjects:repr-types/action-result");

    final ActionSemantics.Of semantics = objectAction.getSemantics();
    if (semantics.isSafeInNature()) {
      path.get(invokeOperation);

      for (final ObjectActionParameter parameter : parameters) {
        invokeOperation.parameter(
            new QueryParameter()
                .name(parameter.getId())
                .description(
                    Util.roSpec("2.9.1")
                        + (!Strings.isNullOrEmpty(parameter.getDescription())
                            ? (": " + parameter.getDescription())
                            : ""))
                .required(false)
                .type("string"));
      }
      if (!parameters.isEmpty()) {
        invokeOperation.parameter(
            new QueryParameter()
                .name("x-isis-querystring")
                .description(
                    Util.roSpec("2.10") + ": all (formal) arguments as base64 encoded string")
                .required(false)
                .type("string"));
      }

    } else {
      if (semantics.isIdempotentInNature()) {
        path.put(invokeOperation);
      } else {
        path.post(invokeOperation);
      }

      final ModelImpl bodyParam = new ModelImpl().type("object");
      for (final ObjectActionParameter parameter : parameters) {

        final ObjectSpecification specification = parameter.getSpecification();
        final Property valueProperty =
            specification.isValue() ? modelFor(specification) : refToLinkModel();
        bodyParam.property(
            parameter.getId(), new ObjectProperty().property("value", valueProperty));
      }

      invokeOperation
          .consumes("application/json")
          .parameter(new BodyParameter().name("body").schema(bodyParam));
    }

    invokeOperation.response(
        200,
        new Response()
            .description(objectType + "#" + actionId)
            .schema(actionReturnTypeFor(objectAction)));
  }
Ejemplo n.º 6
0
  void appendServiceActionInvokePath(
      final ObjectSpecification serviceSpec, final ObjectAction serviceAction) {

    final String serviceId = serviceIdFor(serviceSpec);
    final String actionId = serviceAction.getId();

    final List<ObjectActionParameter> parameters = serviceAction.getParameters();
    final Path path = new Path();
    swagger.path(String.format("/services/%s/actions/%s/invoke", serviceId, actionId), path);

    final String tag = tagFor(serviceId, "> services");
    final Operation invokeOperation =
        new Operation()
            .tag(tag)
            .description(
                Util.roSpec("19.1") + ": (invoke) resource of " + serviceId + "#" + actionId)
            .produces("application/json;profile=urn:org.apache.isis/v1")
            .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true")
            .produces("application/json;profile=urn:org.restfulobjects:repr-types/action-result");

    final ActionSemantics.Of semantics = serviceAction.getSemantics();
    if (semantics.isSafeInNature()) {
      path.get(invokeOperation);

      for (final ObjectActionParameter parameter : parameters) {
        invokeOperation.parameter(
            new QueryParameter()
                .name(parameter.getId())
                .description(
                    Util.roSpec("2.9.1")
                        + (!Strings.isNullOrEmpty(parameter.getDescription())
                            ? (": " + parameter.getDescription())
                            : ""))
                .required(false)
                .type("string"));
      }
      if (!parameters.isEmpty()) {
        invokeOperation.parameter(
            new QueryParameter()
                .name("x-isis-querystring")
                .description(
                    Util.roSpec("2.10") + ": all (formal) arguments as base64 encoded string")
                .required(false)
                .type("string"));
      }

    } else {
      if (semantics.isIdempotentInNature()) {
        path.put(invokeOperation);
      } else {
        path.post(invokeOperation);
      }

      final ModelImpl bodyParam = new ModelImpl().type("object");
      for (final ObjectActionParameter parameter : parameters) {

        final Property valueProperty;
        // TODO: need to switch on parameter's type and create appropriate impl of valueProperty
        // if(parameter.getSpecification().isValue()) ...
        valueProperty = stringProperty();

        bodyParam.property(
            parameter.getId(), new ObjectProperty().property("value", valueProperty));
      }

      invokeOperation
          .consumes("application/json")
          .parameter(new BodyParameter().name("body").schema(bodyParam));
    }

    invokeOperation.response(
        200,
        new Response()
            .description(
                serviceId
                    + "#"
                    + actionId
                    + " , if Accept: application/json;profile=urn:org.apache.isis/v1")
            .schema(actionReturnTypeFor(serviceAction)));
  }