From 40be863aec75ae0c0c7b97ad5622ff47f476a783 Mon Sep 17 00:00:00 2001
From: Guy Elsmore-Paddock <guy@rosieapp.com>
Date: Thu, 26 Oct 2017 01:46:23 +0000
Subject: [PATCH] Fix read-only sub-resource CREST API descr (#6)

---
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java |   57 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java
index 9c8fbd0..d82c741 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Resource.java
@@ -470,6 +470,31 @@
         return id;
     }
 
+    /**
+     * Gets a unique name for the configuration of this resource in CREST.
+     *
+     * The name is the combination of the resource type and the writability of the resource. For
+     * example, {@code frapi:opendj:rest2ldap:group:1.0:read-write} or
+     * {@code frapi:opendj:rest2ldap:user:1.0:read-only}. Multiple resources can share the same
+     * service description if they manipulate the same resource type and have the same writability.
+     *
+     * @param  isReadOnly
+     *         Whether or not this resource is read-only.
+     *
+     * @return The unique service ID for this resource, given the specified writability.
+     */
+    String getServiceId(boolean isReadOnly) {
+        StringBuilder serviceId = new StringBuilder(this.getResourceId());
+
+        if (isReadOnly) {
+            serviceId.append(":read-only");
+        } else {
+            serviceId.append(":read-write");
+        }
+
+        return serviceId.toString();
+    }
+
     void build(final Rest2Ldap rest2Ldap) {
         // Prevent re-entrant calls.
         if (isBuilt) {
@@ -522,7 +547,7 @@
 
         org.forgerock.api.models.Resource.Builder resource = org.forgerock.api.models.Resource.
             resource()
-            .title(id)
+            .title(this.getServiceId(isReadOnly))
             .description(toLS(description))
             .resourceSchema(schemaRef("#/definitions/" + id))
             .mvccSupported(isMvccSupported());
@@ -539,8 +564,8 @@
         return ApiDescription.apiDescription()
                       .id("unused").version("unused")
                       .definitions(definitions())
-                      .services(services(resource))
-                      .paths(paths())
+                      .services(services(resource, isReadOnly))
+                      .paths(paths(isReadOnly))
                       .errors(errors())
                       .build();
     }
@@ -555,13 +580,17 @@
     ApiDescription collectionApi(boolean isReadOnly) {
         org.forgerock.api.models.Resource.Builder resource = org.forgerock.api.models.Resource.
             resource()
-            .title(id)
+            .title(this.getServiceId(isReadOnly))
             .description(toLS(description))
             .resourceSchema(schemaRef("#/definitions/" + id))
             .mvccSupported(isMvccSupported());
 
         resource.items(buildItems(isReadOnly));
-        resource.create(createOperation(CreateMode.ID_FROM_SERVER));
+
+        if (!isReadOnly) {
+            resource.create(createOperation(CreateMode.ID_FROM_SERVER));
+        }
+
         resource.query(Query.query()
                            .stability(EVOLVING)
                            .type(QueryType.FILTER)
@@ -580,23 +609,29 @@
         return ApiDescription.apiDescription()
                              .id("unused").version("unused")
                              .definitions(definitions())
-                             .services(services(resource))
-                             .paths(paths())
+                             .services(services(resource, isReadOnly))
+                             .paths(paths(isReadOnly))
                              .errors(errors())
                              .build();
     }
 
-    private Services services(org.forgerock.api.models.Resource.Builder resource) {
+    private Services services(org.forgerock.api.models.Resource.Builder resource,
+                              boolean isReadOnly) {
+        final String serviceId = this.getServiceId(isReadOnly);
+
         return Services.services()
-                       .put(id, resource.build())
+                       .put(serviceId, resource.build())
                        .build();
     }
 
-    private Paths paths() {
+    private Paths paths(boolean isReadOnly) {
+        final String serviceId = this.getServiceId(isReadOnly);
+        final org.forgerock.api.models.Resource resource = resourceRef("#/services/" + serviceId);
+
         return Paths.paths()
                      // do not put anything in the path to avoid unfortunate string concatenation
                      // also use UNVERSIONED and rely on the router to stamp the version
-                     .put("", versionedPath().put(UNVERSIONED, resourceRef("#/services/" + id)).build())
+                     .put("", versionedPath().put(UNVERSIONED, resource).build())
                      .build();
     }
 

--
Gitblit v1.10.0