summaryrefslogtreecommitdiffstats
path: root/vpp-integration/api-docs/core/src/main/java/io/fd/hc2vpp/docs/core/CoverageGenerator.java
diff options
context:
space:
mode:
Diffstat (limited to 'vpp-integration/api-docs/core/src/main/java/io/fd/hc2vpp/docs/core/CoverageGenerator.java')
-rw-r--r--vpp-integration/api-docs/core/src/main/java/io/fd/hc2vpp/docs/core/CoverageGenerator.java184
1 files changed, 184 insertions, 0 deletions
diff --git a/vpp-integration/api-docs/core/src/main/java/io/fd/hc2vpp/docs/core/CoverageGenerator.java b/vpp-integration/api-docs/core/src/main/java/io/fd/hc2vpp/docs/core/CoverageGenerator.java
new file mode 100644
index 000000000..4b6ab776c
--- /dev/null
+++ b/vpp-integration/api-docs/core/src/main/java/io/fd/hc2vpp/docs/core/CoverageGenerator.java
@@ -0,0 +1,184 @@
+/*
+ * 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.hc2vpp.docs.core;
+
+
+import static io.fd.hc2vpp.docs.api.Operation.CrudOperation.DELETE;
+import static io.fd.hc2vpp.docs.api.Operation.CrudOperation.UPDATE;
+import static io.fd.hc2vpp.docs.api.Operation.CrudOperation.WRITE;
+import static java.lang.String.format;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+import io.fd.hc2vpp.docs.api.CoverageUnit;
+import io.fd.hc2vpp.docs.api.JavaApiMessage;
+import io.fd.hc2vpp.docs.api.Operation;
+import io.fd.hc2vpp.docs.api.PluginCoverage;
+import io.fd.hc2vpp.docs.api.YangType;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.reflections.ReflectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CoverageGenerator implements VppApiUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CoverageGenerator.class);
+
+ private final CollectingWriterBuilder writerBuilder;
+
+ public CoverageGenerator() {
+ writerBuilder = new CollectingWriterBuilder();
+ }
+
+ public PluginCoverage generateConfigCoverage(final Class<?> pluginClass,
+ final String version,
+ final List<Module> scannedModules,
+ final YangTypeLinkIndex yangTypeIndex,
+ final ClassPathTypeIndex classPathIndex) {
+ LOG.info("Generating config coverage for plugin {}", pluginClass);
+ getInjectedWriterFactories(scannedModules).forEach(writerFactory -> writerFactory.init(writerBuilder));
+
+ LOG.info("Processing single node handlers");
+ final Set<CoverageUnit> singleNodeCoverageUnits = writerBuilder.getSingleNodeHandlers().stream()
+ .flatMap(writer -> {
+ // extracts customizer class from handler
+ final Class<?> customizerClass = getCustomizerClass(writer);
+
+ // scans within write method
+ final Set<PluginMethodReference> writeReferences =
+ new CoverageScanner(customizerClass, WRITE, pluginClass).scan();
+
+ // scans within update method
+ final Set<PluginMethodReference> updateReferences =
+ new CoverageScanner(customizerClass, UPDATE, pluginClass).scan();
+
+ // scans within delete method
+ final Set<PluginMethodReference> deleteReferences =
+ new CoverageScanner(customizerClass, DELETE, pluginClass).scan();
+
+ return Stream.of(writeReferences.stream(), updateReferences.stream(), deleteReferences.stream())
+ .flatMap(pluginMethodReferences -> pluginMethodReferences)
+ .map(reference -> {
+ final CoverageUnit.CoverageUnitBuilder builder = new CoverageUnit.CoverageUnitBuilder();
+
+ // binds vpp api name and generateLink bind with version
+ builder.setVppApi(fromJvppApi(version, reference));
+
+ //binds java api reference
+ builder.setJavaApi(new JavaApiMessage(reference.getName()));
+
+ //binds Yang types with links from pre-build index
+ // TODO - use deserialized yii
+ final String typeName = writer.getManagedDataObjectType().getTargetType().getTypeName();
+ builder.setYangTypes(Collections.singletonList(new YangType(
+ typeName,
+ yangTypeIndex.getLinkForType(typeName))));
+
+ final List<Operation> supportedOperations = new LinkedList<>();
+
+ final String callerClassLink = classPathIndex.linkForClass(reference.getCaller());
+ if (writeReferences.contains(reference)) {
+ supportedOperations.add(new Operation(callerClassLink, WRITE));
+ }
+
+ if (updateReferences.contains(reference)) {
+ supportedOperations.add(new Operation(callerClassLink, UPDATE));
+ }
+
+ if (deleteReferences.contains(reference)) {
+ supportedOperations.add(new Operation(callerClassLink, DELETE));
+ }
+ return builder.setSupportedOperations(supportedOperations).build();
+ });
+ }).collect(Collectors.toSet());
+
+ LOG.info("Processing multi node handlers");
+ final Set<CoverageUnit> multiNodeCoverageUnits = writerBuilder.getMultiNodeWriteHandlers().stream()
+ .flatMap(handler -> {
+ final Class<?> customizerClass = getCustomizerClass(handler.getWriter());
+ final Set<PluginMethodReference> writeReferences =
+ new CoverageScanner(customizerClass, WRITE, pluginClass).scan();
+
+ final Set<PluginMethodReference> updateReferences =
+ new CoverageScanner(customizerClass, UPDATE, pluginClass).scan();
+
+ final Set<PluginMethodReference> deleteReferences =
+ new CoverageScanner(customizerClass, DELETE, pluginClass).scan();
+
+ return Stream.of(writeReferences.stream(), updateReferences.stream(), deleteReferences.stream())
+ .flatMap(pluginMethodReferenceStream -> pluginMethodReferenceStream)
+ .map(reference -> {
+ final CoverageUnit.CoverageUnitBuilder builder = new CoverageUnit.CoverageUnitBuilder();
+ builder.setVppApi(fromJvppApi(version, reference));
+ builder.setJavaApi(new JavaApiMessage(reference.getName()));
+
+ builder.setYangTypes(handler.getHandledChildren().stream()
+ .map(type -> new YangType(type, yangTypeIndex.getLinkForType(type)))
+ .collect(Collectors.toList()));
+
+ final String callerClassLink = classPathIndex.linkForClass(reference.getCaller());
+ final List<Operation> supportedOperations = new LinkedList<>();
+ if (writeReferences.contains(reference)) {
+ supportedOperations.add(new Operation(callerClassLink, WRITE));
+ }
+
+ if (updateReferences.contains(reference)) {
+ supportedOperations.add(new Operation(callerClassLink, UPDATE));
+ }
+
+ if (deleteReferences.contains(reference)) {
+ supportedOperations.add(new Operation(callerClassLink, DELETE));
+ }
+ return builder.setSupportedOperations(supportedOperations).build();
+ });
+ }).collect(Collectors.toSet());
+
+ return new PluginCoverage(pluginClass.getSimpleName(),
+ Stream.of(singleNodeCoverageUnits.stream(), multiNodeCoverageUnits.stream())
+ .flatMap(coverageUnitStream -> coverageUnitStream)
+ .collect(Collectors.toSet()), true);
+ }
+
+ private static Class<?> getCustomizerClass(final Object handler) {
+ try {
+ final Set<Field> customizerFields =
+ ReflectionUtils.getAllFields(handler.getClass(), field -> "customizer".equals(field.getName()));
+ final Field customizerField = customizerFields.iterator().next();
+ customizerField.setAccessible(true);
+ return customizerField.get(handler).getClass();
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(format("Unable to get customizer from %s ", handler), e);
+ }
+ }
+
+ private static Set<WriterFactory> getInjectedWriterFactories(final List<Module> scannedModules) {
+ Injector injector = Guice.createInjector(scannedModules);
+ TypeLiteral<Set<WriterFactory>> writerFactoryType = new TypeLiteral<Set<WriterFactory>>() {
+ };
+ return injector.getInstance(Key.get(writerFactoryType));
+ }
+}