Juan Hernandez has uploaded a new change for review.
Change subject: codegen: Handle dumplicated URL segments
......................................................................
codegen: Handle dumplicated URL segments
There are some entities and collections whose names can't be directly
derived by the corresponding URL segments. For example, the following
two URLs contain segments that are equal:
hosts/{host:id}/numanodes
vms/{vm:id}/numanodes
But the corresponding types are "NumaNode" in the first case and
"VirtualNumaNode" in the second, so it isn't possible to derive the type
name using only the URL segment.
To address this issue this patch introduces a table of exceptions that
the generator will lookup. This table will initially contain the
exception in the example above.
Change-Id: I7fcbfe5e490bb23aa2e1785560dd016d63e3a9ae
Bug-Url: https://bugzilla.redhat.com/1116119
Signed-off-by: Juan Hernandez <[email protected]>
---
M
ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/rsdl/RsdlCodegen.java
M
ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/utils/ArrayUtils.java
2 files changed, 133 insertions(+), 33 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-engine-sdk-java
refs/changes/69/29569/1
diff --git
a/ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/rsdl/RsdlCodegen.java
b/ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/rsdl/RsdlCodegen.java
index 321964c..7bd2eab 100644
---
a/ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/rsdl/RsdlCodegen.java
+++
b/ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/rsdl/RsdlCodegen.java
@@ -19,6 +19,7 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -120,6 +121,78 @@
};
private static final String[] RETURN_BODY_EXCEPTIONS = new String[] {
"Response", "Responses" };
private static final String[] ACTION_NAME_EXCEPTIONS = new String[] {
"import", "export" };
+
+ /**
+ * In come cases it isn't possible to derive the name of the entity from
the link, specially when there are several
+ * links that have similar structure but different types. For example, the
following to lings have the same
+ * structure:
+ *
+ * <pre>
+ * hosts/{host:id}/numanodes/{numanode:id}
+ * vms/{vm:id}/numanodes/{numanode:id}
+ * </pre>
+ *
+ * But for the first the entity type is {@code NumaNode} and for the
second it is {@code VirtualNumaNode}. This
+ * isn't a problem for links that have a request or response type
explicitly specified, as it will be taken from
+ * there. For example, the link to get a VM numa node explicitly indicates
that the type is {@code VirtualNumaNode}:
+ *
+ * <pre>
+ * <link href="/ovirt-engine/api/vms/{vm:id}/numanodes/{numanode:id}"
rel="get">
+ * <description>get the details of the specified virtual NUMA node
for the vm</description>
+ * <request>
+ * <http_method>GET</http_method>
+ * <body/>
+ * </request>
+ * <response>
+ * <type>VirtualNumaNode</type>
+ * </response>
+ * </link>
+ * </pre>
+ *
+ * But some links don't specify a request or response type, like the
{@code DELETE} links. For those cases we need
+ * this map of exceptions.
+ */
+ private static Map<String[], String> ENTITY_NAME_EXCEPTIONS = new
HashMap<>();
+
+ static {
+ ENTITY_NAME_EXCEPTIONS.put(
+ new String[] { "vms", "{vm:id}", "numanodes", "{numanode:id}" },
"VirtualNumaNode"
+ );
+ }
+
+ /**
+ * Same for collections.
+ */
+ private static Map<String[], String> COLLECTION_NAME_EXCEPTIONS = new
HashMap<>();
+
+ static {
+ COLLECTION_NAME_EXCEPTIONS.put(
+ new String[] { "vms", "{vm:id}", "numanodes", }, "VirtualNumaNodes"
+ );
+ }
+
+ /**
+ * Checks if the given name has an exceptional treatment.
+ *
+ * @param exceptions the map of exceptions to check
+ * @param name the name to check
+ * @param periods the URL segments to check
+ * @param i the number of URL segments to check
+ * @return the exceptional name assigned, or {@code null} if no
exceptional treatment is needed
+ */
+ private static String checkNamingException(Map<String[], String>
exceptions, String name, String[] periods, int i) {
+ periods = Arrays.copyOfRange(periods, 0, i);
+ for (Map.Entry<String[], String> exceptionEntry :
exceptions.entrySet()) {
+ String[] exceptionKey = exceptionEntry.getKey();
+ if (exceptionKey.length < i) {
+ continue;
+ }
+ if (ArrayUtils.startsWith(periods, exceptionKey)) {
+ return exceptionEntry.getValue();
+ }
+ }
+ return null;
+ }
/**
* Create a code generator for the decorator classes.
@@ -254,12 +327,12 @@
if (!ArrayUtils.contains(COLLECTION2ENTITY_EXCEPTIONS,
period)) {
if (i == 1) { // root-collection
- String collection = getRootCollectionName(period);
+ String collection = getRootCollectionName(period,
periods, i);
collectionName = collection;
parent =
StringUtils.toUpperCase(StringUtils.toSingular(collection));
String decoratorCollectionName =
StringUtils.toUpperCase(collection);
- String publicEntityName =
getPublicEntity(StringUtils.toSingular(collection));
- String publicCollectionName =
getPublicCollection(collection);
+ String publicEntityName =
getPublicEntity(StringUtils.toSingular(collection), periods, i);
+ String publicCollectionName =
getPublicCollection(collection, periods, i);
String decoratorEntityName =
StringUtils.toSingular(decoratorCollectionName);
addRootCollection(url,
@@ -273,9 +346,9 @@
decoratorEntityName);
} else if (i == 2) { // root-resource
- String resource = getRootResourceName(collectionName);
+ String resource = getRootResourceName(collectionName,
periods, i);
String decoratorResourceName =
StringUtils.toUpperCase(resource);
- String publicEntityName =
getPublicEntity(StringUtils.toSingular(collectionName));
+ String publicEntityName =
getPublicEntity(StringUtils.toSingular(collectionName), periods, i);
addRootResource(url,
rel,
@@ -288,11 +361,11 @@
String collection =
getSubCollectionName(actualReturnType, parent, i, periods);
collectionName = collection;
ResourceHolder resourceHolder =
this.resourcesHolder.get(parent.toLowerCase());
- String decoratorEntityName =
getSubResourceName(collectionName, parent);
+ String decoratorEntityName =
getSubResourceName(collectionName, parent, periods, i);
String publicEntityName =
getSubCollectionEntityName(rel,
actualReturnType, requestMethod, periods, i, period);
String publicCollectionName =
-
getPublicCollection(StringUtils.toPlural(actualReturnType));
+
getPublicCollection(StringUtils.toPlural(actualReturnType), periods, i);
addSubCollection(url,
rel,
@@ -310,9 +383,9 @@
} else { // sub-resource
if (!isAction(period, rel, requestMethod)) {
- String resource =
getSubResourceName(collectionName, parent);
+ String resource =
getSubResourceName(collectionName, parent, periods, i);
String subResourceDecoratorName = resource;
- String publicEntityName =
getSubResourceEntityName(parent, collectionName);
+ String publicEntityName =
getSubResourceEntityName(parent, collectionName, periods, i);
addSubResource(url,
rel,
@@ -330,12 +403,12 @@
} else { // unique treatment for COLLECTION2ENTITY_EXCEPTIONS
if (period.equals("capabilities") ||
parent.equalsIgnoreCase("capabilities")) {
if (i == 1) { // root-collection
- String collection = getRootCollectionName(period);
+ String collection = getRootCollectionName(period,
periods, i);
collectionName = collection;
parent = StringUtils.toUpperCase(collectionName);
String decoratorCollectionName =
StringUtils.toUpperCase(collection);
- String publicEntityName =
getPublicEntity(VersionCaps.class.getSimpleName());
- String publicCollectionName =
getPublicCollection(Capabilities.class.getSimpleName());
+ String publicEntityName =
getPublicEntity(VersionCaps.class.getSimpleName(), periods, i);
+ String publicCollectionName =
getPublicCollection(Capabilities.class.getSimpleName(), periods, i);
String decoratorEntityName =
VersionCaps.class.getSimpleName();
addRootCollection(url,
@@ -351,7 +424,7 @@
} else if (i == 2) { // root-resource
String resource =
VersionCaps.class.getSimpleName();
String decoratorResourceName = resource;
- String publicEntityName =
getPublicEntity(resource);
+ String publicEntityName =
getPublicEntity(resource, periods, i);
addRootResource(url,
rel,
@@ -588,11 +661,11 @@
private String getSubCollectionEntityName(String rel, String
actualReturnType,
HttpMethod requestMethod, String[] periods, int i, String period) {
String publicEntityName =
-
getPublicEntity(StringUtils.toSingular(StringUtils.toPlural(actualReturnType)),
+
getPublicEntity(StringUtils.toSingular(StringUtils.toPlural(actualReturnType)),
periods, i,
false);
if (publicEntityName == null && isAction(period, rel, requestMethod)) {
publicEntityName =
-
getPublicEntity(StringUtils.toSingular(StringUtils.toPlural(periods[i - 3])));
+
getPublicEntity(StringUtils.toSingular(StringUtils.toPlural(periods[i - 3])),
periods, i);
}
return publicEntityName;
}
@@ -604,13 +677,13 @@
* @param collectionName
* @return
*/
- private String getSubResourceEntityName(String parent, String
collectionName) {
+ private String getSubResourceEntityName(String parent, String
collectionName, String[] periods, int i) {
String publicEntityName =
- getPublicEntity(StringUtils.toSingular(collectionName), false);
+ getPublicEntity(StringUtils.toSingular(collectionName),
periods, i, false);
if (publicEntityName == null) {
publicEntityName =
getPublicEntity(StringUtils.toSingular(collectionName.replace(parent,
- "")));
+ "")), periods, i);
}
return publicEntityName;
}
@@ -783,11 +856,11 @@
*
* @return sub-resource name
*/
- private String getSubResourceName(String collectionName, String parent) {
+ private String getSubResourceName(String collectionName, String parent,
String[] periods, int i) {
String resource = StringUtils.toSingular(collectionName);
String resourceCandidate =
getPublicEntity(StringUtils.toSingular(collectionName.replace(parent, "")
- .toLowerCase()), false);
+ .toLowerCase()), periods, i, false);
if (resourceCandidate != null) {
resource = parent + resourceCandidate;
}
@@ -811,7 +884,7 @@
StringUtils.toUpperCase(actualReturnType));
}
} else {
- collection = getPublicCollection(periods[i - 1].toLowerCase(),
false);
+ collection = getPublicCollection(periods[i - 1].toLowerCase(),
periods, i, false);
if (collection != null) {
collection = StringUtils.toPlural(parent
+
@@ -831,9 +904,9 @@
*
* @return root-resource name
*/
- private String getRootResourceName(String collectionName) {
+ private String getRootResourceName(String collectionName, String[]
periods, int i) {
String resource = StringUtils.toSingular(collectionName);
- String resourceCandidate =
getPublicEntity(StringUtils.toSingular(collectionName), false);
+ String resourceCandidate =
getPublicEntity(StringUtils.toSingular(collectionName), periods, i, false);
if (resourceCandidate != null) {
resource = resourceCandidate;
}
@@ -846,9 +919,9 @@
*
* @return root-collection name
*/
- private String getRootCollectionName(String period) {
+ private String getRootCollectionName(String period, String[] periods, int
i) {
String collection =
StringUtils.toUpperCase(StringUtils.toPlural(period));
- String collectionCandidate =
getPublicCollection(StringUtils.toPlural(period), false);
+ String collectionCandidate =
getPublicCollection(StringUtils.toPlural(period), periods, i, false);
if (collectionCandidate != null) {
collection = collectionCandidate;
}
@@ -879,7 +952,7 @@
String actualReturnType;
if (i == periods.length) {
if (responseBodyType == null ||
ArrayUtils.contains(RETURN_BODY_EXCEPTIONS, responseBodyType)) {
- String collectionCandidate =
getPublicCollection(period.toLowerCase(), false);
+ String collectionCandidate =
getPublicCollection(period.toLowerCase(), periods, i, false);
if (collectionCandidate != null) {
actualReturnType = collectionCandidate;
} else {
@@ -890,7 +963,7 @@
}
} else {
- actualReturnType = getPublicCollection(period.toLowerCase(),
false);
+ actualReturnType = getPublicCollection(period.toLowerCase(),
periods, i, false);
}
return actualReturnType;
}
@@ -918,7 +991,11 @@
*
* @return public entity name according to class-simple-name
*/
- private String getPublicCollection(String collectionName) {
+ private String getPublicCollection(String collectionName, String[]
periods, int i) {
+ String exception = checkNamingException(COLLECTION_NAME_EXCEPTIONS,
collectionName, periods, i);
+ if (exception != null) {
+ return exception;
+ }
if (this.entitiesMap.containsKey(collectionName.toLowerCase())) {
return this.entitiesMap.get(collectionName.toLowerCase());
}
@@ -931,9 +1008,9 @@
*
* @return public entity name according to class-simple-name
*/
- private String getPublicCollection(String collectionName, boolean
throwError) {
+ private String getPublicCollection(String collectionName, String[]
periods, int i, boolean throwError) {
try {
- return getPublicCollection(collectionName);
+ return getPublicCollection(collectionName, periods, i);
} catch (RuntimeException rte) {
if (!throwError)
return null;
@@ -946,7 +1023,11 @@
*
* @return public collection name according to class-simple-name
*/
- private String getPublicEntity(String entityName) {
+ private String getPublicEntity(String entityName, String[] periods, int i)
{
+ String exception = checkNamingException(ENTITY_NAME_EXCEPTIONS,
entityName, periods, i);
+ if (exception != null) {
+ return exception;
+ }
if (this.entitiesMap.containsKey(entityName.toLowerCase())) {
return this.entitiesMap.get(entityName.toLowerCase());
}
@@ -959,9 +1040,9 @@
*
* @return public collection name according to class-simple-name
*/
- private String getPublicEntity(String entityName, boolean throwError) {
+ private String getPublicEntity(String entityName, String[] periods, int i,
boolean throwError) {
try {
- return getPublicEntity(entityName);
+ return getPublicEntity(entityName, periods, i);
} catch (RuntimeException rte) {
if (!throwError)
return null;
diff --git
a/ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/utils/ArrayUtils.java
b/ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/utils/ArrayUtils.java
index 855fe60..87ac96c 100644
---
a/ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/utils/ArrayUtils.java
+++
b/ovirt-engine-sdk-java-codegen/src/main/java/org/ovirt/engine/sdk/codegen/utils/ArrayUtils.java
@@ -38,4 +38,23 @@
}
return false;
}
+
+ /**
+ * Checks if an array starts with another array, similar to how the {@link
String#startsWith(String)} checks
+ * strings, but comparing objects instead of characters.
+ *
+ * @param array the array to be checked
+ * @param prefix the prefix to look for
+ */
+ public static <T> boolean startsWith(T[] array, T[] prefix) {
+ if (array.length < prefix.length) {
+ return false;
+ }
+ for (int i = 0; i < prefix.length; i++) {
+ if (!array[i].equals(prefix[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
}
--
To view, visit http://gerrit.ovirt.org/29569
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7fcbfe5e490bb23aa2e1785560dd016d63e3a9ae
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine-sdk-java
Gerrit-Branch: master
Gerrit-Owner: Juan Hernandez <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches