summaryrefslogtreecommitdiffstats
path: root/infra/translate-utils
diff options
context:
space:
mode:
Diffstat (limited to 'infra/translate-utils')
-rw-r--r--infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/AbstractSubtreeManagerRegistryBuilderBuilder.java63
-rw-r--r--infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/YangDAG.java69
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/YangDAGTest.java70
3 files changed, 159 insertions, 43 deletions
diff --git a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/AbstractSubtreeManagerRegistryBuilderBuilder.java b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/AbstractSubtreeManagerRegistryBuilderBuilder.java
index 6a19ed220..fe2f1178f 100644
--- a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/AbstractSubtreeManagerRegistryBuilderBuilder.java
+++ b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/AbstractSubtreeManagerRegistryBuilderBuilder.java
@@ -18,7 +18,6 @@ package io.fd.honeycomb.translate.util;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Sets;
import io.fd.honeycomb.translate.ModifiableSubtreeManagerRegistryBuilder;
import io.fd.honeycomb.translate.SubtreeManager;
import io.fd.honeycomb.translate.SubtreeManagerRegistryBuilder;
@@ -27,17 +26,18 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
-import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends SubtreeManager<? extends DataObject>, R>
- implements ModifiableSubtreeManagerRegistryBuilder<S>, SubtreeManagerRegistryBuilder<R>, AutoCloseable {
+ implements ModifiableSubtreeManagerRegistryBuilder<S>, SubtreeManagerRegistryBuilder<R> {
- // Using directed acyclic graph to represent the ordering relationships between writers
- private final DirectedAcyclicGraph<InstanceIdentifier<?>, Order>
- handlersRelations = new DirectedAcyclicGraph<>((sourceVertex, targetVertex) -> new Order());
private final Map<InstanceIdentifier<?>, S> handlersMap = new HashMap<>();
+ private final YangDAG dag;
+
+ protected AbstractSubtreeManagerRegistryBuilderBuilder(@Nonnull final YangDAG yangDAG) {
+ this.dag = Preconditions.checkNotNull(yangDAG, "yangDAG should not be null");
+ }
/**
* Add handler without any special relationship to any other type.
@@ -49,7 +49,7 @@ public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends Sub
// not be matched to writers in registry
final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
checkWriterNotPresentYet(targetType);
- handlersRelations.addVertex(targetType);
+ dag.addVertex(targetType);
handlersMap.put(targetType, handler);
return this;
}
@@ -78,9 +78,9 @@ public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends Sub
final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
final InstanceIdentifier<?> wildcardedRelatedType = RWUtils.makeIidWildcarded(relatedType);
checkWriterNotPresentYet(targetType);
- handlersRelations.addVertex(targetType);
- handlersRelations.addVertex(wildcardedRelatedType);
- addEdge(targetType, wildcardedRelatedType);
+ dag.addVertex(targetType);
+ dag.addVertex(wildcardedRelatedType);
+ dag.addEdge(targetType, wildcardedRelatedType);
handlersMap.put(targetType, handler);
return this;
}
@@ -90,13 +90,13 @@ public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends Sub
@Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
checkWriterNotPresentYet(targetType);
- handlersRelations.addVertex(targetType);
+ dag.addVertex(targetType);
relatedTypes.stream()
.map(RWUtils::makeIidWildcarded)
- .forEach(handlersRelations::addVertex);
+ .forEach(dag::addVertex);
relatedTypes.stream()
.map(RWUtils::makeIidWildcarded)
- .forEach(type -> addEdge(targetType, type));
+ .forEach(type -> dag.addEdge(targetType, type));
handlersMap.put(targetType, handler);
return this;
}
@@ -129,10 +129,10 @@ public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends Sub
final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
final InstanceIdentifier<?> wildcardedRelatedType = RWUtils.makeIidWildcarded(relatedType);
checkWriterNotPresentYet(targetType);
- handlersRelations.addVertex(targetType);
- handlersRelations.addVertex(wildcardedRelatedType);
+ dag.addVertex(targetType);
+ dag.addVertex(wildcardedRelatedType);
// set edge to indicate before relationship, just reversed
- addEdge(wildcardedRelatedType, targetType);
+ dag.addEdge(wildcardedRelatedType, targetType);
handlersMap.put(targetType, handler);
return this;
}
@@ -142,14 +142,14 @@ public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends Sub
@Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
checkWriterNotPresentYet(targetType);
- handlersRelations.addVertex(targetType);
+ dag.addVertex(targetType);
relatedTypes.stream()
.map(RWUtils::makeIidWildcarded)
- .forEach(handlersRelations::addVertex);
+ .forEach(dag::addVertex);
// set edge to indicate before relationship, just reversed
relatedTypes.stream()
.map(RWUtils::makeIidWildcarded)
- .forEach(type -> addEdge(type, targetType));
+ .forEach(type -> dag.addEdge(type, targetType));
handlersMap.put(targetType, handler);
return this;
}
@@ -170,22 +170,10 @@ public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends Sub
return addAfter(getSubtreeHandler(handledChildren, handler), relatedTypes);
}
-
- private void addEdge(final InstanceIdentifier<?> targetType,
- final InstanceIdentifier<?> relatedType) {
- try {
- handlersRelations.addDagEdge(targetType, relatedType);
- } catch (DirectedAcyclicGraph.CycleFoundException e) {
- throw new IllegalArgumentException(String.format(
- "Unable to add writer with relation: %s -> %s. Loop detected", targetType, relatedType), e);
- }
- }
-
protected ImmutableMap<InstanceIdentifier<?>, S> getMappedHandlers() {
final ImmutableMap.Builder<InstanceIdentifier<?>, S> builder = ImmutableMap.builder();
// Iterate writer types according to their relationships from graph
- handlersRelations.iterator()
- .forEachRemaining(handlerType -> {
+ dag.iterator().forEachRemaining(handlerType -> {
// There might be types stored just for relationship sake, no real writer, ignoring those
if (handlersMap.containsKey(handlerType)) {
builder.put(handlerType, handlersMap.get(handlerType));
@@ -199,15 +187,4 @@ public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends Sub
return builder.build();
}
-
- @Override
- public void close() throws Exception {
- handlersMap.clear();
- // Wrap sets into another set to avoid concurrent modification ex in graph
- handlersRelations.removeAllEdges(Sets.newHashSet(handlersRelations.edgeSet()));
- handlersRelations.removeAllVertices(Sets.newHashSet(handlersRelations.vertexSet()));
- }
-
- // Represents edges in graph
- private class Order {}
}
diff --git a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/YangDAG.java b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/YangDAG.java
new file mode 100644
index 000000000..2269adbff
--- /dev/null
+++ b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/YangDAG.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * 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.
+ */
+
+package io.fd.honeycomb.translate.util;
+
+import java.util.Iterator;
+import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Directed acyclic graph representing ordering relationships between schema nodes represented as wildcarded
+ * InstanceIdentifiers. Maintains topological order of vertices. Feature is used by translation layer if more nodes are
+ * affected in single read/write transaction.
+ */
+public final class YangDAG {
+
+ private final DirectedAcyclicGraph<InstanceIdentifier<?>, Edge>
+ dag = new DirectedAcyclicGraph<>((sourceVertex, targetVertex) -> new Edge());
+
+ /**
+ * Adds the vertex if it wasn't already in the graph.
+ *
+ * @param vertex vertex to be added
+ */
+ public void addVertex(final InstanceIdentifier<?> vertex) {
+ dag.addVertex(vertex);
+ }
+
+ /**
+ * Adds edge between source and target vertices.
+ *
+ * @param source source vertex of the edge
+ * @param target target vertex of the edge
+ * @throws IllegalArgumentException if the edge would induce a cycle in the graph
+ */
+ public void addEdge(final InstanceIdentifier<?> source, final InstanceIdentifier<?> target) {
+ try {
+ dag.addDagEdge(source, target);
+ } catch (DirectedAcyclicGraph.CycleFoundException e) {
+ throw new IllegalArgumentException(String.format(
+ "Unable to add writer with relation: %s -> %s. Loop detected", source, target), e);
+ }
+ }
+
+ /**
+ * Traverses schema nodes in topological order.
+ *
+ * @return an iterator that will traverse the graph in topological order.
+ */
+ public Iterator<InstanceIdentifier<?>> iterator() {
+ return dag.iterator();
+ }
+
+ private static final class Edge {
+ }
+}
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/YangDAGTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/YangDAGTest.java
new file mode 100644
index 000000000..1c8fb5442
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/translate/util/YangDAGTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * 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.
+ */
+
+package io.fd.honeycomb.translate.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Iterator;
+import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class YangDAGTest {
+
+ private static final InstanceIdentifier<DataObjects.DataObject1> VERTEX_A = DataObjects.DataObject1.IID;
+ private static final InstanceIdentifier<DataObjects.DataObject2> VERTEX_B = DataObjects.DataObject2.IID;
+
+ private YangDAG dag;
+
+ @Before
+ public void setUp() {
+ dag = new YangDAG();
+ }
+ @Test
+ public void testAddVertex() {
+ dag.addVertex(VERTEX_A);
+ final Iterator<InstanceIdentifier<?>> it = dag.iterator();
+ assertEquals(VERTEX_A, it.next());
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testAddEdge() {
+ dag.addVertex(VERTEX_A);
+ dag.addVertex(VERTEX_B);
+ dag.addEdge(VERTEX_A, VERTEX_B);
+ final Iterator<InstanceIdentifier<?>> it = dag.iterator();
+ assertEquals(VERTEX_A, it.next());
+ assertEquals(VERTEX_B, it.next());
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testAddCycleFails() {
+ dag.addVertex(VERTEX_A);
+ dag.addVertex(VERTEX_B);
+ dag.addEdge(VERTEX_A, VERTEX_B);
+ try {
+ dag.addEdge(VERTEX_B, VERTEX_A);
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getCause() instanceof DirectedAcyclicGraph.CycleFoundException);
+ }
+ }
+} \ No newline at end of file