diff options
author | Steve Smokowski <ss835w@att.com> | 2020-05-01 14:19:45 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2020-05-01 14:19:45 +0000 |
commit | 52ecd9c8163060b6715e1f13055d680c90229e65 (patch) | |
tree | f525fc36ffe1392ef2ade955e6cfebcb7b667962 | |
parent | 9d305608206854a1820e742aaccd69fab2974353 (diff) | |
parent | e7f7527a7ad0397f9f98c739f6f4dfba357bcf3a (diff) |
Merge "add fluent type builder support to A&AI client"
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> |