aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/org/onap/aai/migration/EdgeMigrator.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/onap/aai/migration/EdgeMigrator.java')
-rw-r--r--src/main/java/org/onap/aai/migration/EdgeMigrator.java319
1 files changed, 218 insertions, 101 deletions
diff --git a/src/main/java/org/onap/aai/migration/EdgeMigrator.java b/src/main/java/org/onap/aai/migration/EdgeMigrator.java
index 99b4896..bb8acfc 100644
--- a/src/main/java/org/onap/aai/migration/EdgeMigrator.java
+++ b/src/main/java/org/onap/aai/migration/EdgeMigrator.java
@@ -17,26 +17,38 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
-package org.onap.aai.migration;
-import java.util.List;
+package org.onap.aai.migration;
import com.google.common.collect.Multimap;
-import org.javatuples.Pair;
-import org.apache.tinkerpop.gremlin.structure.Edge;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.javatuples.Pair;
import org.onap.aai.db.props.AAIProperties;
import org.onap.aai.edges.EdgeIngestor;
+import org.onap.aai.edges.EdgeRule;
import org.onap.aai.edges.EdgeRuleQuery;
+import org.onap.aai.edges.enums.EdgeType;
+import org.onap.aai.exceptions.AAIException;
import org.onap.aai.introspection.LoaderFactory;
import org.onap.aai.serialization.db.EdgeSerializer;
+import org.onap.aai.serialization.db.exceptions.EdgeMultiplicityException;
import org.onap.aai.serialization.engines.TransactionalGraphEngine;
-import org.onap.aai.edges.EdgeRule;
import org.onap.aai.setup.SchemaVersions;
+
/**
* A migration template for migrating all edge properties between "from" and "to" node from the DbedgeRules.json
*
@@ -45,101 +57,206 @@ import org.onap.aai.setup.SchemaVersions;
@MigrationDangerRating(1)
public abstract class EdgeMigrator extends Migrator {
- private boolean success = true;
-
- public EdgeMigrator(TransactionalGraphEngine engine, LoaderFactory loaderFactory, EdgeIngestor edgeIngestor, EdgeSerializer edgeSerializer, SchemaVersions schemaVersions) {
- super(engine, loaderFactory, edgeIngestor, edgeSerializer, schemaVersions);
- }
-
- public EdgeMigrator(TransactionalGraphEngine engine, LoaderFactory loaderFactory, EdgeIngestor edgeIngestor, EdgeSerializer edgeSerializer, SchemaVersions schemaVersions, List<Pair<String, String>> nodePairList) {
- super(engine, loaderFactory, edgeIngestor, edgeSerializer, schemaVersions);
- }
-
-
- /**
- * Do not override this method as an inheritor of this class
- */
- @Override
- public void run() {
-
- executeModifyOperation();
-
- }
-
- /**
- * This is where inheritors should add their logic
- */
- protected void executeModifyOperation() {
-
- changeEdgeProperties();
-
- }
-
- protected void changeEdgeLabels() {
- //TODO: when json file has edge label as well as edge property changes
- }
-
-
-
- protected void changeEdgeProperties() {
- try {
- List<Pair<String, String>> nodePairList = this.getAffectedNodePairTypes();
- for (Pair<String, String> nodePair : nodePairList) {
-
- String NODE_A = nodePair.getValue0();
- String NODE_B = nodePair.getValue1();
- Multimap<String, EdgeRule> result = edgeIngestor.getRules(new EdgeRuleQuery.Builder(NODE_A, NODE_B).build());
-
- GraphTraversal<Vertex, Vertex> g = this.engine.asAdmin().getTraversalSource().V();
- /*
- * Find Out-Edges from Node A to Node B and change them
- * Also Find Out-Edges from Node B to Node A and change them
- */
- g.union(__.has(AAIProperties.NODE_TYPE, NODE_A).outE().where(__.inV().has(AAIProperties.NODE_TYPE, NODE_B)),
- __.has(AAIProperties.NODE_TYPE, NODE_B).outE().where(__.inV().has(AAIProperties.NODE_TYPE, NODE_A)))
- .sideEffect(t -> {
- Edge e = t.get();
- try {
- Vertex out = e.outVertex();
- Vertex in = e.inVertex();
- if (out == null || in == null) {
- logger.error(
- e.id() + " invalid because one vertex was null: out=" + out + " in=" + in);
- } else {
- if (result.containsKey(e.label())) {
- EdgeRule rule = result.get(e.label()).iterator().next();
- e.properties().forEachRemaining(prop -> prop.remove());
- edgeSerializer.addProperties(e, rule);
- } else {
- logger.info("found vertices connected by unkwown label: out=" + out + " label="
- + e.label() + " in=" + in);
- }
- }
- } catch (Exception e1) {
- throw new RuntimeException(e1);
- }
- }).iterate();
- }
-
- } catch (Exception e) {
- logger.error("error encountered", e);
- success = false;
- }
- }
+ protected int processed = 0;
+ protected int skipped = 0;
+ protected Map<String, Integer> edgeMultiplicityExceptionCtr = new HashMap<>();
+ protected List<String> edgeMissingParentProperty = new ArrayList<>();
+
+ private boolean success = true;
+
+ public EdgeMigrator(TransactionalGraphEngine engine, LoaderFactory loaderFactory, EdgeIngestor edgeIngestor,
+ EdgeSerializer edgeSerializer, SchemaVersions schemaVersions) {
+ super(engine, loaderFactory, edgeIngestor, edgeSerializer, schemaVersions);
+ }
+
+ /**
+ * Do not override this method as an inheritor of this class.
+ */
+ @Override
+ public void run() {
+
+ executeModifyOperation();
+
+ }
+
+ /**
+ * This is where inheritors should add their logic.
+ */
+ protected void executeModifyOperation() {
+
+ changeEdgeProperties();
+
+ }
+
+ protected void changeEdgeLabels() {
+ //TODO: when json file has edge label as well as edge property changes
+ }
+
+
+
+ protected void changeEdgeProperties() {
+ try {
+ List<Pair<String, String>> nodePairList = this.getAffectedNodePairTypes();
+ for (Pair<String, String> nodePair : nodePairList) {
+
+ String NODE_A = nodePair.getValue0();
+ String NODE_B = nodePair.getValue1();
+ Multimap<String, EdgeRule> result = edgeIngestor.getRules(new EdgeRuleQuery.Builder(NODE_A, NODE_B).build());
+
+ GraphTraversal<Vertex, Vertex> g = this.engine.asAdmin().getTraversalSource().V();
+ /*
+ * Find Out-Edges from Node A to Node B and change them
+ * Also Find Out-Edges from Node B to Node A and change them
+ */
+ g.union(__.has(AAIProperties.NODE_TYPE, NODE_A).outE().where(__.inV().has(AAIProperties.NODE_TYPE, NODE_B)),
+ __.has(AAIProperties.NODE_TYPE, NODE_B).outE().where(__.inV().has(AAIProperties.NODE_TYPE, NODE_A)))
+ .sideEffect(t -> {
+ Edge e = t.get();
+ try {
+ Vertex out = e.outVertex();
+ Vertex in = e.inVertex();
+ if (out == null || in == null) {
+ logger.error(
+ e.id() + " invalid because one vertex was null: out=" + out + " in=" + in);
+ } else {
+ if (result.containsKey(e.label())) {
+ EdgeRule rule = result.get(e.label()).iterator().next();
+ e.properties().forEachRemaining(prop -> prop.remove());
+ edgeSerializer.addProperties(e, rule);
+ } else {
+ logger.info("found vertices connected by unkwown label: out=" + out + " label="
+ + e.label() + " in=" + in);
+ }
+ }
+ } catch (Exception e1) {
+ throw new RuntimeException(e1);
+ }
+ }).iterate();
+ }
+
+ } catch (Exception e) {
+ logger.error("error encountered", e);
+ success = false;
+ }
+ }
- @Override
- public Status getStatus() {
- if (success) {
- return Status.SUCCESS;
- } else {
- return Status.FAILURE;
- }
- }
-
- /**
- * List of node pairs("from" and "to"), you would like EdgeMigrator to migrate from json files
- * @return
- */
- public abstract List<Pair<String, String>> getAffectedNodePairTypes() ;
-
+ @Override
+ public Status getStatus() {
+ if (success) {
+ return Status.SUCCESS;
+ } else {
+ return Status.FAILURE;
+ }
+ }
+
+ /**
+ * List of node pairs("from" and "to"), you would like EdgeMigrator to migrate from json files.
+ * @return
+ */
+ public abstract List<Pair<String, String>> getAffectedNodePairTypes() ;
+
+ /**
+ * Takes the set of edges, and rebuild them according to current edgeRules schema.
+ * @param edges takes set of edges as input.
+ */
+ protected void rebuildEdges(Set<Edge> edges) {
+ Vertex out = null;
+ Vertex in = null;
+ String oldEdgeString = null;
+ edgeMultiplicityExceptionCtr = new HashMap<>();
+ edgeMissingParentProperty = new ArrayList<>();
+ GraphTraversalSource graphTraversalSource = engine.asAdmin().getTraversalSource();
+ try {
+ for (Edge edge : edges) {
+ oldEdgeString = toStringForPrinting(edge, 1);
+ out = edge.outVertex();
+ in = edge.inVertex();
+ rebuildEdge(edge, graphTraversalSource);
+ }
+ } catch (Exception ex) {
+ logger.error(MIGRATION_ERROR + "exception occurred during migration, failing: out=" + out + " in=" + in
+ + "edge=" + oldEdgeString, ex);
+ success = false;
+ }
+ }
+
+ private void rebuildEdge(Edge edge, GraphTraversalSource graphTraversalSource)
+ throws AAIException {
+ boolean isCousin = false;
+ Vertex out = edge.outVertex();
+ Vertex in = edge.inVertex();
+ if (out == null || in == null) {
+ logger.error(edge.id() + " invalid because one vertex was null: out="
+ + edge.outVertex() + " in=" + edge.inVertex());
+ skipped++;
+ return;
+ }
+
+ if (edge.property("contains-other-v").isPresent()) {
+ isCousin = "NONE".equals(edge.property("contains-other-v").value());
+ } else if (edge.property("isParent").isPresent()) {
+ isCousin = !(Boolean) edge.property("isParent").value();
+ } else {
+ edgeMissingParentProperty.add(this.toStringForPrinting(edge, 1));
+ }
+
+ String inVertexNodeType = in.value(AAIProperties.NODE_TYPE);
+ String outVertexNodeType = out.value(AAIProperties.NODE_TYPE);
+ String label = null;
+
+ try {
+ Collection<EdgeRule> edgeRules = edgeIngestor.getRules(new EdgeRuleQuery.Builder(inVertexNodeType,
+ outVertexNodeType).build()).values();
+ Set<String> edgeLabels = edgeRules.stream().map(EdgeRule::getLabel).collect(Collectors.toSet());
+ if (edgeLabels.size() > 1) {
+ label = selectLabel(edge, edgeLabels);
+ if (label == null) {
+ logger.warn("For Multiple EdgeRules between " + "out=" + outVertexNodeType + " in="
+ + inVertexNodeType + ": did not find label for edge :" + edge.id());
+ }
+ }
+ } catch (Exception e) {
+ logger.error(edge.id() + " did not migrate as no edge rule found for: out=" + outVertexNodeType
+ + " in=" + inVertexNodeType);
+ skipped++;
+ return;
+ }
+
+ try {
+ edge.remove();
+ if (isCousin) {
+ edgeSerializer.addEdgeIfPossible(graphTraversalSource, in, out, label);
+ } else {
+ edgeSerializer.addTreeEdge(graphTraversalSource, out, in);
+ }
+ processed++;
+ } catch (EdgeMultiplicityException edgeMultiplicityException) {
+ logger.warn("Edge Multiplicity Exception: "
+ + "\nInV:\n" + this.toStringForPrinting(in, 1)
+ + "Edge:\n" + this.toStringForPrinting(edge, 1)
+ + "OutV:\n" + this.toStringForPrinting(out, 1)
+ );
+
+ final String mapKey = "OUT:" + outVertexNodeType + " "
+ + (isCousin ? EdgeType.COUSIN.toString() : EdgeType.TREE.toString()) + " "
+ + "IN:" + inVertexNodeType;
+ if (edgeMultiplicityExceptionCtr.containsKey(mapKey)) {
+ edgeMultiplicityExceptionCtr.put(mapKey, edgeMultiplicityExceptionCtr.get(mapKey) + 1);
+ } else {
+ edgeMultiplicityExceptionCtr.put(mapKey, 1);
+ }
+ }
+ }
+
+ /**
+ * For selecting label from multiple EdgeLabels
+ * (where labels got changed between edgeRules' versions),
+ * you should override this method in inheritor class.
+ * @param edge Edge
+ * @param edgeLabels set of edgeLabels
+ * @return
+ */
+ protected String selectLabel(Edge edge, Set<String> edgeLabels) {
+ return null;
+ }
}