diff options
author | Pavel Paroulek <pavel.paroulek@orange.com> | 2019-08-15 14:07:14 +0200 |
---|---|---|
committer | Pavel Paroulek <pavel.paroulek@orange.com> | 2019-08-15 14:07:14 +0200 |
commit | aaa166d1fd35fa712f20623a12ecb088fb9051bf (patch) | |
tree | 21d510810c71193cb0fd5a47a36fe731a7c23968 /src/main | |
parent | 23874dc27b9fbccb7c160aac0ae65f5b94c4af54 (diff) |
Adding export for Papyrus using a velocity template
Change-Id: Ie3d5af8b9821365d30f9e645239ed04d4f8e8c77
Signed-off-by: Pavel Paroulek <pavel.paroulek@orange.com>
Issue-ID: AAI-531
Diffstat (limited to 'src/main')
7 files changed, 490 insertions, 1 deletions
diff --git a/src/main/java/org/onap/aai/graphgraph/App.java b/src/main/java/org/onap/aai/graphgraph/App.java index 002876c..33172ca 100644 --- a/src/main/java/org/onap/aai/graphgraph/App.java +++ b/src/main/java/org/onap/aai/graphgraph/App.java @@ -19,11 +19,12 @@ */ package org.onap.aai.graphgraph; +import static org.onap.aai.graphgraph.ModelExporter.exportModel; + import java.util.HashMap; import java.util.Map; import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.introspection.MoxyLoader; -import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.nodes.NodeIngestor; import org.onap.aai.restclient.PropertyPasswordConfiguration; import org.onap.aai.setup.SchemaVersion; @@ -48,10 +49,16 @@ public class App{ } public static void main( String[] args ) { + ArgumentParser parser = new ArgumentParser().parseArguments(args); SpringApplication app = new SpringApplication(App.class); app.addInitializers(new PropertyPasswordConfiguration()); ConfigurableApplicationContext context = app.run(args); loadSchemes(context); edgeIngestor = (EdgeIngestor) context.getBean("edgeIngestor"); + + if (parser.shoudGenerateUml()){ + exportModel(parser.getSchemaVersion()); + System.exit(0); + } } } diff --git a/src/main/java/org/onap/aai/graphgraph/ArgumentParser.java b/src/main/java/org/onap/aai/graphgraph/ArgumentParser.java new file mode 100644 index 0000000..4940a25 --- /dev/null +++ b/src/main/java/org/onap/aai/graphgraph/ArgumentParser.java @@ -0,0 +1,54 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 Orange Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.graphgraph; + +import org.kohsuke.args4j.CmdLineException; +import org.kohsuke.args4j.CmdLineParser; +import org.kohsuke.args4j.Option; + +public class ArgumentParser { + @Option(name = "-g", usage = "schema to be generated", metaVar = "schema") + private String schemaVersion; + + public ArgumentParser parseArguments(String [] args){ + CmdLineParser parser = new CmdLineParser(this); + + try { + parser.parseArgument(args); + } catch( CmdLineException e ) { + System.err.println(e.getMessage()); + parser.printUsage(System.err); + } + + return this; + } + + public String getSchemaVersion() { + return schemaVersion; + } + + public void setSchemaVersion(String schemaVersion) { + this.schemaVersion = schemaVersion; + } + + public boolean shoudGenerateUml(){ + return schemaVersion != null; + } +} diff --git a/src/main/java/org/onap/aai/graphgraph/ModelExporter.java b/src/main/java/org/onap/aai/graphgraph/ModelExporter.java new file mode 100644 index 0000000..0410250 --- /dev/null +++ b/src/main/java/org/onap/aai/graphgraph/ModelExporter.java @@ -0,0 +1,170 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 Orange Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.graphgraph; + +import com.google.common.collect.Multimap; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; +import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.edges.enums.DirectionNotation; +import org.onap.aai.edges.enums.EdgeField; +import org.onap.aai.edges.enums.MultiplicityRule; +import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; +import org.onap.aai.graphgraph.velocity.VelocityAssociation; +import org.onap.aai.graphgraph.velocity.VelocityEntity; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.setup.SchemaVersion; + +public class ModelExporter { + + private static final String AAIMODEL_UML_FILENAME = "aaimodel.uml"; + public static final String VELOCITY_TEMPLATE_FILENAME = "model_export.vm"; + + private static Multimap<String, EdgeRule> getEdgeRules(String schemaVersion) { + try { + Multimap<String, EdgeRule> allRules = App.edgeIngestor.getAllRules(new SchemaVersion(schemaVersion)); + Map<String, Introspector> allEntities = App.moxyLoaders.get("v16").getAllObjects(); + for (Entry<String, Introspector> currentParent : allEntities.entrySet()) { + currentParent.getValue().getProperties().stream() + .filter(v -> allEntities.containsKey(v)) + .filter(v -> !currentParent.getKey().equals(v)) + .forEach(v -> { + String key = currentParent.getKey() + "|" + v; + if (!allRules.containsKey(key)) { + allRules.put(key, createEdgeRule(currentParent.getKey(), v)); + } + }); + } + return allRules; + } catch (EdgeRuleNotFoundException e) { + e.printStackTrace(); + } + + return null; + } + + private static EdgeRule createEdgeRule(String parent, String child) { + Map<String, String> edgeRuleProps = new HashMap<>(); + edgeRuleProps.put(EdgeField.FROM.toString(), child); + edgeRuleProps.put(EdgeField.TO.toString(), parent); + edgeRuleProps.put(EdgeField.DIRECTION.toString(), Direction.OUT.toString()); //TODO check direction + edgeRuleProps.put(EdgeField.LABEL.toString(), "OXM Parent-Child"); + edgeRuleProps.put(EdgeField.MULTIPLICITY.toString(), MultiplicityRule.MANY2ONE.toString()); + edgeRuleProps.put(EdgeField.DEFAULT.toString(), Boolean.toString(false)); + edgeRuleProps.put(EdgeField.PRIVATE.toString(), Boolean.toString(false)); + edgeRuleProps.put(EdgeField.DELETE_OTHER_V.toString(), DirectionNotation.DIRECTION.toString()); + edgeRuleProps.put(EdgeField.PREVENT_DELETE.toString(), DirectionNotation.DIRECTION.toString()); + edgeRuleProps.put(EdgeField.CONTAINS.toString(), DirectionNotation.DIRECTION.toString()); + edgeRuleProps.put(EdgeField.DESCRIPTION.toString(), "fake edgerule representing parent-child"); + return new EdgeRule(edgeRuleProps); + } + + static void exportModel(String schemaVersion) { + Map<String, Introspector> allObjects = App.moxyLoaders.get(schemaVersion).getAllObjects(); + Template t = initVelocity(); + VelocityContext context = populateVelocityContext(schemaVersion, allObjects); + StringWriter writer = new StringWriter(); + t.merge( context, writer ); + try { + FileWriter fw = new FileWriter(AAIMODEL_UML_FILENAME); + fw.write(writer.toString()); + fw.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static VelocityContext populateVelocityContext(String schemaVersion, + Map<String, Introspector> allObjects) { + VelocityContext context = new VelocityContext(); + Multimap<String, EdgeRule> edgeRules = getEdgeRules(schemaVersion); + Set<VelocityEntity> entityList = createEntityList(edgeRules); + Set<VelocityAssociation> associationsList = createVelocityAssociations(entityList, edgeRules); + updateEntities(entityList, associationsList, allObjects); + context.put("entityList", entityList); + context.put("associationList", associationsList); + return context; + } + + private static Template initVelocity() { + VelocityEngine ve = new VelocityEngine(); + ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); + ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); + ve.init(); + return ve.getTemplate(VELOCITY_TEMPLATE_FILENAME); + } + + private static void updateEntities(Set<VelocityEntity> entityList, + Set<VelocityAssociation> associationsList, + Map<String, Introspector> allObjects) { + entityList.forEach(e -> { + List<VelocityAssociation> associations = associationsList.stream() + .filter(a -> a.getFromEntityId().equals(e.getId())).collect( + Collectors.toList()); + + entityList.forEach(entity -> entity.setProperties(allObjects.get(entity.getName()).getProperties())); + + e.setNeighbours(associations); + }); + } + + private static Set<VelocityEntity> createEntityList( + Multimap<String, EdgeRule> edgeRules) { + return Objects.requireNonNull(edgeRules).values().stream() + .flatMap(er -> Stream.of(er.getFrom(), er.getTo())) + .map(VelocityEntity::new) + .collect(Collectors.toSet()); + } + + private static Set<VelocityAssociation> createVelocityAssociations(Set<VelocityEntity> entities, + Multimap<String, EdgeRule> edgeRules) { + Set<VelocityAssociation> result = new HashSet<>(); + result.addAll(edgeRules.values().stream().map(er -> + new VelocityAssociation( + findVelocityEntity(er.getFrom(), entities), + findVelocityEntity(er.getTo(), entities), + String.format("%s - %s (label: %s)", er.getFrom(), er.getTo(), er.getLabel()), + er.getMultiplicityRule().name(), + er.getLabel().equals("org.onap.relationships.inventory.BelongsTo") + )).collect(Collectors.toSet())); + + return result; + } + + private static VelocityEntity findVelocityEntity(String from, Set<VelocityEntity> entities) { + return entities.stream().filter(e -> e.getName().equals(from)).findFirst().get(); + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/aai/graphgraph/velocity/VelocityAssociation.java b/src/main/java/org/onap/aai/graphgraph/velocity/VelocityAssociation.java new file mode 100644 index 0000000..bcc314e --- /dev/null +++ b/src/main/java/org/onap/aai/graphgraph/velocity/VelocityAssociation.java @@ -0,0 +1,104 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 Orange Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.graphgraph.velocity; + +public class VelocityAssociation extends VelocityId { + + private final String name; + private final VelocityEntity fromEntity; + private final VelocityEntity toEntity; + private final String fromId = getRandomId(); + private final String toId = getRandomId(); + private final String multiplicity; + private final boolean isComposition; + + public VelocityAssociation(VelocityEntity fromEntity, + VelocityEntity toEntity, String name, String multiplicity, boolean isComposition) { + this.fromEntity = fromEntity; + this.toEntity = toEntity; + this.name = name; + this.multiplicity = multiplicity; + this.isComposition = isComposition; + } + + public String getFromEntityName(){ + return fromEntity.getName(); + } + + public String getToEntityName(){ + return toEntity.getName(); + } + + public String getFromEntityId(){ + return fromEntity.getId(); + } + + public String getToEntityId(){ + return toEntity.getId(); + } + + public String getFromId() { + return fromId; + } + + public String getToId() { + return toId; + } + + public String getName() { + return name; + } + + public String getMultiplicity() { + return multiplicity.toUpperCase(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + VelocityAssociation that = (VelocityAssociation) o; + + if (!name.equals(that.name)) { + return false; + } + if (!fromEntity.equals(that.fromEntity)) { + return false; + } + return toEntity.equals(that.toEntity); + } + + public boolean getIsComposition() { + return isComposition; + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + fromEntity.hashCode(); + result = 31 * result + toEntity.hashCode(); + return result; + } +} diff --git a/src/main/java/org/onap/aai/graphgraph/velocity/VelocityEntity.java b/src/main/java/org/onap/aai/graphgraph/velocity/VelocityEntity.java new file mode 100644 index 0000000..111f67c --- /dev/null +++ b/src/main/java/org/onap/aai/graphgraph/velocity/VelocityEntity.java @@ -0,0 +1,76 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 Orange Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.graphgraph.velocity; + +import java.util.List; +import java.util.Set; + +public class VelocityEntity extends VelocityId { + private String name; + private List<VelocityAssociation> neighbours; + private Set<String> properties; + + public Set<String> getProperties() { + return properties; + } + + public void setProperties(Set<String> properties) { + this.properties = properties; + } + + public VelocityEntity(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List<VelocityAssociation> getNeighbours() { + return neighbours; + } + + public void setNeighbours(List<VelocityAssociation> neighbours) { + this.neighbours = neighbours; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + VelocityEntity that = (VelocityEntity) o; + + return name.equals(that.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/src/main/java/org/onap/aai/graphgraph/velocity/VelocityId.java b/src/main/java/org/onap/aai/graphgraph/velocity/VelocityId.java new file mode 100644 index 0000000..fc44a5e --- /dev/null +++ b/src/main/java/org/onap/aai/graphgraph/velocity/VelocityId.java @@ -0,0 +1,34 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 Orange Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.graphgraph.velocity; + +import java.util.UUID; + +public abstract class VelocityId { + private String id = getRandomId(); + + public String getId() { + return id; + } + + public String getRandomId() { + return UUID.randomUUID().toString(); + } +} diff --git a/src/main/resources/model_export.vm b/src/main/resources/model_export.vm new file mode 100644 index 0000000..c15805c --- /dev/null +++ b/src/main/resources/model_export.vm @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_Z9InoLIpEemXwfLFUQ7Icw" name="AAIModel"> + <packageImport xmi:type="uml:PackageImport" xmi:id="_aFqRgLIpEemXwfLFUQ7Icw"> + <importedPackage xmi:type="uml:Model" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#_0"/> + </packageImport> + <packagedElement xmi:type="uml:Package" xmi:id="_dl4P8LIpEemXwfLFUQ7Icw" name="Associations"> + #foreach($association in $associationList) + <packagedElement xmi:type="uml:Association" xmi:id="$association.id" name="$association.name" memberEnd="$association.fromId $association.toId"> + <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="$association.randomId" source="org.eclipse.papyrus"> + <details xmi:type="ecore:EStringToStringMapEntry" xmi:id="$association.randomId" key="nature" value="UML_Nature"/> + </eAnnotations> + <ownedEnd xmi:type="uml:Property" xmi:id="$association.toId" name="$association.fromEntityName" type="$association.fromEntityId" association="$association.id"> + #if($association.multiplicity == "MANY2ONE" || $association.multiplicity == "MANY2MANY") + <lowerValue xmi:type="uml:LiteralInteger" xmi:id="$association.randomId"/> + <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="$association.randomId" value="*"/> + #else + <lowerValue xmi:type="uml:LiteralInteger" xmi:id="$association.randomId" value="1"/> + <upperValue xmi:type="uml:LiteralInteger" xmi:id="$association.randomId" value="1"/> + #end + </ownedEnd> + </packagedElement> + #end + </packagedElement> + <packagedElement xmi:type="uml:Package" xmi:id="_rBN-QLIqEemXwfLFUQ7Icw" name="ObjectClasses"> + #foreach($entity in $entityList) + <packagedElement xmi:type="uml:Class" xmi:id="$entity.id" name="$entity.name"> + #foreach($association in $entity.neighbours) + <ownedAttribute xmi:type="uml:Property" xmi:id="$association.fromId" name="$association.toEntityName" type="$association.toEntityId" #if( $association.isComposition) aggregation="composite" #end association="$association.id"> + #if($association.multiplicity == "ONE2MANY" || $association.multiplicity == "MANY2MANY") + <lowerValue xmi:type="uml:LiteralInteger" xmi:id="$association.randomId"/> + <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="$association.randomId" value="*"/> + #else + <lowerValue xmi:type="uml:LiteralInteger" xmi:id="$association.randomId" value="1"/> + <upperValue xmi:type="uml:LiteralInteger" xmi:id="$association.randomId" value="1"/> + #end + </ownedAttribute> + #end + #foreach($prop in $entity.properties) + <ownedAttribute xmi:type="uml:Property" xmi:id="$entity.randomId" name="$prop"/> + #end + </packagedElement> + #end + </packagedElement> +</uml:Model>
\ No newline at end of file |