package org.jboss.forge.addon.thorntail.ui; import org.jboss.forge.addon.dependencies.Dependency; import org.jboss.forge.addon.dependencies.builder.DependencyBuilder; import org.jboss.forge.addon.facets.constraints.FacetConstraint; import org.jboss.forge.addon.parser.java.converters.PackageRootConverter; import org.jboss.forge.addon.parser.java.facets.JavaSourceFacet; import org.jboss.forge.addon.projects.Project; import org.jboss.forge.addon.projects.facets.DependencyFacet; import org.jboss.forge.addon.thorntail.config.ThorntailConfiguration; import org.jboss.forge.addon.thorntail.facet.ThorntailFacet; import org.jboss.forge.addon.ui.context.UIBuilder; import org.jboss.forge.addon.ui.context.UIContext; import org.jboss.forge.addon.ui.context.UIExecutionContext; import org.jboss.forge.addon.ui.facets.HintsFacet; import org.jboss.forge.addon.ui.hints.InputType; import org.jboss.forge.addon.ui.input.InputComponentFactory; import org.jboss.forge.addon.ui.input.UIInput; import org.jboss.forge.addon.ui.input.UISelectOne; import org.jboss.forge.addon.ui.metadata.UICommandMetadata; import org.jboss.forge.addon.ui.result.Result; import org.jboss.forge.addon.ui.result.Results; import org.jboss.forge.addon.ui.util.Categories; import org.jboss.forge.addon.ui.util.Metadata; import org.jboss.forge.roaster.Roaster; import org.jboss.forge.roaster.model.source.AnnotationSource; import org.jboss.forge.roaster.model.source.FieldSource; import org.jboss.forge.roaster.model.source.JavaClassSource; import org.jboss.forge.roaster.model.source.MethodSource; import org.jboss.forge.roaster.model.util.Types; import java.io.IOException; import java.net.URL; import java.util.Arrays; import java.util.List; /** * Creates a sample Arquillian Test. * It adds Arquillian dependency as well. * * @author <a href="mailto:[email protected]">Alex Soto</a> */ @FacetConstraint(ThorntailFacet.class) public class CreateTestClassCommand extends AbstractThorntailCommand { public static final Dependency SWARM_ARQUILLIAN_DEPENDENCY = DependencyBuilder .create().setGroupId("io.thorntail") .setArtifactId("arquillian") .setScopeType("test"); public static final List<String> ARCHIVE_TYPES = Arrays.asList("JAR", "WAR"); // Mandatory fields private UIInput<String> targetPackage; private UIInput<String> named; // Optional fields private UIInput<Boolean> asClient; private UISelectOne<String> archiveType; @Override public boolean isEnabled(UIContext context) { boolean result = super.isEnabled(context); return result; } @Override public UICommandMetadata getMetadata(UIContext context) { return Metadata.from(super.getMetadata(context), getClass()).name("Thorntail: New Test") .description("Create new Arquillian test for WildFly Swarm") .category(Categories.create("Thorntail")); } @Override public void initializeUI(UIBuilder builder) throws Exception { InputComponentFactory inputFactory = builder.getInputComponentFactory(); targetPackage = inputFactory.createInput("targetPackage", String.class) .setLabel("Package Name") .setRequired(true) .setDescription("The package name where this type will be created"); targetPackage.getFacet(HintsFacet.class).setInputType(InputType.JAVA_PACKAGE_PICKER); targetPackage.setValueConverter(new PackageRootConverter(getProjectFactory(), builder)); targetPackage.setDefaultValue(calculateDefaultPackage(builder.getUIContext())); named = inputFactory.createInput("named", String.class) .setLabel("Type Name").setRequired(true) .setDescription("The type name"); named.addValidator((context) -> { if (!Types.isSimpleName(named.getValue())) context.addValidationError(named, "Invalid java type name."); }); asClient = inputFactory.createInput(ThorntailConfiguration.TEST_AS_CLIENT_FLAG_CONFIGURATION_ELEMENT, Boolean.class) .setLabel("As Client").setDescription("Sets test mode to as client."); archiveType = inputFactory.createSelectOne(ThorntailConfiguration.TEST_TYPE_CONFIGURATION_ELEMENT, String.class) .setLabel("Archive Type") .setDescription("Sets type of default archive") .setValueChoices(ARCHIVE_TYPES); builder.add(targetPackage) .add(named) .add(asClient) .add(archiveType); } protected String calculateDefaultPackage(UIContext context) { String packageName; Project project = getSelectedProject(context); if (project != null) { packageName = project.getFacet(JavaSourceFacet.class).getBasePackage(); } else { packageName = ""; } return packageName; } @Override public Result execute(UIExecutionContext context) throws Exception { Project project = getSelectedProject(context); final DependencyFacet dependencyFacet = project.getFacet(DependencyFacet.class); if (!isArquillianWildflySwarmDependencyInstalled(dependencyFacet)) { installArquillianWildflySwarmDependency(dependencyFacet); } JavaClassSource test = Roaster.create(JavaClassSource.class) .setPackage(targetPackage.getValue()) .setName(named.getValue()); addArquillianRunner(test); addDefaultDeploymentAnnotation(test, project); addArquillianResourceEnricher(test); addTestMethod(test); JavaSourceFacet facet = project.getFacet(JavaSourceFacet.class); facet.saveTestJavaSource(test); return Results.success(String.format("Test Class %s.%s was created", targetPackage.getValue(), named.getValue())); } private void addArquillianResourceEnricher(JavaClassSource test) { if (asClient.hasValue()) { test.addImport("org.jboss.arquillian.test.api.ArquillianResource"); final FieldSource<JavaClassSource> urlField = test.addField(); urlField .setName("url") .setType(URL.class) .setPrivate(); urlField.addAnnotation("ArquillianResource"); } } private void addTestMethod(JavaClassSource test) { test.addImport("org.junit.Test"); MethodSource<JavaClassSource> testMethod = test.addMethod() .setPublic() .setReturnTypeVoid() .setName("should_start_service") .setBody(""); testMethod.addAnnotation("Test"); } private void addArquillianRunner(JavaClassSource test) { test.addImport("org.junit.runner.RunWith"); test.addImport("org.jboss.arquillian.junit.Arquillian"); test.addAnnotation("RunWith").setLiteralValue("Arquillian.class"); } private void addDefaultDeploymentAnnotation(JavaClassSource test, Project project) throws ClassNotFoundException, IOException { test.addImport("org.wildfly.swarm.arquillian.DefaultDeployment"); final AnnotationSource<JavaClassSource> defaultDeploymentAnnotation = test.addAnnotation("DefaultDeployment"); if (asClient.hasValue()) { defaultDeploymentAnnotation.setLiteralValue("testable", "false"); } if (archiveType.hasValue()) { defaultDeploymentAnnotation.setLiteralValue("type", String.format("DefaultDeployment.Type.%s", archiveType.getValue())); } } private void installArquillianWildflySwarmDependency(DependencyFacet dependencyFacet) { dependencyFacet.addDirectDependency(SWARM_ARQUILLIAN_DEPENDENCY); } private boolean isArquillianWildflySwarmDependencyInstalled(DependencyFacet dependencyFacet) { return dependencyFacet.getDependencies().stream() .map(dependency -> dependency.getCoordinate()) .anyMatch(coordinate -> "io.thorntail".equals(coordinate.getGroupId()) && "arquillian".equals(coordinate.getArtifactId())); } }