aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin, Max <max.benjamin@att.com>2020-04-30 10:41:46 -0400
committerBenjamin, Max (mb388a) <mb388a@att.com>2020-04-30 11:08:10 -0400
commite7f7527a7ad0397f9f98c739f6f4dfba357bcf3a (patch)
tree96db50b73b0a7d096683ecb0672c79cf6897ee90
parent0fdf096ae4ff4ee4b7a644549bd67d75e4aa82b1 (diff)
add fluent type builder support to A&AI client
add fluent type builder support to A&AI client Issue-ID: SO-2856 Signed-off-by: Benjamin, Max (mb388a) <mb388a@att.com> Change-Id: I2957aedb84a1c6b23979ff2e1c4dfb16b3a646c7
-rw-r--r--graph-inventory/aai-client/pom.xml119
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java5
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectName.java23
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectPlurals.java32
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectType.java27
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIQueryClient.java5
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/Relationships.java5
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentPluralType.java12
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentSingleType.java12
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTopLevelType.java11
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTypeReverseLookup.java51
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIUriFactory.java10
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentTopLevelType.java5
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentType.java10
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentTypeBase.java16
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryObjectPlurals.java2
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java6
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/GraphInventoryRelationships.java4
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParser.java4
-rw-r--r--graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParserSpringImpl.java12
-rw-r--r--graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java2
-rw-r--r--graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTypeReverseLookupTest.java74
-rw-r--r--graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAISimpleUriTest.java11
-rw-r--r--graph-inventory/fluent-builder-maven-plugin/pom.xml55
-rw-r--r--graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java324
-rw-r--r--graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGeneratorMojo.java53
-rw-r--r--graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/ObjectField.java26
-rw-r--r--graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/ObjectType.java91
-rw-r--r--graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/SwaggerConverter.java176
-rw-r--r--graph-inventory/pom.xml2
30 files changed, 1161 insertions, 24 deletions
diff --git a/graph-inventory/aai-client/pom.xml b/graph-inventory/aai-client/pom.xml
index c8b10cce1f..754f1bb1f4 100644
--- a/graph-inventory/aai-client/pom.xml
+++ b/graph-inventory/aai-client/pom.xml
@@ -7,6 +7,125 @@
<version>1.6.0-SNAPSHOT</version>
</parent>
<artifactId>aai-client</artifactId>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <versionRange>[1.0.0,)</versionRange>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute />
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.onap.so</groupId>
+ <artifactId>fluent-builder-maven-plugin</artifactId>
+ <goals>
+ <goal>generate-builders</goal>
+ </goals>
+ <versionRange>[0.0,)</versionRange>
+ </pluginExecutionFilter>
+ <action>
+ <execute />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.onap.aai.traversal</groupId>
+ <artifactId>aai-traversal</artifactId>
+ <version>1.6.3</version>
+ <outputDirectory>${project.build.directory}/antlr</outputDirectory>
+ <includes>**/*.g4</includes>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.onap.aai.schema-service</groupId>
+ <artifactId>aai-schema</artifactId>
+ <version>1.6.5</version>
+ <outputDirectory>${project.build.directory}/swagger</outputDirectory>
+ <includes>**/*.yaml</includes>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.onap.so</groupId>
+ <artifactId>fluent-builder-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-builders</goal>
+ </goals>
+ <configuration>
+ <destination>${project.build.directory}/generated-sources</destination>
+ <destinationClasspath>org.onap.aaiclient.client.generated.fluentbuilders</destinationClasspath>
+ <builderName>AAIFluentTypeBuilder</builderName>
+ <swaggerLocation>${project.build.directory}/swagger/onap/aai_swagger_yaml/aai_swagger_v19.yaml</swaggerLocation>
+ <singularBuilderClass>org.onap.aaiclient.client.aai.entities.uri.AAIFluentSingleType</singularBuilderClass>
+ <pluralBuilderClass>org.onap.aaiclient.client.aai.entities.uri.AAIFluentPluralType</pluralBuilderClass>
+ <topLevelBuilderClass>org.onap.aaiclient.client.aai.entities.uri.AAIFluentTopLevelType</topLevelBuilderClass>
+ <baseBuilderClass>org.onap.aaiclient.client.graphinventory.GraphInventoryFluentTypeBase</baseBuilderClass>
+ <singularClass>org.onap.aaiclient.client.aai.AAIObjectType</singularClass>
+ <pluralClass>org.onap.aaiclient.client.aai.AAIObjectPlurals</pluralClass>
+ <nameClass>org.onap.aaiclient.client.aai.AAIObjectName</nameClass>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${project.build.directory}/generated-sources/fluent/</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
<dependencies>
<dependency>
<groupId>org.onap.so</groupId>
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java
index 4c45a675b2..238e87392f 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIDSLQueryClient.java
@@ -21,6 +21,7 @@
package org.onap.aaiclient.client.aai;
import org.onap.aaiclient.client.aai.entities.AAIResultWrapper;
+import org.onap.aaiclient.client.aai.entities.uri.AAIFluentTypeReverseLookup;
import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
import org.onap.aaiclient.client.graphinventory.GraphInventoryQueryClient;
import org.onap.aaiclient.client.graphinventory.entities.DSLQuery;
@@ -49,8 +50,8 @@ public class AAIDSLQueryClient
}
@Override
- public AAIObjectType createType(String name) {
- return AAIObjectType.fromTypeName(name);
+ public AAIObjectType createType(String name, String uri) {
+ return new AAIFluentTypeReverseLookup().fromName(name, uri);
}
}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectName.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectName.java
new file mode 100644
index 0000000000..180a99e88b
--- /dev/null
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectName.java
@@ -0,0 +1,23 @@
+package org.onap.aaiclient.client.aai;
+
+import org.onap.aaiclient.client.graphinventory.GraphInventoryObjectName;
+import com.google.common.base.CaseFormat;
+
+public class AAIObjectName implements GraphInventoryObjectName {
+
+ private final String name;
+
+ public AAIObjectName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String typeName() {
+ return name;
+ }
+
+ @Override
+ public String typeName(CaseFormat format) {
+ return CaseFormat.LOWER_HYPHEN.to(format, this.name);
+ }
+}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectPlurals.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectPlurals.java
index fcda3c8ad4..5b68d0c69a 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectPlurals.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectPlurals.java
@@ -77,12 +77,18 @@ public class AAIObjectPlurals implements AAIObjectBase, GraphInventoryObjectPlur
private final String uriTemplate;
private final String partialUri;
- private final AAIObjectType type;
+ private final String name;
protected AAIObjectPlurals(AAIObjectType type, String parentUri, String partialUri) {
this.uriTemplate = parentUri + partialUri;
this.partialUri = partialUri;
- this.type = type;
+ this.name = type.typeName();
+ }
+
+ public AAIObjectPlurals(String name, String parentUri, String partialUri) {
+ this.uriTemplate = parentUri + partialUri;
+ this.partialUri = partialUri;
+ this.name = name;
}
@Override
@@ -101,17 +107,27 @@ public class AAIObjectPlurals implements AAIObjectBase, GraphInventoryObjectPlur
}
@Override
- public AAIObjectType getType() {
- return this.type;
+ public String typeName() {
+ return this.typeName(CaseFormat.LOWER_HYPHEN);
}
@Override
- public String typeName() {
- return this.getType().typeName();
+ public String typeName(CaseFormat format) {
+ return CaseFormat.LOWER_HYPHEN.to(format, this.name.replace("default-", ""));
}
@Override
- public String typeName(CaseFormat format) {
- return this.getType().typeName(format);
+ public int hashCode() {
+ return this.typeName().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+
+ if (o instanceof AAIObjectBase) {
+ return this.typeName().equals(((AAIObjectBase) o).typeName());
+ }
+
+ return false;
}
}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectType.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectType.java
index 8045a220a3..b3402fa221 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectType.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIObjectType.java
@@ -74,6 +74,7 @@ import org.onap.aai.domain.yang.VolumeGroup;
import org.onap.aai.domain.yang.VpnBinding;
import org.onap.aai.domain.yang.Vserver;
import org.onap.aai.domain.yang.Zone;
+import org.onap.aaiclient.client.aai.entities.uri.AAIFluentTypeReverseLookup;
import org.onap.aaiclient.client.graphinventory.GraphInventoryObjectType;
import org.onap.so.constants.Defaults;
import org.reflections.Reflections;
@@ -262,12 +263,16 @@ public class AAIObjectType implements AAIObjectBase, GraphInventoryObjectType, S
}
protected AAIObjectType(String parentUri, String partialUri, String name) {
+ this(parentUri, partialUri, name, true);
+ }
+
+ public AAIObjectType(String parentUri, String partialUri, String name, boolean register) {
this.parentUri = parentUri;
this.partialUri = partialUri;
this.uriTemplate = parentUri + partialUri;
this.aaiObjectClass = null;
this.name = name;
- if (!AAIObjectType.map.containsKey(name)) {
+ if (register && !AAIObjectType.map.containsKey(name)) {
AAIObjectType.map.put(name, this);
}
}
@@ -288,6 +293,11 @@ public class AAIObjectType implements AAIObjectBase, GraphInventoryObjectType, S
return this.uriTemplate();
}
+ public static AAIObjectType fromTypeName(String name, String uri) {
+
+ return new AAIFluentTypeReverseLookup().fromName(name, uri);
+ }
+
public static AAIObjectType fromTypeName(String name) {
if (map.containsKey(name)) {
return map.get(name);
@@ -316,6 +326,21 @@ public class AAIObjectType implements AAIObjectBase, GraphInventoryObjectType, S
return this.partialUri;
}
+ @Override
+ public int hashCode() {
+ return this.typeName().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+
+ if (o instanceof AAIObjectBase) {
+ return this.typeName().equals(((AAIObjectBase) o).typeName());
+ }
+
+ return false;
+ }
+
protected String removeParentUri(Class<?> aaiObjectClass, String parentUri) {
return aaiObjectClass.getAnnotation(Metadata.class).uriTemplate().replaceFirst(Pattern.quote(parentUri), "");
}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIQueryClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIQueryClient.java
index 5e8b052146..75d4a6ff56 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIQueryClient.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/AAIQueryClient.java
@@ -22,6 +22,7 @@ package org.onap.aaiclient.client.aai;
import org.onap.aaiclient.client.aai.entities.AAIResultWrapper;
import org.onap.aaiclient.client.aai.entities.CustomQuery;
+import org.onap.aaiclient.client.aai.entities.uri.AAIFluentTypeReverseLookup;
import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
import org.onap.aaiclient.client.graphinventory.GraphInventoryQueryClient;
import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventoryUri;
@@ -53,8 +54,8 @@ public class AAIQueryClient
}
@Override
- public AAIObjectType createType(String name) {
- return AAIObjectType.fromTypeName(name);
+ public AAIObjectType createType(String name, String uri) {
+ return new AAIFluentTypeReverseLookup().fromName(name, uri);
}
}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/Relationships.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/Relationships.java
index fb205310fc..b8a80f082c 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/Relationships.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/Relationships.java
@@ -24,6 +24,7 @@ import java.util.List;
import javax.ws.rs.core.UriBuilder;
import org.onap.aaiclient.client.aai.AAIObjectType;
import org.onap.aaiclient.client.aai.AAIResourcesClient;
+import org.onap.aaiclient.client.aai.entities.uri.AAIFluentTypeReverseLookup;
import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
import org.onap.aaiclient.client.graphinventory.GraphInventoryObjectName;
@@ -68,7 +69,7 @@ public class Relationships extends GraphInventoryRelationships<AAIResultWrapper,
}
@Override
- protected AAIObjectType fromTypeName(String name) {
- return AAIObjectType.fromTypeName(name);
+ protected AAIObjectType fromTypeName(String name, String uri) {
+ return new AAIFluentTypeReverseLookup().fromName(name, uri);
}
}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentPluralType.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentPluralType.java
new file mode 100644
index 0000000000..ea81e7b95c
--- /dev/null
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentPluralType.java
@@ -0,0 +1,12 @@
+package org.onap.aaiclient.client.aai.entities.uri;
+
+import org.onap.aaiclient.client.aai.AAIObjectPlurals;
+import org.onap.aaiclient.client.graphinventory.GraphInventoryFluentType;
+
+public interface AAIFluentPluralType extends GraphInventoryFluentType<AAIObjectPlurals> {
+
+ public interface Info extends GraphInventoryFluentType.Info {
+
+
+ }
+}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentSingleType.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentSingleType.java
new file mode 100644
index 0000000000..9310933499
--- /dev/null
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentSingleType.java
@@ -0,0 +1,12 @@
+package org.onap.aaiclient.client.aai.entities.uri;
+
+import org.onap.aaiclient.client.aai.AAIObjectType;
+import org.onap.aaiclient.client.graphinventory.GraphInventoryFluentType;
+
+public interface AAIFluentSingleType extends GraphInventoryFluentType<AAIObjectType> {
+
+ public interface Info extends GraphInventoryFluentType.Info {
+
+
+ }
+}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTopLevelType.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTopLevelType.java
new file mode 100644
index 0000000000..46a521d82e
--- /dev/null
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTopLevelType.java
@@ -0,0 +1,11 @@
+package org.onap.aaiclient.client.aai.entities.uri;
+
+import org.onap.aaiclient.client.graphinventory.GraphInventoryFluentTopLevelType;
+
+public interface AAIFluentTopLevelType extends GraphInventoryFluentTopLevelType {
+
+ public interface Info extends GraphInventoryFluentTopLevelType.Info {
+
+
+ }
+}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTypeReverseLookup.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTypeReverseLookup.java
new file mode 100644
index 0000000000..bd9f4c713f
--- /dev/null
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTypeReverseLookup.java
@@ -0,0 +1,51 @@
+package org.onap.aaiclient.client.aai.entities.uri;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.onap.aaiclient.client.aai.AAIObjectType;
+import org.onap.aaiclient.client.graphinventory.GraphInventoryFluentType;
+import org.onap.aaiclient.client.graphinventory.entities.uri.parsers.UriParserSpringImpl;
+import com.google.common.base.CaseFormat;
+
+public class AAIFluentTypeReverseLookup {
+
+ public AAIObjectType fromName(String name, String uri) {
+
+ String className = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name);
+
+ uri = uri.replaceFirst(".*?/v\\d+", "");
+ try {
+ Class<? extends GraphInventoryFluentType.Info> clazz =
+ (Class<? extends GraphInventoryFluentType.Info>) Class
+ .forName("org.onap.aaiclient.client.generated.fluentbuilders." + className + "$Info");
+
+ GraphInventoryFluentType.Info type = clazz.newInstance();
+
+ Optional<String> parentTemplate = findParentPath(type, uri);
+ if (parentTemplate.isPresent()) {
+ return new AAIObjectType(parentTemplate.get(), type.getPartialUri(), type.getName(), false);
+ } else {
+ // fallback to enum lookup
+ return AAIObjectType.fromTypeName(name);
+ }
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
+ }
+ return AAIObjectType.UNKNOWN;
+ }
+
+ protected Optional<String> findParentPath(GraphInventoryFluentType.Info type, String uri) {
+
+ List<UriParserSpringImpl> parsers =
+ type.getPaths().stream().map(path -> new UriParserSpringImpl(path)).collect(Collectors.toList());
+
+ for (UriParserSpringImpl parser : parsers) {
+ if (parser.isMatch(uri)) {
+ String partialUriReplacer = type.getPartialUri().replaceAll("\\{[^}]+\\}", "[^/]+");
+ return Optional.of(parser.getTemplate().replaceFirst(partialUriReplacer + "$", ""));
+ }
+ }
+
+ return Optional.empty();
+ }
+}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIUriFactory.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIUriFactory.java
index 31b55958d6..6bb2cbd471 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIUriFactory.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/aai/entities/uri/AAIUriFactory.java
@@ -47,6 +47,10 @@ public class AAIUriFactory {
}
}
+ public static AAIResourceUri createResourceUri(AAIFluentSingleType uri) {
+ return new AAISimpleUri(uri.build(), uri.values());
+ }
+
public static NodesSingleUri createNodesUri(AAIObjectType type, Object... values) {
return new NodesSingleUri(type, values);
@@ -88,6 +92,12 @@ public class AAIUriFactory {
return new AAISimplePluralUri(parentUri, childType);
}
+ public static AAISimplePluralUri createResourceUri(AAIFluentPluralType uri) {
+
+ return new AAISimplePluralUri(uri.build());
+
+ }
+
/**
* Creates a uri for a plural type e.g. /cloud-infrastructure/pservers
*
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentTopLevelType.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentTopLevelType.java
new file mode 100644
index 0000000000..9740016d17
--- /dev/null
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentTopLevelType.java
@@ -0,0 +1,5 @@
+package org.onap.aaiclient.client.graphinventory;
+
+public interface GraphInventoryFluentTopLevelType extends GraphInventoryFluentTypeBase {
+
+}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentType.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentType.java
new file mode 100644
index 0000000000..94fa240244
--- /dev/null
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentType.java
@@ -0,0 +1,10 @@
+package org.onap.aaiclient.client.graphinventory;
+
+public interface GraphInventoryFluentType<T> extends GraphInventoryFluentTypeBase {
+
+ public interface Info extends GraphInventoryFluentTypeBase.Info {
+ String getName();
+ }
+
+ T build();
+}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentTypeBase.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentTypeBase.java
new file mode 100644
index 0000000000..1a258fcd88
--- /dev/null
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryFluentTypeBase.java
@@ -0,0 +1,16 @@
+package org.onap.aaiclient.client.graphinventory;
+
+import java.util.List;
+
+public interface GraphInventoryFluentTypeBase {
+
+ public interface Info {
+ String getPartialUri();
+
+ List<String> getPaths();
+ }
+
+ Object[] values();
+
+ String uriTemplate();
+}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryObjectPlurals.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryObjectPlurals.java
index 3eb71b21c2..a2d31f80b5 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryObjectPlurals.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryObjectPlurals.java
@@ -22,6 +22,4 @@ package org.onap.aaiclient.client.graphinventory;
public interface GraphInventoryObjectPlurals extends GraphInventoryObjectBase {
- public GraphInventoryObjectType getType();
-
}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java
index 8aa03e2920..c749561e5f 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/GraphInventoryQueryClient.java
@@ -95,8 +95,8 @@ public abstract class GraphInventoryQueryClient<S, I, Wrapper extends GraphInven
if (!entrySet.getKey().equals("url")) {
String url = (String) m.get("url");
String stringJson = mapper.writeValueAsString(entrySet.getValue());
- result.add(
- new ResourceAndUrl<Wrapper>(url, createType(entrySet.getKey()), createWrapper(stringJson)));
+ result.add(new ResourceAndUrl<Wrapper>(url, createType(entrySet.getKey(), url),
+ createWrapper(stringJson)));
}
}
}
@@ -106,7 +106,7 @@ public abstract class GraphInventoryQueryClient<S, I, Wrapper extends GraphInven
public abstract Wrapper createWrapper(String json);
- public abstract Type createType(String name);
+ public abstract Type createType(String name, String uri);
public S depth(String depth) {
this.depth = Optional.of(depth);
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/GraphInventoryRelationships.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/GraphInventoryRelationships.java
index 7d960877b0..48feba25df 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/GraphInventoryRelationships.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/GraphInventoryRelationships.java
@@ -86,8 +86,8 @@ public abstract class GraphInventoryRelationships<Wrapper extends GraphInventory
final String relatedTo = (String) relationship.get("related-to");
if (p.test(relatedTo)) {
Type type;
- type = fromTypeName(relatedTo);
final String relatedLink = (String) relationship.get("related-link");
+ type = fromTypeName(relatedTo, relatedLink);
result.add(createUri(type, relatedLink));
}
@@ -116,7 +116,7 @@ public abstract class GraphInventoryRelationships<Wrapper extends GraphInventory
protected abstract Uri createUri(Type type, String relatedLink);
- protected abstract Type fromTypeName(String name);
+ protected abstract Type fromTypeName(String name, String uri);
protected List<String> getRelatedLinks(Optional<GraphInventoryObjectName> type) {
String matcher = "";
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParser.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParser.java
index 24a20240e0..c6a2f96550 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParser.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParser.java
@@ -27,4 +27,8 @@ public interface UriParser {
public Set<String> getVariables();
public Map<String, String> parse(final String uri);
+
+ public boolean isMatch(final String uri);
+
+ public String getTemplate();
}
diff --git a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParserSpringImpl.java b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParserSpringImpl.java
index db13ef742a..291e395373 100644
--- a/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParserSpringImpl.java
+++ b/graph-inventory/aai-client/src/main/java/org/onap/aaiclient/client/graphinventory/entities/uri/parsers/UriParserSpringImpl.java
@@ -32,9 +32,16 @@ import org.springframework.web.util.UriUtils;
public class UriParserSpringImpl implements UriParser {
private final UriTemplate uriTemplate;
+ private final String template;
public UriParserSpringImpl(final String template) {
this.uriTemplate = new UriTemplate(template);
+ this.template = template;
+ }
+
+ @Override
+ public boolean isMatch(final String uri) {
+ return this.uriTemplate.matches(uri);
}
@Override
@@ -51,6 +58,11 @@ public class UriParserSpringImpl implements UriParser {
return Collections.unmodifiableSet(new LinkedHashSet<String>(this.uriTemplate.getVariableNames()));
}
+ @Override
+ public String getTemplate() {
+ return this.template;
+ }
+
protected Map<String, String> decodeParams(Map<String, String> map) {
final Map<String, String> result = new LinkedHashMap<>();
diff --git a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java
index 4cb79ef9ad..ca361f46d8 100644
--- a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java
+++ b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/AAIResourcesClientTest.java
@@ -49,7 +49,6 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.onap.aai.domain.yang.GenericVnf;
import org.onap.aai.domain.yang.GenericVnfs;
import org.onap.aai.domain.yang.Relationship;
-import org.onap.so.client.RestClient;
import org.onap.aaiclient.client.aai.entities.AAIEdgeLabel;
import org.onap.aaiclient.client.aai.entities.AAIResultWrapper;
import org.onap.aaiclient.client.aai.entities.uri.AAIPluralResourceUri;
@@ -57,6 +56,7 @@ import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
import org.onap.aaiclient.client.defaultproperties.DefaultAAIPropertiesImpl;
import org.onap.aaiclient.client.graphinventory.exceptions.GraphInventoryMultipleItemsException;
+import org.onap.so.client.RestClient;
import com.github.tomakehurst.wiremock.admin.NotFoundException;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
diff --git a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTypeReverseLookupTest.java b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTypeReverseLookupTest.java
new file mode 100644
index 0000000000..699eac9768
--- /dev/null
+++ b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAIFluentTypeReverseLookupTest.java
@@ -0,0 +1,74 @@
+package org.onap.aaiclient.client.aai.entities.uri;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+import org.onap.aaiclient.client.aai.AAIObjectType;
+
+public class AAIFluentTypeReverseLookupTest {
+
+
+ @Test
+ public void reverseParseEntryUri() {
+ String cloudRegion =
+ "http://localhost:8888/aai/v38/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}";
+ String newvce = "/aai/v9/network/newvces/newvce/{vnf-id2}";
+
+ AAIFluentTypeReverseLookup lookup = new AAIFluentTypeReverseLookup();
+ AAIObjectType type = lookup.fromName("cloud-region", cloudRegion);
+
+ assertEquals("cloud-region", type.typeName());
+ assertEquals("/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}", type.partialUri());
+ assertEquals("/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}",
+ type.uriTemplate());
+
+ type = lookup.fromName("newvce", newvce);
+
+ assertEquals("newvce", type.typeName());
+ assertEquals("/newvces/newvce/{vnf-id2}", type.partialUri());
+ assertEquals("/network/newvces/newvce/{vnf-id2}", type.uriTemplate());
+
+ type = lookup.fromName("unknown-type-of-something", "/some/endpoint");
+
+ assertEquals("unknown", type.typeName());
+
+ }
+
+ @Test
+ public void reverseParseTest() {
+
+ String pserverParent =
+ "/aai/v9/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{l-interface.interface-name}";
+ String cloudRegionParent =
+ "http://localhost:8888/aai/v38/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}";
+ String newVceParent = "/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{l-interface.interface-name}";
+
+
+ AAIFluentTypeReverseLookup lookup = new AAIFluentTypeReverseLookup();
+
+ AAIObjectType type = lookup.fromName("l-interface", pserverParent);
+
+ assertEquals("l-interface", type.typeName());
+ assertEquals("/l-interfaces/l-interface/{l-interface.interface-name}", type.partialUri());
+ assertEquals(
+ "/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{l-interface.interface-name}",
+ type.uriTemplate());
+
+ type = lookup.fromName("l-interface", cloudRegionParent);
+
+ assertEquals("l-interface", type.typeName());
+ assertEquals("/l-interfaces/l-interface/{l-interface.interface-name}", type.partialUri());
+ assertEquals(
+ "/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{l-interface.interface-name}",
+ type.uriTemplate());
+
+ type = lookup.fromName("l-interface", newVceParent);
+
+ assertEquals("l-interface", type.typeName());
+ assertEquals("/l-interfaces/l-interface/{l-interface.interface-name}", type.partialUri());
+ assertEquals("/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{l-interface.interface-name}",
+ type.uriTemplate());
+
+
+
+ }
+}
diff --git a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAISimpleUriTest.java b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAISimpleUriTest.java
index 3b11c01436..f8dd1726d3 100644
--- a/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAISimpleUriTest.java
+++ b/graph-inventory/aai-client/src/test/java/org/onap/aaiclient/client/aai/entities/uri/AAISimpleUriTest.java
@@ -31,6 +31,7 @@ import java.util.Map;
import org.junit.Test;
import org.onap.aaiclient.client.aai.AAIObjectPlurals;
import org.onap.aaiclient.client.aai.AAIObjectType;
+import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder;
import org.onap.aaiclient.client.graphinventory.entities.uri.Depth;
public class AAISimpleUriTest {
@@ -130,4 +131,14 @@ public class AAISimpleUriTest {
assertEquals(e2.build().toString(), uri.build().toString());
}
+
+ @Test
+ public void fluentBuilderTest() {
+ AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
+ .cloudRegion("cloud1", "cloud-id").tenant("tenant-id").vserver("vserver-id"));
+
+ assertEquals(
+ "/cloud-infrastructure/cloud-regions/cloud-region/cloud1/cloud-id/tenants/tenant/tenant-id/vservers/vserver/vserver-id",
+ uri.build().toString());
+ }
}
diff --git a/graph-inventory/fluent-builder-maven-plugin/pom.xml b/graph-inventory/fluent-builder-maven-plugin/pom.xml
new file mode 100644
index 0000000000..7833bce48e
--- /dev/null
+++ b/graph-inventory/fluent-builder-maven-plugin/pom.xml
@@ -0,0 +1,55 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.so</groupId>
+ <artifactId>graph-inventory</artifactId>
+ <version>1.6.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>fluent-builder-maven-plugin</artifactId>
+ <packaging>maven-plugin</packaging>
+ <properties>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>3.6.0</version>
+ <configuration>
+ <goalPrefix>fluent-builder</goalPrefix>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>3.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-annotations</artifactId>
+ <version>3.6.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>2.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-parser</artifactId>
+ <version>1.0.50</version>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup</groupId>
+ <artifactId>javapoet</artifactId>
+ <version>1.12.1</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java
new file mode 100644
index 0000000000..f9c664389b
--- /dev/null
+++ b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGenerator.java
@@ -0,0 +1,324 @@
+package org.onap.graphinventory.generate;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import javax.lang.model.element.Modifier;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.maven.plugin.logging.Log;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.google.common.base.CaseFormat;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeSpec;
+
+public class FluentGenerator {
+
+ private final Map<String, ObjectType> doc;
+ private final String location;
+ private final String CLASSPATH;
+
+ private final String singularBuilderClass;
+ private final String pluralBuilderClass;
+ private final String topLevelBuilderClass;
+ private final String baseBuilderClass;
+ private final String singularClass;
+ private final String pluralClass;
+ private final String builderName;
+ private final String nameClass;
+
+ public FluentGenerator(Log log, String location, String destinationClasspath, String swaggerLocation,
+ String builderName, String singularBuilderClass, String pluralBuilderClass, String topLevelBuilderClass,
+ String baseBuilderClass, String singularClass, String pluralClass, String nameClass)
+ throws JsonProcessingException {
+
+ this.location = location;
+ this.CLASSPATH = destinationClasspath;
+ this.builderName = builderName;
+ this.singularBuilderClass = singularBuilderClass;
+ this.pluralBuilderClass = pluralBuilderClass;
+ this.topLevelBuilderClass = topLevelBuilderClass;
+ this.baseBuilderClass = baseBuilderClass;
+ this.singularClass = singularClass;
+ this.pluralClass = pluralClass;
+ this.nameClass = nameClass;
+ doc = new SwaggerConverter(log).getDoc(swaggerLocation);
+ }
+
+ public void run() throws IOException {
+ List<JavaFile> files = new ArrayList<>();
+ for (Entry<String, ObjectType> entry : doc.entrySet()) {
+ // String key = "routing-instance";
+ // ObjectType oType = test;
+ String key = entry.getKey();
+ ObjectType oType = entry.getValue();
+ MethodSpec.Builder constructor = MethodSpec.constructorBuilder().addModifiers(Modifier.PROTECTED);
+ List<ParameterSpec> constructorParams = new ArrayList<>();
+ List<FieldSpec> classFields = new ArrayList<>();
+
+ if (!oType.getType().equals("top level")) {
+ Pair<String, String> path = splitClasspath(this.baseBuilderClass);
+ ClassName parameterizedTypeName = ClassName.get(path.getLeft(), path.getRight());
+ constructorParams.add(ParameterSpec.builder(parameterizedTypeName, "parentObj").build());
+ classFields.add(FieldSpec.builder(parameterizedTypeName, "parentObj")
+ .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build());
+ }
+ List<ParameterSpec> typeParams = new ArrayList<>();
+
+ for (ObjectField oF : oType.getFields()) {
+ if (oF.getType().equals("string")) {
+ typeParams.add(ParameterSpec.builder(String.class, lowerCamel(makeValidJavaVariable(oF.getName())))
+ .build());
+ classFields.add(FieldSpec.builder(String.class, lowerCamel(makeValidJavaVariable(oF.getName())))
+ .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build());
+ } else if (oF.getType().equals("integer")) {
+ typeParams.add(
+ ParameterSpec.builder(int.class, lowerCamel(makeValidJavaVariable(oF.getName()))).build());
+ classFields.add(FieldSpec.builder(int.class, lowerCamel(makeValidJavaVariable(oF.getName())))
+ .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build());
+ }
+ }
+ constructorParams.addAll(typeParams);
+ constructor.addParameters(constructorParams);
+ for (ParameterSpec p : constructorParams) {
+ constructor.addStatement("this.$L = $L", p.name, p.name);
+
+ }
+ List<MethodSpec> methods = new ArrayList<>();
+ methods.add(constructor.build());
+
+ methods.addAll(createChildMethods(oType));
+
+ methods.addAll(createInterfaceMethods(oType, typeParams));
+
+ ClassName superType = null;
+ if (oType.getType().equals("top level")) {
+ Pair<String, String> path = splitClasspath(this.topLevelBuilderClass);
+ superType = ClassName.get(path.getLeft(), path.getRight());
+ } else {
+ if (oType.getType().equals("singular")) {
+ Pair<String, String> path = splitClasspath(this.singularBuilderClass);
+ superType = ClassName.get(path.getLeft(), path.getRight());
+
+ } else if (oType.getType().equals("plural")) {
+ Pair<String, String> path = splitClasspath(this.pluralBuilderClass);
+ superType = ClassName.get(path.getLeft(), path.getRight());
+ }
+ }
+
+ TypeSpec type = TypeSpec.classBuilder(upperCamel(key)).addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addType(createInnerInfoClass(oType)).addSuperinterface(superType).addFields(classFields)
+ .addMethods(methods).build();
+
+ files.add(JavaFile.builder(CLASSPATH, type).build());
+
+ }
+
+ files.add(createBuilderClass());
+
+ files.stream().forEach(javaFile -> {
+ try {
+ javaFile.writeTo(Paths.get(location, "fluent"));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ }
+
+ protected List<MethodSpec> createInterfaceMethods(ObjectType oType, List<ParameterSpec> typeParams) {
+
+ List<MethodSpec> methods = new ArrayList<>();
+
+ CodeBlock.Builder uriTemplateCodeBlock = CodeBlock.builder();
+ if (!oType.getType().equals("top level")) {
+ uriTemplateCodeBlock.add("return this.parentObj.uriTemplate() + Info.partialUri");
+ } else {
+ uriTemplateCodeBlock.add("return Info.partialUri");
+
+ }
+ methods.add(MethodSpec.methodBuilder("uriTemplate").returns(String.class).addModifiers(Modifier.PUBLIC)
+ .addStatement(uriTemplateCodeBlock.build()).addAnnotation(Override.class).build());
+
+ ClassName arrayUtils = ClassName.get(ArrayUtils.class);
+
+ CodeBlock.Builder valuesReturn = CodeBlock.builder();
+
+ if (oType.getType().equals("top level")) {
+ valuesReturn.add("return new Object[0]");
+ } else {
+ if (!typeParams.isEmpty()) {
+ valuesReturn.add("return $T.addAll(this.parentObj.values(), $L)", arrayUtils, String.join(", ",
+ typeParams.stream().map(item -> "this." + item.name).collect(Collectors.toList())));
+ } else {
+ valuesReturn.add("return this.parentObj.values()");
+ }
+ }
+ methods.add(MethodSpec.methodBuilder("values").returns(Object[].class).addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class).addStatement(valuesReturn.build()).build());
+
+ if (!oType.getType().equals("top level")) {
+ ClassName returnType = null;
+ CodeBlock.Builder block = CodeBlock.builder();
+ if (oType.getType().equals("singular")) {
+ Pair<String, String> path = splitClasspath(this.singularClass);
+ returnType = ClassName.get(path.getLeft(), path.getRight());
+ block.add("return new $T(this.parentObj.uriTemplate(), Info.partialUri, Info.name, false)", returnType);
+ } else if (oType.getType().equals("plural")) {
+ Pair<String, String> path = splitClasspath(this.pluralClass);
+ returnType = ClassName.get(path.getLeft(), path.getRight());
+ block.add("return new $T(Info.name, this.parentObj.uriTemplate(), Info.partialUri)", returnType);
+ }
+
+ methods.add(MethodSpec.methodBuilder("build").returns(returnType).addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class).addStatement(block.build()).build());
+
+ }
+
+ return methods;
+ }
+
+ protected List<MethodSpec> createChildMethods(ObjectType oType) {
+ List<MethodSpec> methods = new ArrayList<>();
+ for (String child : oType.getChildren()) {
+ methods.add(createAccessMethod(doc.get(child), true, false));
+ }
+
+ return methods;
+ }
+
+ protected MethodSpec createAccessMethod(ObjectType oType, boolean isChild, boolean isStatic) {
+
+ ClassName childClass = ClassName.get(CLASSPATH, upperCamel(oType.getName()));
+ MethodSpec.Builder b = MethodSpec.methodBuilder(lowerCamel(oType.getName())).returns(childClass);
+ List<Modifier> modifiers = new ArrayList<>();
+ if (isStatic) {
+ modifiers.add(Modifier.STATIC);
+ }
+ modifiers.add(Modifier.PUBLIC);
+ b.addModifiers(modifiers);
+ List<ParameterSpec> params = new ArrayList<>();
+ for (ObjectField oF : doc.get(oType.getName()).getFields()) {
+ if (oF.getType().equals("string")) {
+ params.add(
+ ParameterSpec.builder(String.class, lowerCamel(makeValidJavaVariable(oF.getName()))).build());
+ } else if (oF.getType().equals("integer")) {
+ params.add(ParameterSpec.builder(int.class, lowerCamel(makeValidJavaVariable(oF.getName()))).build());
+ }
+ }
+ List<String> paramNames = params.stream().map(item -> item.name).collect(Collectors.toList());
+ if (isChild) {
+ paramNames.add(0, "this");
+ }
+ b.addParameters(params).addStatement("return new $T($L)", childClass, String.join(", ", paramNames));
+
+ return b.build();
+ }
+
+ protected JavaFile createBuilderClass() {
+
+ List<MethodSpec> methods = doc.values().stream().filter(item -> item.getType().equals("top level"))
+ .map(item -> createAccessMethod(item, false, true)).collect(Collectors.toList());
+
+ TypeSpec type = TypeSpec.classBuilder(this.builderName).addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addMethods(methods).addType(createTypes()).build();
+
+ return JavaFile.builder(CLASSPATH, type).build();
+
+ }
+
+ protected TypeSpec createTypes() {
+ Pair<String, String> path = splitClasspath(this.nameClass);
+ ClassName nameType = ClassName.get(path.getLeft(), path.getRight());
+
+ List<FieldSpec> params =
+ doc.values().stream().filter(item -> item.getType().equals("singular"))
+ .sorted(Comparator
+ .comparing(item -> item.getName()))
+ .map(item -> FieldSpec
+ .builder(nameType,
+ CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, item.getName()),
+ Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
+ .initializer("new $T($S)", nameType, item.getName()).build())
+ .collect(Collectors.toList());
+
+ TypeSpec type = TypeSpec.classBuilder("Types").addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC)
+ .addFields(params).build();
+
+ return type;
+
+ }
+
+ protected TypeSpec createInnerInfoClass(ObjectType oType) {
+ List<FieldSpec> classFields = new ArrayList<>();
+ List<MethodSpec> methods = new ArrayList<>();
+
+ classFields.add(FieldSpec.builder(String.class, "partialUri")
+ .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC)
+ .initializer("$S", oType.getPartialUri()).build());
+
+ classFields.add(FieldSpec.builder(ParameterizedTypeName.get(List.class, String.class), "paths")
+ .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC)
+ .initializer("$T.asList($L)", ClassName.get(Arrays.class),
+ "\"" + oType.getPaths().stream().collect(Collectors.joining("\", \"")) + "\"")
+ .build());
+
+ ClassName superInterface;
+ if (oType.getType().equals("plural")) {
+ classFields.add(FieldSpec.builder(String.class, "name")
+ .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC)
+ .initializer("$S", oType.getAdditionalName()).build());
+ superInterface = ClassName.get(this.pluralBuilderClass, "Info");
+ } else if (oType.getType().equals("singular")) {
+ classFields.add(FieldSpec.builder(String.class, "name")
+ .addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC).initializer("$S", oType.getName())
+ .build());
+ superInterface = ClassName.get(this.singularBuilderClass, "Info");
+ } else {
+ superInterface = ClassName.get(this.topLevelBuilderClass, "Info");
+ }
+ methods.add(MethodSpec.methodBuilder("getPaths").returns(ParameterizedTypeName.get(List.class, String.class))
+ .addModifiers(Modifier.PUBLIC).addAnnotation(Override.class).addStatement("return Info.paths").build());
+ methods.add(MethodSpec.methodBuilder("getPartialUri").returns(String.class).addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class).addStatement("return Info.partialUri").build());
+ if (!oType.getType().equals("top level")) {
+ methods.add(MethodSpec.methodBuilder("getName").returns(String.class).addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class).addStatement("return Info.name").build());
+ }
+ return TypeSpec.classBuilder("Info").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .addSuperinterface(superInterface).addFields(classFields).addMethods(methods).build();
+
+ }
+
+ protected String makeValidJavaVariable(String name) {
+
+ return name.replace(".", "_");
+ }
+
+ protected Pair<String, String> splitClasspath(String path) {
+
+ return Pair.of(path.substring(0, path.lastIndexOf(".")),
+ path.substring(path.lastIndexOf(".") + 1, path.length()));
+ }
+
+ protected String lowerCamel(String s) {
+ return CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, s);
+ }
+
+ protected String upperCamel(String s) {
+ return CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, s);
+ }
+
+}
diff --git a/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGeneratorMojo.java b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGeneratorMojo.java
new file mode 100644
index 0000000000..9de249faa2
--- /dev/null
+++ b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/FluentGeneratorMojo.java
@@ -0,0 +1,53 @@
+package org.onap.graphinventory.generate;
+
+import java.io.IOException;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+@Mojo(name = "generate-builders", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
+public class FluentGeneratorMojo extends AbstractMojo {
+
+ @Parameter
+ private String destination;
+ @Parameter
+ private String destinationClasspath;
+ @Parameter
+ private String builderName;
+ @Parameter
+ private String swaggerLocation;
+ @Parameter
+ private String singularBuilderClass;
+ @Parameter
+ private String pluralBuilderClass;
+ @Parameter
+ private String topLevelBuilderClass;
+ @Parameter
+ private String baseBuilderClass;
+ @Parameter
+ private String singularClass;
+ @Parameter
+ private String pluralClass;
+ @Parameter
+ private String nameClass;
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+
+ try {
+ new FluentGenerator(getLog(), destination, destinationClasspath, swaggerLocation, builderName,
+ singularBuilderClass, pluralBuilderClass, topLevelBuilderClass, baseBuilderClass, singularClass,
+ pluralClass, nameClass).run();
+ } catch (JsonProcessingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/ObjectField.java b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/ObjectField.java
new file mode 100644
index 0000000000..7c93804bd1
--- /dev/null
+++ b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/ObjectField.java
@@ -0,0 +1,26 @@
+package org.onap.graphinventory.generate;
+
+public class ObjectField {
+
+
+ private String name;
+ private String type;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+
+}
diff --git a/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/ObjectType.java b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/ObjectType.java
new file mode 100644
index 0000000000..3e7f7dcd46
--- /dev/null
+++ b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/ObjectType.java
@@ -0,0 +1,91 @@
+package org.onap.graphinventory.generate;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ObjectType {
+
+ private List<String> paths = new ArrayList<>();
+
+ private Set<String> children = new HashSet<>();
+
+ private String name;
+
+ private String additionalName;
+
+ private String topLevel;
+
+ private String type;
+
+ private String partialUri;
+
+ private List<ObjectField> fields = new ArrayList<>();
+
+ public List<String> getPaths() {
+ return paths;
+ }
+
+ public void setPaths(List<String> paths) {
+ this.paths = paths;
+ }
+
+ public String getTopLevel() {
+ return topLevel;
+ }
+
+ public void setTopLevel(String topLevel) {
+ this.topLevel = topLevel;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public List<ObjectField> getFields() {
+ return fields;
+ }
+
+ public void setFields(List<ObjectField> fields) {
+ this.fields = fields;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Set<String> getChildren() {
+ return children;
+ }
+
+ public void setChildren(Set<String> children) {
+ this.children = children;
+ }
+
+ public String getPartialUri() {
+ return partialUri;
+ }
+
+ public void setPartialUri(String partialUri) {
+ this.partialUri = partialUri;
+ }
+
+ public String getAdditionalName() {
+ return additionalName;
+ }
+
+ public void setAdditionalName(String additionalName) {
+ this.additionalName = additionalName;
+ }
+
+
+}
diff --git a/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/SwaggerConverter.java b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/SwaggerConverter.java
new file mode 100644
index 0000000000..b3ced65390
--- /dev/null
+++ b/graph-inventory/fluent-builder-maven-plugin/src/main/java/org/onap/graphinventory/generate/SwaggerConverter.java
@@ -0,0 +1,176 @@
+package org.onap.graphinventory.generate;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import org.apache.maven.plugin.logging.Log;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.swagger.models.Path;
+import io.swagger.models.Swagger;
+import io.swagger.models.parameters.Parameter;
+import io.swagger.models.parameters.SerializableParameter;
+import io.swagger.parser.SwaggerParser;
+
+public class SwaggerConverter {
+
+ private final Log log;
+
+ public SwaggerConverter(Log log) {
+ this.log = log;
+ }
+
+ public Map<String, ObjectType> getDoc(String swaggerLocation) throws JsonProcessingException {
+ Swagger swagger = new SwaggerParser().read(swaggerLocation);
+
+ Map<String, Path> paths = swagger.getPaths().entrySet().stream()
+ .filter(item -> !item.getKey().endsWith("/relationship-list/relationship"))
+ .collect(Collectors.toMap(item -> item.getKey(), item -> item.getValue()));
+
+ Pattern pluralPattern = Pattern.compile(".*(?<partial>/(?<name>[^{]*$))");
+ Pattern singularPattern = Pattern.compile(".*(?<partial>/(?<name>[^/{}]*)/\\{.*$)");
+ Pattern topLevelPattern = Pattern.compile("^/([^/]+)/.*");
+ Pattern urlTemplatePattern = Pattern.compile("\\{([^}]+)\\}");
+ Matcher pluralMatcher;
+ Matcher singularMatcher;
+ Matcher topLevelMatcher;
+
+ Map<String, ObjectType> output = new HashMap<>();
+ for (Map.Entry<String, Path> entry : paths.entrySet()) {
+
+ pluralMatcher = pluralPattern.matcher(entry.getKey());
+ singularMatcher = singularPattern.matcher(entry.getKey());
+ topLevelMatcher = topLevelPattern.matcher(entry.getKey());
+ ObjectType item;
+ if (pluralMatcher.matches()) {
+ if (!output.containsKey(pluralMatcher.group("name"))) {
+ output.put(pluralMatcher.group("name"), new ObjectType());
+ }
+ item = output.get(pluralMatcher.group("name"));
+ item.setType("plural");
+ item.setName(pluralMatcher.group("name"));
+ item.setPartialUri(pluralMatcher.group("partial"));
+ item.getPaths().add(entry.getKey());
+
+ if (topLevelMatcher.matches()) {
+ item.setTopLevel(topLevelMatcher.group(1));
+ if (!output.containsKey(topLevelMatcher.group(1))) {
+ output.put(topLevelMatcher.group(1), new ObjectType());
+ output.get(topLevelMatcher.group(1)).setType("top level");
+ output.get(topLevelMatcher.group(1)).setName(topLevelMatcher.group(1));
+ output.get(topLevelMatcher.group(1)).setPartialUri("/" + topLevelMatcher.group(1));
+ output.get(topLevelMatcher.group(1)).getPaths().add("/" + topLevelMatcher.group(1));
+
+ }
+ }
+ } else if (singularMatcher.matches()) {
+
+ if (!output.containsKey(singularMatcher.group("name"))) {
+ output.put(singularMatcher.group("name"), new ObjectType());
+
+ item = output.get(singularMatcher.group("name"));
+
+ item.setType("singular");
+ item.setName(singularMatcher.group("name"));
+ item.setPartialUri(singularMatcher.group("partial"));
+
+ item.getPaths().add(entry.getKey());
+
+ if (topLevelMatcher.matches()) {
+ item.setTopLevel(topLevelMatcher.group(1));
+ if (!output.containsKey(topLevelMatcher.group(1))) {
+ output.put(topLevelMatcher.group(1), new ObjectType());
+ output.get(topLevelMatcher.group(1)).setType("top level");
+ output.get(topLevelMatcher.group(1)).setName(topLevelMatcher.group(1));
+ output.get(topLevelMatcher.group(1)).setPartialUri("/" + topLevelMatcher.group(1));
+ output.get(topLevelMatcher.group(1)).getPaths().add("/" + topLevelMatcher.group(1));
+ }
+ }
+ List<Parameter> parameters = entry.getValue().getGet().getParameters();
+
+ if (parameters != null) {
+ parameters.stream().filter(param -> "path".equals(param.getIn())).collect(Collectors.toList());
+ }
+ for (Parameter p : parameters) {
+ ObjectField field = new ObjectField();
+
+ field.setName(p.getName());
+ field.setType(((SerializableParameter) p).getType());
+ item.getFields().add(field);
+ }
+
+ } else {
+ item = output.get(singularMatcher.group("name"));
+ if (singularMatcher.group("partial").contains(item.getName() + ".")) {
+ item.setPartialUri(singularMatcher.group("partial"));
+ }
+ item.getPaths().add(entry.getKey());
+ }
+ }
+
+ }
+ ObjectMapper mapper = new ObjectMapper();
+
+ for (ObjectType item : output.values()) {
+ for (String path : item.getPaths()) {
+ String partialUriReplacer = item.getPartialUri().replaceAll("\\{[^}]+\\}", "[^/]+");
+ String childParentUri = path.replaceFirst(partialUriReplacer + "$", "");
+ for (ObjectType itemToUpdate : output.values()) {
+ if (itemToUpdate.getPaths().stream()
+ .anyMatch(itemToUpdateUri -> itemToUpdateUri.equals(childParentUri))) {
+ itemToUpdate.getChildren().add(item.getName());
+ }
+ }
+ }
+ }
+
+ log.debug(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(output));
+
+ for (Map.Entry<String, ObjectType> item : output.entrySet()) {
+
+ if (item.getValue().getType().equals("plural")) {
+ Set<String> children = item.getValue().getChildren();
+ // should only be one
+ if (!children.isEmpty()) {
+ item.getValue().setAdditionalName(children.iterator().next());
+ }
+ }
+ Set<String> pluralChildren = new HashSet<>();
+ for (String child : item.getValue().getChildren()) {
+ if (output.get(child).getType().equals("plural")) {
+ Set<String> children = output.get(child).getChildren();
+ pluralChildren.addAll(children);
+ }
+ }
+ item.getValue().getChildren().addAll(pluralChildren);
+
+ if (item.getValue().getType().equals("plural")) {
+ for (String child : item.getValue().getChildren()) {
+ output.get(child)
+ .setPartialUri(item.getValue().getPartialUri() + output.get(child).getPartialUri());
+ }
+ }
+
+ if (!item.getValue().getFields().isEmpty()) {
+ Matcher templates = urlTemplatePattern.matcher(item.getValue().getPartialUri());
+ List<String> localFields = new ArrayList<>();
+ while (templates.find()) {
+ localFields.add(templates.group(1));
+ }
+ item.getValue().setFields(item.getValue().getFields().stream()
+ .filter(f -> localFields.contains(f.getName())).collect(Collectors.toList()));
+ }
+ }
+
+ output.values().stream().filter(item -> item.getType().equals("plural"))
+ .forEach(item -> item.getChildren().clear());
+
+ return output;
+ }
+}
diff --git a/graph-inventory/pom.xml b/graph-inventory/pom.xml
index d01b0ec682..0f465b03b1 100644
--- a/graph-inventory/pom.xml
+++ b/graph-inventory/pom.xml
@@ -9,7 +9,7 @@
<artifactId>graph-inventory</artifactId>
<packaging>pom</packaging>
<modules>
- <!-- <module>fluent-builder-maven-plugin</module>-->
+ <module>fluent-builder-maven-plugin</module>
<module>aai-client</module>
</modules>
</project>