All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.powerunit.extensions.matchers.provideprocessor.ProvidesMatchersAnnotatedElementMirror Maven / Gradle / Ivy

Go to download

This is a test framework for the JDK 1.8 - Extension to provide matchers based on annotation. - Factory Support

There is a newer version: 0.1.6
Show newest version
/**
 * Powerunit - A JDK1.8 test framework
 * Copyright (C) 2014 Mathieu Boretti.
 *
 * This file is part of Powerunit
 *
 * Powerunit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Powerunit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Powerunit. If not, see .
 */
package ch.powerunit.extensions.matchers.provideprocessor;

import static ch.powerunit.extensions.matchers.common.CommonUtils.addPrefix;
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.toList;

import java.io.PrintWriter;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;

import ch.powerunit.extensions.matchers.common.CommonUtils;
import ch.powerunit.extensions.matchers.common.FileObjectHelper;
import ch.powerunit.extensions.matchers.provideprocessor.fields.AbstractFieldDescription;
import ch.powerunit.extensions.matchers.provideprocessor.xml.GeneratedMatcher;

public class ProvidesMatchersAnnotatedElementMirror extends ProvidesMatchersAnnotatedElementMatcherMirror {

	private final Collection> dslProvider;

	public ProvidesMatchersAnnotatedElementMirror(TypeElement typeElement, RoundMirror roundMirror) {
		super(typeElement, roundMirror);
		boolean hasParentInSameRound = roundMirror.isInSameRound(typeElement);
		List> tmp = new ArrayList<>(
				Arrays.asList(this::generateDefaultDSLStarter, this::generateDefaultForChainingDSLStarter));
		if (fullyQualifiedNameOfSuperClassOfClassAnnotatedWithProvideMatcher.isPresent()) {
			tmp.add(this::generateParentDSLStarter);
			if (hasParentInSameRound) {
				tmp.add(this::generateParentValueDSLStarter);
				if (((TypeElement) roundMirror.getProcessingEnv().getTypeUtils()
						.asElement(typeElementForClassAnnotatedWithProvideMatcher.getSuperclass())).getTypeParameters()
								.isEmpty()) {
					tmp.add(this::generateParentInSameRoundWithChaningDSLStarter);
				}
			}
		} else {
			tmp.add(this::generateNoParentValueDSLStarter);
		}
		tmp.addAll(Optional.ofNullable(getDSLExtension()).orElseGet(Collections::emptyList).stream()
				.map(t -> t.getDSLMethodFor(() -> this)).flatMap(Collection::stream).collect(toList()));
		tmp.addAll(roundMirror.getDSLMethodFor(() -> this));
		this.dslProvider = unmodifiableList(tmp);
	}

	public Collection process() {
		RoundMirror rm = roundMirror;
		Element te = typeElementForClassAnnotatedWithProvideMatcher;
		Collection results = new ArrayList<>();
		FileObjectHelper.processFileWithIOException(
				() -> rm.getProcessingEnv().getFiler().createSourceFile(getFullyQualifiedNameOfGeneratedClass(), te),
				jfo -> new PrintWriter(jfo.openWriter()), wjfo -> {
					wjfo.println("package " + getPackageNameOfGeneratedClass() + ";");
					wjfo.println();
					wjfo.println(generateMainJavaDoc());
					wjfo.println("@javax.annotation.Generated(value=\""
							+ ProvidesMatchersAnnotationsProcessor.class.getName() + "\",date=\""
							+ Instant.now().toString() + "\",comments=" + CommonUtils.toJavaSyntax(getComments())
							+ ")");
					wjfo.println("public final class " + getSimpleNameOfGeneratedClass() + " {");
					wjfo.println();
					wjfo.println("  private " + getSimpleNameOfGeneratedClass() + "() {}");
					wjfo.println();
					wjfo.println(generateMatchers());
					wjfo.println();
					wjfo.println(generatePublicInterface());
					wjfo.println();
					wjfo.println(generatePrivateImplementation());
					wjfo.println();
					Collection tmp = generateDSLStarter();
					tmp.stream().map(m -> addPrefix("  ", m.asStaticImplementation())).forEach(wjfo::println);
					wjfo.println("}");
					results.addAll(tmp);
				} , e -> rm.getProcessingEnv().getMessager().printMessage(Kind.ERROR,
						"Unable to create the file containing the target class because of " + e, te));
		return results;
	}

	public String generateMainJavaDoc() {
		return String.format(
				"/**\n* This class provides matchers for the class {@link %1$s}.\n * \n * @see %1$s The class for which matchers are provided.\n */\n",
				fullyQualifiedNameOfClassAnnotatedWithProvideMatcher);
	}

	public Collection generateDSLStarter() {
		return dslProvider.stream().map(Supplier::get).collect(toList());
	}

	public String getDefaultStarterBody(boolean withParentBuilder) {
		String targetImpl = withParentBuilder ? getSimpleNameOfGeneratedImplementationMatcherWithGenericParent()
				: getSimpleNameOfGeneratedImplementationMatcherWithGenericNoParent();
		boolean withSuper = fullyQualifiedNameOfSuperClassOfClassAnnotatedWithProvideMatcher.isPresent();
		if (withParentBuilder) {
			return withSuper ? ("return new " + targetImpl + "(org.hamcrest.Matchers.anything(),parentBuilder);")
					: ("return new " + targetImpl + "(parentBuilder);");
		} else {
			return withSuper ? ("return new " + targetImpl + "(org.hamcrest.Matchers.anything());")
					: ("return new " + targetImpl + "();");
		}
	}

	public DSLMethod generateDefaultDSLStarter() {
		return new DSLMethod(
				generateDefaultJavaDoc(
						Optional.of(
								"The returned builder (which is also a Matcher), at this point accepts any object that is a "
										+ getDefaultLinkForAnnotatedClass() + "."),
						Optional.empty(), Optional.of("the DSL matcher"), true, false),
				fullGeneric + " " + getFullyQualifiedNameOfGeneratedClass() + "."
						+ getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent() + " " + methodShortClassName
						+ "With",
				getDefaultStarterBody(false));
	}

	public DSLMethod generateDefaultForChainingDSLStarter() {
		return new DSLMethod(
				generateDefaultJavaDoc(
						Optional.of(
								"The returned builder (which is also a Matcher), at this point accepts any object that is a "
										+ getDefaultLinkForAnnotatedClass() + "."),
						Optional.of("parentBuilder the parentBuilder."), Optional.of("the DSL matcher"), true, true),
				getFullGenericParent() + " " + getFullyQualifiedNameOfGeneratedClass() + "."
						+ getSimpleNameOfGeneratedInterfaceMatcherWithGenericParent() + " " + methodShortClassName
						+ "WithParent",
				new String[] { "_PARENT", "parentBuilder" }, getDefaultStarterBody(true));
	}

	public DSLMethod generateParentDSLStarter() {
		String mscn = methodShortClassName;
		String fqngc = getFullyQualifiedNameOfGeneratedClass();
		return new DSLMethod(
				generateDefaultJavaDoc(Optional.empty(), Optional.of("matcherOnParent the matcher on the parent data."),
						Optional.of("the DSL matcher"), true, false),
				fullGeneric + " " + fqngc + "." + getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent() + " "
						+ mscn + "With",
				new String[] {
						"org.hamcrest.Matcher",
								"matcherOnParent" },
				"return " + fqngc + "." + mscn + "With(matcherOnParent);");
	}

	public DSLMethod generatParentValueDSLStarter(String argumentForParentBuilder) {
		String genericNoParent = getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent();
		String javadoc = generateDefaultJavaDoc(Optional.empty(),
				Optional.of("other the other object to be used as a reference."), Optional.of("the DSL matcher"), true,
				false);
		List lines = new ArrayList<>();
		lines.add(genericNoParent + " m=new " + getSimpleNameOfGeneratedImplementationMatcherWithGenericNoParent() + "("
				+ argumentForParentBuilder + ");");
		lines.addAll(fields.stream().map(f -> "    " + f.getFieldCopy("m", "other") + ";").collect(toList()));
		lines.add("return m;");
		return new DSLMethod(javadoc,
				fullGeneric + " " + getFullyQualifiedNameOfGeneratedClass() + "." + genericNoParent + " "
						+ methodShortClassName + "WithSameValue",
				new String[] { getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(), "other" },
				lines.toArray(new String[0]));
	}

	public DSLMethod generateNoParentValueDSLStarter() {
		return generatParentValueDSLStarter("");
	}

	public ProvidesMatchersAnnotatedElementMirror getParentMirror() {
		RoundMirror rm = roundMirror;
		return rm.getByName(((TypeElement) rm.getProcessingEnv().getTypeUtils()
				.asElement(typeElementForClassAnnotatedWithProvideMatcher.getSuperclass())).getQualifiedName()
						.toString());
	}

	public DSLMethod generateParentValueDSLStarter() {
		ProvidesMatchersAnnotatedElementMirror parentMirror = getParentMirror();
		String argumentForParentBuilder = parentMirror.getFullyQualifiedNameOfGeneratedClass() + "."
				+ parentMirror.methodShortClassName + "WithSameValue(other)";
		return generatParentValueDSLStarter(argumentForParentBuilder);
	}

	public DSLMethod generateParentInSameRoundWithChaningDSLStarter() {
		String implGenericNoParent = getSimpleNameOfGeneratedImplementationMatcherWithGenericNoParent();
		ProvidesMatchersAnnotatedElementMirror parentMirror = getParentMirror();
		String pmfqngc = parentMirror.getFullyQualifiedNameOfGeneratedClass();
		return new DSLMethod(
				generateDefaultJavaDoc(Optional.empty(), Optional.empty(), Optional.of("the DSL matcher"), true, false),
				fullGeneric + " " + pmfqngc + "." + parentMirror.simpleNameOfGeneratedInterfaceMatcher
						+ genericForChaining + " " + methodShortClassName + "WithParent",
				new String[] {
						implGenericNoParent + " m=new " + implGenericNoParent + "(org.hamcrest.Matchers.anything());",
						pmfqngc + "." + parentMirror.simpleNameOfGeneratedInterfaceMatcher + " tmp = " + pmfqngc + "."
								+ parentMirror.methodShortClassName + "WithParent(m);",
						"m._parent = new SuperClassMatcher(tmp);", "return tmp;" });
	}

	public GeneratedMatcher asXml() {
		GeneratedMatcher gm = new GeneratedMatcher();
		gm.setFullyQualifiedNameGeneratedClass(getFullyQualifiedNameOfGeneratedClass());
		gm.setFullyQualifiedNameInputClass(fullyQualifiedNameOfClassAnnotatedWithProvideMatcher);
		gm.setSimpleNameGeneratedClass(getSimpleNameOfGeneratedClass());
		gm.setSimpleNameInputClass(simpleNameOfClassAnnotatedWithProvideMatcher);
		gm.setDslMethodNameStart(methodShortClassName);
		gm.setGeneratedMatcherField(
				fields.stream().map(AbstractFieldDescription::asGeneratedMatcherField).collect(toList()));
		gm.setMirror(this);
		return gm;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy