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());
+ }
+
}