SLING-8783 : Create API for api regions
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java b/src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java
index 16560a0..feb37b9 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java
@@ -74,9 +74,9 @@
final ApiRegion sourceRegion = srcRegions.getRegionByName(targetRegion.getName());
if (sourceRegion != null) {
srcRegions.remove(sourceRegion);
- for (final ApiExport srcExp : sourceRegion.getExports()) {
+ for (final ApiExport srcExp : sourceRegion.listExports()) {
if (targetRegion.getExportByName(srcExp.getName()) == null) {
- targetRegion.getExports().add(srcExp);
+ targetRegion.add(srcExp);
}
}
}
@@ -84,7 +84,7 @@
// If there are any remaining regions in the src extension, process them now
for (final ApiRegion r : srcRegions.listRegions()) {
- if (!targetRegions.addUniqueRegion(r)) {
+ if (!targetRegions.add(r)) {
throw new IllegalStateException("Duplicate region " + r.getName());
}
}
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckApiRegions.java b/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckApiRegions.java
index 84d2ba7..088e105 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckApiRegions.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckApiRegions.java
@@ -51,7 +51,7 @@
for (final ApiRegion region : apiRegions.listRegions()) {
ApiExport export = region.getExportByName(exportedPackage);
if (export != null) {
- region.getExports().remove(export);
+ region.remove(export);
}
}
}
@@ -59,7 +59,7 @@
boolean isEmpty = true;
for (final ApiRegion region : apiRegions.listRegions()) {
- if (!region.getExports().isEmpty()) {
+ if (!region.listExports().isEmpty()) {
isEmpty = false;
break;
}
@@ -68,14 +68,14 @@
if (!isEmpty) {
// track a single error for each region
for (ApiRegion region : apiRegions.listRegions()) {
- if (!region.getExports().isEmpty()) {
+ if (!region.listExports().isEmpty()) {
Formatter formatter = new Formatter();
formatter.format("Region '%s' defined in feature '%s' declares %s package%s which %s not exported by any bundle:%n",
region.getName(),
ctx.getFeature().getId(),
- region.getExports().size(), getExtension(region.getExports(), "", "s"),
- getExtension(region.getExports(), "is", "are"));
- region.getExports().forEach(api -> formatter.format(" * %s%n", api.getName()));
+ region.listExports().size(), getExtension(region.listExports(), "", "s"),
+ getExtension(region.listExports(), "is", "are"));
+ region.listExports().forEach(api -> formatter.format(" * %s%n", api.getName()));
ctx.reportError(formatter.toString());
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckApiRegionsDuplicates.java b/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckApiRegionsDuplicates.java
index 05cd8b4..25d12b5 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckApiRegionsDuplicates.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckApiRegionsDuplicates.java
@@ -69,7 +69,7 @@
private static Set<String> calculateIntersection(ApiRegion source, ApiRegion target) {
final Set<String> intersection = new HashSet<>();
- for (ApiExport packageName : source.getExports()) {
+ for (ApiExport packageName : source.listExports()) {
if (target.getExportByName(packageName.getName()) != null) {
intersection.add(packageName.getName());
}
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiExport.java b/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiExport.java
index 2fcbd49..88ff28d 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiExport.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiExport.java
@@ -16,6 +16,9 @@
*/
package org.apache.sling.feature.extension.apiregions.api;
+import java.util.HashMap;
+import java.util.Map;
+
import org.apache.sling.feature.ArtifactId;
/**
@@ -23,47 +26,81 @@
*/
public class ApiExport {
- private volatile String name;
+ private final String name;
private volatile String toggle;
private volatile ArtifactId previous;
- public ApiExport() {
- // default
- }
+ private final Map<String, String> properties = new HashMap<>();
+ /**
+ * Create a new export
+ *
+ * @param name Package name for the export
+ */
public ApiExport(final String name) {
this.name = name;
}
+ /**
+ * Get the package name
+ *
+ * @return The package name
+ */
public String getName() {
return name;
}
- public void setName(String name) {
- this.name = name;
- }
-
+ /**
+ * Get the optional toggle information
+ *
+ * @return The toggle info or {@code null}
+ */
public String getToggle() {
return toggle;
}
+ /**
+ * Set the toggle info.
+ *
+ * @param toggle The toggle info
+ */
public void setToggle(String toggle) {
this.toggle = toggle;
}
+ /**
+ * Get the previous version of this api
+ *
+ * @return The previous version or {@code null}
+ */
public ArtifactId getPrevious() {
return previous;
}
+ /**
+ * Set the previous version
+ *
+ * @param previous Previus version
+ */
public void setPrevious(ArtifactId previous) {
this.previous = previous;
}
+ /**
+ * Get additional properties
+ *
+ * @return Modifiable map of properties
+ */
+ public Map<String, String> getProperties() {
+ return this.properties;
+ }
+
@Override
public String toString() {
- return "ApiExport [name=" + name + ", toggle=" + toggle + ", previous=" + previous + "]";
+ return "ApiExport [name=" + name + ", toggle=" + toggle + ", previous=" + previous + ", properties="
+ + properties + "]";
}
@Override
@@ -72,6 +109,7 @@
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((previous == null) ? 0 : previous.hashCode());
+ result = prime * result + ((properties == null) ? 0 : properties.hashCode());
result = prime * result + ((toggle == null) ? 0 : toggle.hashCode());
return result;
}
@@ -95,6 +133,11 @@
return false;
} else if (!previous.equals(other.previous))
return false;
+ if (properties == null) {
+ if (other.properties != null)
+ return false;
+ } else if (!properties.equals(other.properties))
+ return false;
if (toggle == null) {
if (other.toggle != null)
return false;
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiRegion.java b/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiRegion.java
index a17af08..ba77277 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiRegion.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiRegion.java
@@ -57,12 +57,43 @@
}
/**
- * Modifiable collection of exports for this region
+ * Add the export. The export is only added if there isn't already a export with
+ * the same name
+ *
+ * @param export The export to add
+ * @return {@code true} if the export could be added, {@code false} otherwise
+ */
+ public boolean add(final ApiExport export) {
+ boolean found = false;
+ for (final ApiExport c : this.exports) {
+ if (c.getName().equals(export.getName())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ this.exports.add(export);
+ }
+ return !found;
+ }
+
+ /**
+ * Remove the export
+ *
+ * @param export export to remove
+ * @return {@code true} if the export got removed.
+ */
+ public boolean remove(final ApiExport export) {
+ return this.exports.remove(export);
+ }
+
+ /**
+ * Unmodifiable collection of exports for this region
*
* @return The collection of exports
*/
- public Collection<ApiExport> getExports() {
- return this.exports;
+ public Collection<ApiExport> listExports() {
+ return Collections.unmodifiableCollection(this.exports);
}
/**
@@ -70,10 +101,10 @@
*
* @return The collection of exports
*/
- public Collection<ApiExport> getAllExports() {
+ public Collection<ApiExport> listAllExports() {
final List<ApiExport> list = new ArrayList<>();
if (parent != null) {
- list.addAll(parent.getAllExports());
+ list.addAll(parent.listAllExports());
}
list.addAll(this.exports);
return Collections.unmodifiableCollection(list);
@@ -96,7 +127,7 @@
/**
* Get additional properties
- *
+ *
* @return Modifiable map of properties
*/
public Map<String, String> getProperties() {
@@ -105,7 +136,7 @@
/**
* Get the parent region
- *
+ *
* @return The parent region or {@code null}
*/
public ApiRegion getParent() {
@@ -114,7 +145,7 @@
/**
* Get the child region
- *
+ *
* @return The child region or {@code null}
*/
public ApiRegion getChild() {
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiRegions.java b/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiRegions.java
index d9966d1..86d700a 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiRegions.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/api/ApiRegions.java
@@ -84,7 +84,7 @@
* @param region The region to add
* @return {@code true} if the region could be added, {@code false} otherwise
*/
- public boolean addUniqueRegion(final ApiRegion region) {
+ public boolean add(final ApiRegion region) {
boolean found = false;
for (final ApiRegion c : this.regions) {
if (c.getName().equals(region.getName())) {
@@ -172,18 +172,23 @@
final JsonObjectBuilder regionBuilder = Json.createObjectBuilder();
regionBuilder.add(NAME_KEY, region.getName());
- if (!region.getExports().isEmpty()) {
+ if (!region.listExports().isEmpty()) {
final JsonArrayBuilder expArrayBuilder = Json.createArrayBuilder();
- for (final ApiExport exp : region.getExports()) {
- if (exp.getToggle() == null) {
+ for (final ApiExport exp : region.listExports()) {
+ if (exp.getToggle() == null && exp.getPrevious() == null && exp.getProperties().isEmpty()) {
expArrayBuilder.add(exp.getName());
} else {
final JsonObjectBuilder expBuilder = Json.createObjectBuilder();
expBuilder.add(NAME_KEY, exp.getName());
- expBuilder.add(TOGGLE_KEY, exp.getToggle());
+ if (exp.getToggle() != null) {
+ expBuilder.add(TOGGLE_KEY, exp.getToggle());
+ }
if (exp.getPrevious() != null) {
expBuilder.add(PREVIOUS_KEY, exp.getPrevious().toMvnId());
}
+ for (final Map.Entry<String, String> entry : exp.getProperties().entrySet()) {
+ expBuilder.add(entry.getKey(), entry.getValue());
+ }
expArrayBuilder.add(expBuilder);
}
}
@@ -255,20 +260,30 @@
if (e.getValueType() == ValueType.STRING) {
final String name = ((JsonString) e).getString();
if (!name.startsWith("#")) {
- final ApiExport export = new ApiExport();
- region.getExports().add(export);
-
- export.setName(name);
+ final ApiExport export = new ApiExport(name);
+ if (!region.add(export)) {
+ throw new IOException("Export " + export.getName()
+ + " is defined twice in region " + region.getName());
+ }
}
} else if (e.getValueType() == ValueType.OBJECT) {
final JsonObject expObj = (JsonObject) e;
- final ApiExport export = new ApiExport();
- region.getExports().add(export);
+ final ApiExport export = new ApiExport(expObj.getString(NAME_KEY));
+ if (!region.add(export)) {
+ throw new IOException("Export " + export.getName() + " is defined twice in region "
+ + region.getName());
+ }
- export.setName(expObj.getString(NAME_KEY));
- export.setToggle(expObj.getString(TOGGLE_KEY, null));
- if (expObj.containsKey(PREVIOUS_KEY)) {
- export.setPrevious(ArtifactId.parse(expObj.getString(PREVIOUS_KEY)));
+ for (final String key : expObj.keySet()) {
+ if (NAME_KEY.equals(key)) {
+ continue; // already set
+ } else if (TOGGLE_KEY.equals(key)) {
+ export.setToggle(expObj.getString(key));
+ } else if (PREVIOUS_KEY.equals(key)) {
+ export.setPrevious(ArtifactId.parse(expObj.getString(key)));
+ } else {
+ export.getProperties().put(key, expObj.getString(key));
+ }
}
}
}
@@ -276,7 +291,7 @@
region.getProperties().put(entry.getKey(), ((JsonString) entry.getValue()).getString());
}
}
- if (!regions.addUniqueRegion(region)) {
+ if (!regions.add(region)) {
throw new IOException("Region " + region.getName() + " is defined twice");
}
}
diff --git a/src/test/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandlerTest.java b/src/test/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandlerTest.java
index 2761e3a..04e967b 100644
--- a/src/test/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandlerTest.java
+++ b/src/test/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandlerTest.java
@@ -101,20 +101,20 @@
ApiRegions expected = new ApiRegions();
ApiRegion global = new ApiRegion("global");
- global.getExports().add(new ApiExport("a.b.c"));
- global.getExports().add(new ApiExport("d.e.f"));
- global.getExports().add(new ApiExport("test"));
- expected.addUniqueRegion(global);
+ global.add(new ApiExport("a.b.c"));
+ global.add(new ApiExport("d.e.f"));
+ global.add(new ApiExport("test"));
+ expected.add(global);
ApiRegion internal = new ApiRegion("internal");
- internal.getExports().add(new ApiExport("xyz"));
+ internal.add(new ApiExport("xyz"));
internal.getProperties().put("some-key", "some-val");
- expected.addUniqueRegion(internal);
+ expected.add(internal);
ApiRegion something = new ApiRegion("something");
- something.getExports().add(new ApiExport("a.ha"));
+ something.add(new ApiExport("a.ha"));
something.getProperties().put("my-key", "my-val");
- expected.addUniqueRegion(something);
+ expected.add(something);
ApiRegions created = ApiRegions.parse((JsonArray) tgEx.getJSONStructure());
diff --git a/src/test/java/org/apache/sling/feature/extension/apiregions/api/TestApiRegions.java b/src/test/java/org/apache/sling/feature/extension/apiregions/api/TestApiRegions.java
index e19893f..3db71ae 100644
--- a/src/test/java/org/apache/sling/feature/extension/apiregions/api/TestApiRegions.java
+++ b/src/test/java/org/apache/sling/feature/extension/apiregions/api/TestApiRegions.java
@@ -58,12 +58,12 @@
final ApiRegion global = regions.listRegions().get(0);
assertEquals("global", global.getName());
- assertEquals(2, global.getExports().size());
+ assertEquals(2, global.listExports().size());
final ApiRegion internal = regions.listRegions().get(1);
assertEquals("internal", internal.getName());
- assertEquals(1, internal.getExports().size());
+ assertEquals(1, internal.listExports().size());
}
@Test
@@ -76,11 +76,11 @@
final ApiRegion duplicate = new ApiRegion("two");
final ApiRegion other = new ApiRegion("other");
- assertTrue(regions.addUniqueRegion(one));
- assertTrue(regions.addUniqueRegion(two));
- assertTrue(regions.addUniqueRegion(three));
+ assertTrue(regions.add(one));
+ assertTrue(regions.add(two));
+ assertTrue(regions.add(three));
- assertFalse(regions.addUniqueRegion(duplicate));
+ assertFalse(regions.add(duplicate));
assertEquals(3, regions.listRegions().size());
@@ -106,34 +106,34 @@
final ApiRegions regions = new ApiRegions();
final ApiRegion one = new ApiRegion("one");
- one.getExports().add(new ApiExport("a"));
+ one.add(new ApiExport("a"));
final ApiRegion two = new ApiRegion("two");
- two.getExports().add(new ApiExport("b"));
+ two.add(new ApiExport("b"));
final ApiRegion three = new ApiRegion("three");
- three.getExports().add(new ApiExport("c"));
+ three.add(new ApiExport("c"));
- assertTrue(regions.addUniqueRegion(one));
- assertTrue(regions.addUniqueRegion(two));
- assertTrue(regions.addUniqueRegion(three));
+ assertTrue(regions.add(one));
+ assertTrue(regions.add(two));
+ assertTrue(regions.add(three));
- assertEquals(1, one.getAllExports().size());
- assertTrue(one.getAllExports().contains(new ApiExport("a")));
- assertEquals(1, one.getExports().size());
- assertTrue(one.getExports().contains(new ApiExport("a")));
+ assertEquals(1, one.listAllExports().size());
+ assertTrue(one.listAllExports().contains(new ApiExport("a")));
+ assertEquals(1, one.listExports().size());
+ assertTrue(one.listExports().contains(new ApiExport("a")));
- assertEquals(2, two.getAllExports().size());
- assertTrue(two.getAllExports().contains(new ApiExport("a")));
- assertTrue(two.getAllExports().contains(new ApiExport("b")));
- assertEquals(1, two.getExports().size());
- assertTrue(two.getExports().contains(new ApiExport("b")));
+ assertEquals(2, two.listAllExports().size());
+ assertTrue(two.listAllExports().contains(new ApiExport("a")));
+ assertTrue(two.listAllExports().contains(new ApiExport("b")));
+ assertEquals(1, two.listExports().size());
+ assertTrue(two.listExports().contains(new ApiExport("b")));
- assertEquals(3, three.getAllExports().size());
- assertTrue(three.getAllExports().contains(new ApiExport("a")));
- assertTrue(three.getAllExports().contains(new ApiExport("b")));
- assertTrue(three.getAllExports().contains(new ApiExport("c")));
- assertEquals(1, three.getExports().size());
- assertTrue(three.getExports().contains(new ApiExport("c")));
+ assertEquals(3, three.listAllExports().size());
+ assertTrue(three.listAllExports().contains(new ApiExport("a")));
+ assertTrue(three.listAllExports().contains(new ApiExport("b")));
+ assertTrue(three.listAllExports().contains(new ApiExport("c")));
+ assertEquals(1, three.listExports().size());
+ assertTrue(three.listExports().contains(new ApiExport("c")));
}
}