private RequestHandler createHandler(boolean collection, Object provider) {
   RequestHandler handler =
       collection ? Resources.newCollection(provider) : Resources.newSingleton(provider);
   UriRouter router = new UriRouter();
   router.addRoute(collection ? STARTS_WITH : EQUALS, "test", handler);
   return router;
 }
 @SuppressWarnings("unchecked")
 @Test(dataProvider = "testCollectionResourceProviderData")
 public void testCollectionResourceProvider(String resourcePath, String expectedId)
     throws Exception {
   CollectionResourceProvider collection = mock(CollectionResourceProvider.class);
   RequestHandler handler = Resources.newCollection(collection);
   Connection connection = Resources.newInternalConnection(handler);
   ReadRequest read = Requests.newReadRequest(resourcePath);
   connection.readAsync(new RootContext(), read);
   ArgumentCaptor<ReadRequest> captor = ArgumentCaptor.forClass(ReadRequest.class);
   verify(collection).readInstance(any(ServerContext.class), eq(expectedId), captor.capture());
   Assertions.assertThat(captor.getValue().getResourcePath()).isEqualTo("");
 }
  @Test(dataProvider = "annotatedRequestHandlerData")
  public void testPatchCollectionItemAnnotatedRequestHandler(
      Class<?> requestHandler,
      boolean collection,
      boolean create,
      boolean read,
      boolean update,
      boolean delete,
      boolean patch,
      boolean resourceAction,
      boolean collectionAction,
      boolean query)
      throws Exception {

    // Given
    Object provider = requestHandler.newInstance();
    Connection connection = Resources.newInternalConnection(createHandler(collection, provider));
    PatchRequest req = Requests.newPatchRequest("/test/fred");

    // When
    Promise<Resource, ResourceException> promise = connection.patchAsync(new RootContext(), req);

    // Then
    if (patch && collection) {
      assertThat(promise).succeeded().withId().isEqualTo("patch-fred");
    } else if (collection) {
      assertThat(promise).failedWithException().isInstanceOf(NotSupportedException.class);
    } else {
      assertThat(promise).failedWithException().isInstanceOf(NotFoundException.class);
    }
  }
  @Test(dataProvider = "annotatedRequestHandlerData")
  public void testUpdateAnnotatedRequestHandler(
      Class<?> requestHandler,
      boolean collection,
      boolean create,
      boolean read,
      boolean update,
      boolean delete,
      boolean patch,
      boolean resourceAction,
      boolean collectionAction,
      boolean query)
      throws Exception {

    // Given
    Object provider = requestHandler.newInstance();
    Connection connection = Resources.newInternalConnection(createHandler(collection, provider));
    UpdateRequest req = Requests.newUpdateRequest("/test", json(object(field("dummy", "test"))));

    // When
    Promise<Resource, ResourceException> promise = connection.updateAsync(new RootContext(), req);

    // Then
    if (update && !collection) {
      assertThat(promise).succeeded().withId().isEqualTo("update");
    } else if (!collection) {
      assertThat(promise).failedWithException().isInstanceOf(NotSupportedException.class);
    } else {
      assertThat(promise).failedWithException().isInstanceOf(BadRequestException.class);
    }
  }
  @Test(dataProvider = "annotatedRequestHandlerData")
  public void testActionCollectionItemAnnotatedRequestHandler(
      Class<?> requestHandler,
      boolean collection,
      boolean create,
      boolean read,
      boolean update,
      boolean delete,
      boolean patch,
      boolean resourceAction,
      boolean collectionAction,
      boolean query)
      throws Exception {

    // Given
    Object provider = requestHandler.newInstance();
    Connection connection = Resources.newInternalConnection(createHandler(collection, provider));
    ActionRequest req1 = Requests.newActionRequest("/test/fred", "instanceAction1");
    ActionRequest req2 = Requests.newActionRequest("/test/fred", "instanceAction2");

    // When
    Promise<JsonValue, ResourceException> promise1 =
        connection.actionAsync(new RootContext(), req1);
    Promise<JsonValue, ResourceException> promise2 =
        connection.actionAsync(new RootContext(), req2);

    // Then
    if (collectionAction && collection) {
      AssertJJsonValueAssert.assertThat(promise1)
          .succeeded()
          .stringAt("result")
          .isEqualTo("instanceAction1-fred");
      AssertJJsonValueAssert.assertThat(promise2)
          .succeeded()
          .stringAt("result")
          .isEqualTo("instanceAction2-fred");
    } else if (collection) {
      AssertJJsonValueAssert.assertThat(promise1)
          .failedWithException()
          .isInstanceOf(NotSupportedException.class);
      AssertJJsonValueAssert.assertThat(promise2)
          .failedWithException()
          .isInstanceOf(NotSupportedException.class);
    } else {
      AssertJJsonValueAssert.assertThat(promise1)
          .failedWithException()
          .isInstanceOf(NotFoundException.class);
      AssertJJsonValueAssert.assertThat(promise2)
          .failedWithException()
          .isInstanceOf(NotFoundException.class);
    }
  }
  @Test(dataProvider = "annotatedRequestHandlerData")
  public void testQueryCollectionAnnotatedRequestHandler(
      Class<?> requestHandler,
      boolean collection,
      boolean create,
      boolean read,
      boolean update,
      boolean delete,
      boolean patch,
      boolean resourceAction,
      boolean collectionAction,
      boolean query)
      throws Exception {

    // Given
    Object provider = requestHandler.newInstance();
    Connection connection = Resources.newInternalConnection(createHandler(collection, provider));
    QueryRequest req = Requests.newQueryRequest("/test");

    // When
    Promise<QueryResult, ResourceException> promise =
        connection.queryAsync(new RootContext(), req, mock(QueryResourceHandler.class));

    // Then
    if (query && collection) {
      AssertJPromiseAssert.assertThat(promise).succeeded();
      QueryResult result = promise.get();
      Assertions.assertThat(result.getPagedResultsCookie()).isEqualTo("query");
    } else if (collection) {
      AssertJPromiseAssert.assertThat(promise)
          .failedWithException()
          .isInstanceOf(NotSupportedException.class);
    } else {
      AssertJPromiseAssert.assertThat(promise)
          .failedWithException()
          .isInstanceOf(BadRequestException.class);
    }
  }
  /**
   * Create a new relationship set for the given managed resource
   *
   * @param connectionFactory Connection factory used to access the repository
   * @param resourcePath Name of the resource we are handling relationships for eg. managed/user
   * @param propertyName Name of property on first object represents the relationship
   * @param uriPropertyName Property name used on the URI for nested routes
   * @param isReverse If this provider represents a reverse relationship
   * @param activityLogger The audit activity logger to use
   * @param managedObjectSyncService Service to send sync events to
   */
  public SingletonRelationshipProvider(
      final ConnectionFactory connectionFactory,
      final ResourcePath resourcePath,
      final JsonPointer propertyName,
      final String uriPropertyName,
      final boolean isReverse,
      final ActivityLogger activityLogger,
      final ManagedObjectSyncService managedObjectSyncService) {
    super(
        connectionFactory,
        resourcePath,
        propertyName,
        isReverse,
        activityLogger,
        managedObjectSyncService);

    final Router router = new Router();
    router.addRoute(
        STARTS_WITH,
        uriTemplate(String.format("{%s}/%s", URI_PARAM_FIRST_ID, uriPropertyName)),
        Resources.newSingleton(this));
    this.requestHandler = router;
  }
  @Test(dataProvider = "annotatedRequestHandlerData")
  public void testActionAnnotatedRequestHandler(
      Class<?> requestHandler,
      boolean collection,
      boolean create,
      boolean read,
      boolean update,
      boolean delete,
      boolean patch,
      boolean resourceAction,
      boolean collectionAction,
      boolean query)
      throws Exception {

    // Given
    Object provider = requestHandler.newInstance();
    Connection connection = Resources.newInternalConnection(createHandler(collection, provider));
    String actionId1 = collection ? "collectionAction1" : "instanceAction1";
    ActionRequest req1 = Requests.newActionRequest("/test", actionId1);
    String actionId2 = collection ? "collectionAction2" : "instanceAction2";
    ActionRequest req2 = Requests.newActionRequest("/test", actionId2);

    // When
    Promise<JsonValue, ResourceException> promise1 =
        connection.actionAsync(new RootContext(), req1);
    Promise<JsonValue, ResourceException> promise2 =
        connection.actionAsync(new RootContext(), req2);

    // Then
    if ((collection && collectionAction) || (!collection && resourceAction)) {
      assertThatJsonValue(promise1).succeeded().stringAt("result").isEqualTo(actionId1);
      assertThatJsonValue(promise2).succeeded().stringAt("result").isEqualTo(actionId2);
    } else {
      assertThatJsonValue(promise1).failedWithException().isInstanceOf(NotSupportedException.class);
      assertThatJsonValue(promise2).failedWithException().isInstanceOf(NotSupportedException.class);
    }
  }
  @Test
  public void smokeTest() throws Exception {

    // @formatter:off
    final ApiDescriptor api =
        ApiDescriptor.builder("urn:forgerock:openam:api:repo:1.0")
            .setDescription("Example OpenAM REST API")
            .addRelation("", API_URN)
            .setMultiplicity(Multiplicity.ONE_TO_ONE)
            .build()
            .addRelation("users", USERS_URN)
            .build()
            .addRelation("groups", "urn:forgerock:openam:resource:group:1.0")
            .build()
            .addRelation("realms", "urn:forgerock:openam:resource:realm:1.0")
            .setDescription("An OpenAM realm")
            .build()
            .addResource(API_URN)
            .setDescription("Commons Rest API Descriptor")
            .setSchema(ApiDescriptor.class)
            .build()
            .addResource("urn:forgerock:openam:resource:user:1.0")
            .setDescription("An OpenAM user")
            .addAction("login")
            .setDescription("Authenticates a user")
            .addParameter("password", "The user's password")
            .build()
            .setSchema(User.class)
            .addProfile(
                "urn:forgerock:ldap:profile:schema:1.0",
                json(object(field("objectClass", "inetOrgPerson"))))
            .build()
            .addResource("urn:forgerock:openam:resource:admin:1.0")
            .setDescription("An OpenAM administrator")
            .setParent("urn:forgerock:openam:resource:user:1.0")
            .setSchema(AdminUser.class)
            .build()
            .addResource("urn:forgerock:openam:resource:group:1.0")
            .setDescription("An OpenAM group")
            .setSchema(Group.class)
            .build()
            .addResource("urn:forgerock:openam:resource:realm:1.0")
            .setDescription("An OpenAM realm")
            .addRelation("users", USERS_URN)
            .addAction("bulk-add")
            .setDescription("Bulk add a load of users")
            .build()
            .build()
            .addRelation("groups", "urn:forgerock:openam:resource:group:1.0")
            .build()
            .addRelation("subrealms", "urn:forgerock:openam:resource:realm:1.0")
            .setDescription("An OpenAM sub-realm")
            .build()
            .setSchema(Realm.class)
            .build()
            .build();
    // @formatter:on
    final RequestHandler handler = Api.newApiDispatcher(api, new ResolverFactoryImpl(api));
    final Connection connection = Resources.newInternalConnection(handler);

    System.out.println("#### Reading API Descriptor");
    System.out.println();
    final Resource apiValue = connection.read(new RootContext(), newReadRequest(""));
    WRITER.writeObject(apiValue.getContent().getObject());

    System.out.println();
    System.out.println("#### Reading user realms/com/subrealms/example/users/bjensen");
    System.out.println();
    final Resource bjensen =
        connection.read(
            new RootContext(), newReadRequest("realms/com/subrealms/example/users/bjensen"));
    WRITER.writeObject(bjensen.getContent().getObject());

    //        System.out.println("#### Serializing API Descriptor");
    //        System.out.println();
    //        WRITER.writeObject(api);
  }
 @Test(dataProvider = "testFilterData")
 public void testFilter(List<JsonPointer> filter, JsonValue content, JsonValue expected) {
   Assertions.assertThat(Resources.filterResource(content, filter).getObject())
       .isEqualTo(expected.getObject());
 }