/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.module.extension.internal.capability.xml.description;
import static com.google.common.truth.Truth.assert_;
import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
import static java.lang.Thread.currentThread;
import static java.util.Collections.emptySet;
import static javax.lang.model.SourceVersion.RELEASE_8;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.mule.runtime.api.dsl.DslResolvingContext.getDefault;
import static org.mule.runtime.module.extension.internal.resources.ExtensionResourcesGeneratorAnnotationProcessor.EXTENSION_VERSION;
import static org.mule.test.module.extension.internal.util.ExtensionsTestUtils.compareXML;
import org.mule.runtime.api.meta.DescribedObject;
import org.mule.runtime.api.meta.model.ExtensionModel;
import org.mule.runtime.api.meta.model.config.ConfigurationModel;
import org.mule.runtime.api.meta.model.declaration.fluent.ExtensionDeclaration;
import org.mule.runtime.api.meta.model.operation.OperationModel;
import org.mule.runtime.api.meta.model.parameter.ParameterModel;
import org.mule.runtime.core.util.IOUtils;
import org.mule.runtime.extension.api.annotation.Extension;
import org.mule.runtime.extension.api.loader.ExtensionLoadingContext;
import org.mule.runtime.extension.api.resources.GeneratedResource;
import org.mule.runtime.extension.internal.loader.DefaultExtensionLoadingContext;
import org.mule.runtime.extension.internal.loader.ExtensionModelFactory;
import org.mule.runtime.module.extension.internal.AbstractAnnotationProcessorTestCase;
import org.mule.runtime.module.extension.internal.capability.xml.TestExtensionWithDocumentation;
import org.mule.runtime.module.extension.internal.loader.enricher.ExtensionDescriptionsEnricher;
import org.mule.runtime.module.extension.internal.loader.java.DefaultJavaModelLoaderDelegate;
import org.mule.runtime.module.extension.internal.resources.documentation.ExtensionDocumentationResourceGenerator;
import org.mule.tck.size.SmallTest;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import org.junit.Test;
@SmallTest
public class ExtensionDescriptionDocumenterTestCase extends AbstractAnnotationProcessorTestCase {
@Test
public void persistDocumentation() throws Exception {
InputStream in = getClass().getResourceAsStream("/META-INF/documentation-extension-descriptions.xml");
assertThat(in, is(notNullValue()));
String expectedXml = IOUtils.toString(in);
TestProcessor processor = new TestProcessor();
doCompile(processor);
ExtensionDocumentationResourceGenerator generator = new ExtensionDocumentationResourceGenerator();
GeneratedResource resource = generator.generateResource(processor.getExtensionModel())
.orElseThrow(() -> new RuntimeException("No Documentation Generated"));
compareXML(expectedXml, new String(resource.getContent()));
}
@Test
public void loadDocumentationFromFile() throws Exception {
ExtensionLoadingContext ctx = new DefaultExtensionLoadingContext(currentThread().getContextClassLoader(),
getDefault(emptySet()));
DefaultJavaModelLoaderDelegate loader = new DefaultJavaModelLoaderDelegate(TestExtensionWithDocumentation.class, "1.0.0-dev");
loader.declare(ctx);
ExtensionDescriptionsEnricher enricher = new ExtensionDescriptionsEnricher();
enricher.enrich(ctx);
ExtensionModelFactory factory = new ExtensionModelFactory();
ExtensionModel extensionModel = factory.create(ctx);
assertDescriptions(extensionModel);
}
@Test
public void describeDescriptions() throws Exception {
TestProcessor processor = new TestProcessor();
doCompile(processor);
assertDescriptions(processor.getExtensionModel());
}
private void assertDescriptions(ExtensionModel declaration) {
assertDescription(declaration, "Test Extension Description");
List<ConfigurationModel> configurations = declaration.getConfigurationModels();
assertThat(configurations, hasSize(2));
ConfigurationModel first = configurations.get(1);
assertDescription(first, "This is some Config documentation.");
assertDescription(first.getConnectionProviders().get(0), "Another Provider Documentation");
assertDescription(first.getConnectionProviders().get(1), "Provider Documentation");
ConfigurationModel second = configurations.get(0);
assertDescription(second, "This is some Another Config documentation.");
assertDescription(second.getConnectionProviders().get(0), "Another Provider Documentation");
List<ParameterModel> params = first.getAllParameterModels();
assertDescription(params.get(0), "Config parameter");
assertDescription(params.get(1), "Config Parameter with an Optional value");
assertDescription(params.get(2), "Group parameter 1");
assertDescription(params.get(3), "Group parameter 2");
List<OperationModel> operations = declaration.getOperationModels();
OperationModel operation = getOperationByName(operations, "operation");
assertDescription(operation, "Test Operation");
assertDescription(operation.getAllParameterModels().get(0), "test value");
OperationModel inheritedOperation = getOperationByName(operations, "inheritedOperation");
assertDescription(inheritedOperation, "Inherited Operation Documentation");
assertDescription(inheritedOperation.getAllParameterModels().get(0), "parameter documentation for an inherited operation.");
OperationModel greetFriend = getOperationByName(operations, "greetFriend");
assertDescription(greetFriend, "This method greets a friend");
assertDescription(greetFriend.getAllParameterModels().get(0), "This is one of my friends");
assertDescription(greetFriend.getAllParameterModels().get(1), "Some other friend");
List<OperationModel> connectedOperations = first.getOperationModels();
OperationModel connectedOpe = connectedOperations.get(0);
assertDescription(connectedOpe, "Test Operation with blank parameter description");
assertDescription(connectedOpe.getAllParameterModels().get(0), "");
}
private void doCompile(TestProcessor processor) throws Exception {
assert_().about(javaSources()).that(testSourceFiles()).withCompilerOptions("-Aextension.version=1.0.0-dev")
.processedWith(processor).compilesWithoutError();
}
@SupportedAnnotationTypes(value = {"org.mule.runtime.extension.api.annotation.Extension"})
@SupportedSourceVersion(RELEASE_8)
@SupportedOptions(EXTENSION_VERSION)
private class TestProcessor extends AbstractProcessor {
private ExtensionDeclaration declaration;
private DefaultExtensionLoadingContext ctx;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (declaration == null) {
ExtensionDescriptionDocumenter declarer = new ExtensionDescriptionDocumenter(processingEnv, roundEnv);
Set<? extends Element> extensionElements = roundEnv.getElementsAnnotatedWith(Extension.class);
assertThat(extensionElements, hasSize(1));
Element extension = extensionElements.iterator().next();
assertThat(extension, instanceOf(TypeElement.class));
ctx = new DefaultExtensionLoadingContext(currentThread().getContextClassLoader(), getDefault(emptySet()));
DefaultJavaModelLoaderDelegate loader = new DefaultJavaModelLoaderDelegate(TestExtensionWithDocumentation.class,
"1.0.0-dev");
declaration = loader.declare(ctx).getDeclaration();
declarer.document(declaration, (TypeElement) extension);
}
return false;
}
ExtensionModel getExtensionModel() {
ExtensionModelFactory factory = new ExtensionModelFactory();
return factory.create(ctx);
}
}
private void assertDescription(DescribedObject object, String desc) {
assertThat(object.getDescription(), is(desc));
}
private OperationModel getOperationByName(List<OperationModel> ops, String opeName) {
return ops.stream().filter(operationModel -> operationModel.getName().equals(opeName)).findAny().orElse(null);
}
}