You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by si...@apache.org on 2019/04/10 11:28:01 UTC

[sling-whiteboard] branch master updated: [api-regions] enhanced serializer, added missing javadoc

This is an automated email from the ASF dual-hosted git repository.

simonetripodi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 7332550  [api-regions] enhanced serializer, added missing javadoc
7332550 is described below

commit 7332550538776dd60443581aceca69a8b6353c4a
Author: stripodi <st...@192.168.1.111>
AuthorDate: Wed Apr 10 13:27:54 2019 +0200

    [api-regions] enhanced serializer, added missing javadoc
---
 .../apache/sling/feature/apiregions/ApiRegion.java | 55 +++++++++++++
 .../sling/feature/apiregions/ApiRegions.java       | 26 ++++++
 .../apiregions/io/json/ApiRegionsJSONParser.java   | 23 ++++++
 .../io/json/ApiRegionsJSONSerializer.java          | 47 +++++++++++
 .../io/json/ApiRegionsJSONSerializerTest.java      | 96 +++++++++++++++-------
 5 files changed, 219 insertions(+), 28 deletions(-)

diff --git a/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/ApiRegion.java b/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/ApiRegion.java
index 78f34d3..04fec39 100644
--- a/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/ApiRegion.java
+++ b/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/ApiRegion.java
@@ -27,6 +27,9 @@ import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.regex.Pattern;
 
+/**
+ * In-memory representation of a <code>api-regions</code> section.
+ */
 public final class ApiRegion implements Iterable<String> {
 
     private static final Pattern PACKAGE_NAME_VALIDATION =
@@ -98,14 +101,32 @@ public final class ApiRegion implements Iterable<String> {
         this.parent = parent;
     }
 
+    /**
+     * Returns the name identifying this API region.
+     *
+     * @return the name identifying this API region.
+     */
     public String getName() {
         return name;
     }
 
+    /**
+     * Returns the parent API region which is extended,
+     * <code>null</code> if this region represents the first section in the regions.
+     *
+     * @return the parent API region which is extended,
+     * <code>null</code> if this region represents the first section in the regions.
+     */
     public ApiRegion getParent() {
         return parent;
     }
 
+    /**
+     * Add new API packages iterating over the input collection,
+     * filtering out null, empty or non-conforming to Java packages convention.
+     *
+     * @param apis the input API packages, must be not null.
+     */
     public void addAll(Iterable<String> apis) {
         requireNonNull(apis, "Impossible to import null APIs");
 
@@ -114,6 +135,12 @@ public final class ApiRegion implements Iterable<String> {
         }
     }
 
+    /**
+     * Add a new API package filtering out null, empty or non-conforming to Java packages convention.
+     *
+     * @param api the new API package, must be not null, not empty and conforming to Java packages convention
+     * @return true if the API package is added, false otherwise.
+     */
     public boolean add(String api) {
         // ignore null, empty package and non well-formed packages names, i.e. javax.jms.doc-files
         if (isEmpty(api) || !PACKAGE_NAME_VALIDATION.matcher(api).matches()) {
@@ -137,6 +164,13 @@ public final class ApiRegion implements Iterable<String> {
         return apis.add(api);
     }
 
+    /**
+     * Check is the region contains, across the whole region hierarchy,
+     * if the input API package is contained.
+     * 
+     * @param api the API package to check
+     * @return true, if the API package is contained by this (or parents) region, false otherwise.
+     */
     public boolean contains(String api) {
         if (isEmpty(api)) {
             return false;
@@ -153,6 +187,11 @@ public final class ApiRegion implements Iterable<String> {
         return false;
     }
 
+    /**
+     * Check if this region, across the whole region hierarchy, contains any API.
+     *
+     * @return true if this region, across the whole region hierarchy, contains any API, false otherwise.
+     */
     public boolean isEmpty() {
         if (!apis.isEmpty()) {
             return false;
@@ -165,6 +204,14 @@ public final class ApiRegion implements Iterable<String> {
         return true;
     }
 
+    /**
+     * Removes in this region, or in a region across the whole hierarchy,
+     * the input API package.
+     *
+     * @param api the API package to remove
+     * @return true if the API package was removed in this or one region across the whole region hierarchy,
+     * false othewrwise
+     */
     public boolean remove(String api) {
         if (isEmpty(api)) {
             return false;
@@ -181,6 +228,9 @@ public final class ApiRegion implements Iterable<String> {
         return false;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Iterator<String> iterator() {
         List<Iterable<String>> iterators = new LinkedList<>();
@@ -194,6 +244,11 @@ public final class ApiRegion implements Iterable<String> {
         return new JoinedIterator<String>(iterators.iterator());
     }
 
+    /**
+     * Returns the API packages that are stored only in this region.
+     *
+     * @return the API packages that are stored only in this region.
+     */
     public Iterable<String> getExports() {
         return apis;
     }
diff --git a/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/ApiRegions.java b/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/ApiRegions.java
index 2ebeaa6..23a322d 100644
--- a/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/ApiRegions.java
+++ b/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/ApiRegions.java
@@ -19,10 +19,22 @@ package org.apache.sling.feature.apiregions;
 import java.util.Iterator;
 import java.util.Stack;
 
+/**
+ * <code>api-regions</code> in memory representation.
+ */
 public final class ApiRegions implements Iterable<ApiRegion> {
 
     private final Stack<ApiRegion> regions = new Stack<>();
 
+    /**
+     * Creates then adds a new API region, given its name.
+     *
+     * <i>Please note</i>: according the <code>api-regions</code> specifications,
+     * the order in which the regions are created influences the regions hierarchy.
+     *
+     * @param regionName the name of the region to be created, must be not null and not empty.
+     * @return the created region, identified by the passed name.
+     */
     public ApiRegion addNew(String regionName) {
         if (regionName == null || regionName.isEmpty()) {
             throw new IllegalArgumentException("Impossible to create a new API Region without specifying a valid name");
@@ -33,6 +45,12 @@ public final class ApiRegions implements Iterable<ApiRegion> {
         return regions.push(newRegion);
     }
 
+    /**
+     * Search and returns, if found, the region identified by the given name.
+     *
+     * @param regionName the name of the region to find
+     * @return the region identified by the passed name, null if not found or the name is null or empty
+     */
     public ApiRegion getByName(String regionName) {
         if (regionName == null || regionName.isEmpty()) {
             return null;
@@ -47,10 +65,18 @@ public final class ApiRegions implements Iterable<ApiRegion> {
         return null;
     }
 
+    /**
+     * Checks if any region is present
+     *
+     * @return true if there is at least one declared regin, false otherwise.
+     */
     public boolean isEmpty() {
         return regions.isEmpty();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Iterator<ApiRegion> iterator() {
         return regions.iterator();
diff --git a/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONParser.java b/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONParser.java
index 35aebee..f2fdeb5 100644
--- a/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONParser.java
+++ b/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONParser.java
@@ -34,12 +34,23 @@ import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.apiregions.ApiRegion;
 import org.apache.sling.feature.apiregions.ApiRegions;
 
+/**
+ * <code>api-regions</code> JSON format parser implementation.
+ */
 public final class ApiRegionsJSONParser implements JSONConstants {
 
     private ApiRegionsJSONParser() {
         // this class must not be instantiated from outside
     }
 
+    /**
+     * Extracts and parses an <code>api-regions</code> JSON Extension from a Feature Model,
+     * mapping it to the related in-memory representation.
+     *
+     * @param feature the Feature Model containing the <code>api-regions</code> to parse.
+     * @return the related in-memory representation of the <code>api-regions</code>,
+     * null if the <code>api-regions</code> extension does not exist in the input Feature Model.
+     */
     public static ApiRegions parseApiRegions(Feature feature) {
         requireNonNull(feature, "Impossible to extract api-regions from a null feature");
 
@@ -52,6 +63,12 @@ public final class ApiRegionsJSONParser implements JSONConstants {
         return parseApiRegions(apiRegionsExtension);
     }
 
+    /**
+     * Extracts and parses an <code>api-regions</code> JSON Extension, mapping it to the related in-memory representation.
+     *
+     * @param apiRegionsExtension the <code>api-regions</code> JSON Extension, must named <code>api-regions</code> and of type JSON.
+     * @return the related in-memory representation of the <code>api-regions</code>
+     */
     public static ApiRegions parseApiRegions(Extension apiRegionsExtension) {
         requireNonNull(apiRegionsExtension, "Impossible to extract api-regions from a null extension");
 
@@ -67,6 +84,12 @@ public final class ApiRegionsJSONParser implements JSONConstants {
         return parseApiRegions(apiRegionsExtension.getJSON());
     }
 
+    /**
+     * Parses an <code>api-regions</code> JSON string representation, mapping it to the related in-memory representation.
+     *
+     * @param jsonRepresentation the <code>api-regions</code> JSON string representation
+     * @return the related in-memory representation of the <code>api-regions</code>
+     */
     public static ApiRegions parseApiRegions(String jsonRepresentation) {
         requireNonNull(jsonRepresentation, "Impossible to extract api-regions from a null JSON representation");
 
diff --git a/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONSerializer.java b/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONSerializer.java
index 34d3eb3..4933cdd 100644
--- a/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONSerializer.java
+++ b/feature-api-regions/src/main/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONSerializer.java
@@ -20,6 +20,7 @@ import static java.util.Objects.requireNonNull;
 
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
+import java.io.StringWriter;
 import java.io.Writer;
 import java.util.Collections;
 
@@ -27,9 +28,15 @@ import javax.json.Json;
 import javax.json.stream.JsonGenerator;
 import javax.json.stream.JsonGeneratorFactory;
 
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.apiregions.ApiRegion;
 import org.apache.sling.feature.apiregions.ApiRegions;
 
+/**
+ * <code>api-regions</code> JSON format serializer implementation.
+ */
 public final class ApiRegionsJSONSerializer implements JSONConstants {
 
     private static final JsonGeneratorFactory GENERATOR_FACTORY = Json.createGeneratorFactory(Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true));
@@ -38,11 +45,23 @@ public final class ApiRegionsJSONSerializer implements JSONConstants {
         // this class must not be instantiated from outside
     }
 
+    /**
+     * Serializes the input <code>api-regions</code> to the target stream.
+     *
+     * @param apiRegions the <code>api-regions</code> has to be serialized
+     * @param output the target stream where serializing the <code>api-regions</code>
+     */
     public static void serializeApiRegions(ApiRegions apiRegions, OutputStream output) {
         requireNonNull(output, "Impossible to serialize api-regions to a null stream");
         serializeApiRegions(apiRegions, new OutputStreamWriter(output));
     }
 
+    /**
+     * Serializes the input <code>api-regions</code> to the target writer.
+     *
+     * @param apiRegions the <code>api-regions</code> has to be serialized
+     * @param writer the target writer where serializing the <code>api-regions</code>
+     */
     public static void serializeApiRegions(ApiRegions apiRegions, Writer writer) {
         requireNonNull(apiRegions, "Impossible to serialize null api-regions");
         requireNonNull(writer, "Impossible to serialize api-regions to a null stream");
@@ -65,4 +84,32 @@ public final class ApiRegionsJSONSerializer implements JSONConstants {
         generator.writeEnd().close();
     }
 
+    /**
+     * Maps the input <code>api-regions</code> to the <code>api-regions</code> Feature Model Extension.
+     *
+     * @param apiRegions the <code>api-regions</code> has to be serialized
+     * @return the mapped <code>api-regions</code> Feature Model Extension
+     */
+    public static Extension serializeApiRegions(ApiRegions apiRegions) {
+        StringWriter stringWriter = new StringWriter();
+        serializeApiRegions(apiRegions, stringWriter);
+
+        Extension apiRegionsExtension = new Extension(ExtensionType.JSON, API_REGIONS_KEY, false);
+        apiRegionsExtension.setJSON(stringWriter.toString());
+        return apiRegionsExtension;
+    }
+
+    /**
+     * Maps the input <code>api-regions</code> to the <code>api-regions</code> Feature Model Extension
+     * and add it to the target Feature.
+     *
+     * @param apiRegions the <code>api-regions</code> has to be serialized
+     * @param feature the target Feature where adding the extension
+     */
+    public static void serializeApiRegions(ApiRegions apiRegions, Feature feature) {
+        requireNonNull(feature, "Impossible to serialize api-regions to a null Feature");
+        Extension apiRegionsExtension = serializeApiRegions(apiRegions);
+        feature.getExtensions().add(apiRegionsExtension);
+    }
+
 }
diff --git a/feature-api-regions/src/test/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONSerializerTest.java b/feature-api-regions/src/test/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONSerializerTest.java
index b7b4eeb..f715d3b 100644
--- a/feature-api-regions/src/test/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONSerializerTest.java
+++ b/feature-api-regions/src/test/java/org/apache/sling/feature/apiregions/io/json/ApiRegionsJSONSerializerTest.java
@@ -17,17 +17,59 @@
 package org.apache.sling.feature.apiregions.io.json;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.OutputStream;
 import java.io.StringWriter;
 import java.io.Writer;
 
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.apiregions.ApiRegion;
 import org.apache.sling.feature.apiregions.ApiRegions;
+import org.junit.Before;
 import org.junit.Test;
 
 public final class ApiRegionsJSONSerializerTest {
 
+    private ApiRegions apiRegions;
+
+    private String expected;
+
+    @Before
+    public void setUp() {
+        apiRegions = new ApiRegions();
+
+        ApiRegion base = apiRegions.addNew("base");
+        base.add("org.apache.felix.inventory");
+        base.add("org.apache.felix.metatype");
+
+        ApiRegion extended = apiRegions.addNew("extended");
+        extended.add("org.apache.felix.scr.component");
+        extended.add("org.apache.felix.scr.info");
+
+        expected = "[\n" + 
+                "  {\n" + 
+                "    \"name\":\"base\",\n" + 
+                "    \"exports\":[\n" + 
+                "      \"org.apache.felix.metatype\",\n" + 
+                "      \"org.apache.felix.inventory\"\n" + 
+                "    ]\n" + 
+                "  },\n" + 
+                "  {\n" + 
+                "    \"name\":\"extended\",\n" + 
+                "    \"exports\":[\n" + 
+                "      \"org.apache.felix.scr.component\",\n" + 
+                "      \"org.apache.felix.scr.info\"\n" + 
+                "    ]\n" + 
+                "  }\n" + 
+                "]";
+    }
+
     @Test(expected = NullPointerException.class)
     public void nullOutputStreamNotAccepted() {
         ApiRegionsJSONSerializer.serializeApiRegions(null, (OutputStream) null);
@@ -44,34 +86,7 @@ public final class ApiRegionsJSONSerializerTest {
     }
 
     @Test
-    public void serialization() {
-        String expected = "[\n" + 
-                            "  {\n" + 
-                            "    \"name\":\"base\",\n" + 
-                            "    \"exports\":[\n" + 
-                            "      \"org.apache.felix.metatype\",\n" + 
-                            "      \"org.apache.felix.inventory\"\n" + 
-                            "    ]\n" + 
-                            "  },\n" + 
-                            "  {\n" + 
-                            "    \"name\":\"extended\",\n" + 
-                            "    \"exports\":[\n" + 
-                            "      \"org.apache.felix.scr.component\",\n" + 
-                            "      \"org.apache.felix.scr.info\"\n" + 
-                            "    ]\n" + 
-                            "  }\n" + 
-                            "]";
-
-        ApiRegions apiRegions = new ApiRegions();
-
-        ApiRegion base = apiRegions.addNew("base");
-        base.add("org.apache.felix.inventory");
-        base.add("org.apache.felix.metatype");
-
-        ApiRegion extended = apiRegions.addNew("extended");
-        extended.add("org.apache.felix.scr.component");
-        extended.add("org.apache.felix.scr.info");
-
+    public void stringSerialization() {
         StringWriter writer = new StringWriter();
         ApiRegionsJSONSerializer.serializeApiRegions(apiRegions, writer);
 
@@ -80,4 +95,29 @@ public final class ApiRegionsJSONSerializerTest {
         assertEquals(expected, actual);
     }
 
+    @Test
+    public void extensionCreation() {
+        Extension extension = ApiRegionsJSONSerializer.serializeApiRegions(apiRegions);
+        extensionAssertions(extension);
+    }
+
+    @Test
+    public void addExtensionToFeature() {
+        Feature feature = new Feature(ArtifactId.fromMvnId("org.apache.sling:org.apache.sling.feature.apiregions:1.0.0"));
+
+        ApiRegionsJSONSerializer.serializeApiRegions(apiRegions, feature);
+
+        Extension extension = feature.getExtensions().getByName(JSONConstants.API_REGIONS_KEY);
+        extensionAssertions(extension);
+    }
+
+    private void extensionAssertions(Extension extension) {
+        assertNotNull(extension);
+        assertEquals(ExtensionType.JSON, extension.getType());
+        assertEquals(JSONConstants.API_REGIONS_KEY, extension.getName());
+        assertFalse(extension.isRequired());
+        assertTrue(extension.isOptional());
+        assertEquals(expected, extension.getJSON());
+    }
+
 }