ProvidesMatchersAnnotatedElementMatcherMirror.java
/**
* 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 <http://www.gnu.org/licenses/>.
*/
package ch.powerunit.extensions.matchers.provideprocessor;
import static ch.powerunit.extensions.matchers.common.CommonUtils.addPrefix;
import static ch.powerunit.extensions.matchers.common.ListJoining.joinWithMapperAndDelimiter;
import static java.lang.String.format;
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.reducing;
import static java.util.stream.Collectors.toList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.lang.model.element.TypeElement;
import ch.powerunit.extensions.matchers.common.CommonUtils;
import ch.powerunit.extensions.matchers.common.ListJoining;
import ch.powerunit.extensions.matchers.common.RessourceLoaderHelper;
import ch.powerunit.extensions.matchers.provideprocessor.fields.AbstractFieldDescription;
import ch.powerunit.extensions.matchers.provideprocessor.fields.FieldDescriptionMetaData;
import ch.powerunit.extensions.matchers.provideprocessor.fields.IgnoreFieldDescription;
import ch.powerunit.extensions.matchers.provideprocessor.helper.FeatureMatcher;
public abstract class ProvidesMatchersAnnotatedElementMatcherMirror
extends ProvidesMatchersAnnotatedElementGeneralMirror {
private static final String INTERFACE_FORMAT = RessourceLoaderHelper
.loadRessource(ProvidesMatchersAnnotatedElementMatcherMirror.class, "MatchersInterface.txt");
private static final String IMPLEMENTATION_NO_PARENT_FORMAT = RessourceLoaderHelper
.loadRessource(ProvidesMatchersAnnotatedElementMatcherMirror.class, "MatchersImplementationNoParent.txt");
private static final String IMPLEMENTATION_PARENT_FORMAT = RessourceLoaderHelper
.loadRessource(ProvidesMatchersAnnotatedElementMatcherMirror.class, "MatchersImplementationParent.txt");
private static final String METADATA_FORMAT = RessourceLoaderHelper
.loadRessource(ProvidesMatchersAnnotatedElementMatcherMirror.class, "MatchersMetadata.txt");
private static final ListJoining<AbstractFieldDescription> JOIN_FIELD_DSL_INTERFACE = joinWithMapperAndDelimiter(
s -> addPrefix(" ", s.getDslInterface()), "\n");
private static final ListJoining<AbstractFieldDescription> JOIN_FIELD_MATCHERFIELD = joinWithMapperAndDelimiter(
s -> addPrefix(" ", s.asMatcherField()), "\n");
private static final ListJoining<AbstractFieldDescription> JOIN_FIELD_IMPL = joinWithMapperAndDelimiter(
s -> addPrefix(" ", s.getImplementationInterface()), "\n");
private static final ListJoining<AbstractFieldDescription> JOIN_FIELD_MATCHES_SAFELY = joinWithMapperAndDelimiter(
s -> addPrefix(" ", s.asMatchesSafely() + "\n"), "\n");
private static final ListJoining<AbstractFieldDescription> JOIN_FIELD_DESCRIBE_TO = joinWithMapperAndDelimiter(
s -> addPrefix(" ", s.asDescribeTo() + "\n"), "\n");
private static final ListJoining<AbstractFieldDescription> JOIN_FIELD_MATCHER = joinWithMapperAndDelimiter(
f -> addPrefix(" ", f.getMatcherForField()), "\n");
private static final ListJoining<AbstractFieldDescription> JOIN_FIELD_METADATA = joinWithMapperAndDelimiter(
f -> f.generateMetadata("FieldMetadata"), ", ");
private static final Comparator<AbstractFieldDescription> COMPARING_FIELD_BY_NAME = Comparator
.comparing(FieldDescriptionMetaData::getFieldName);
private static final String DEFAULT_FEATUREMATCHER_FORCONVERTER = "\n private static <_TARGET,_SOURCE> org.hamcrest.Matcher<_SOURCE> asFeatureMatcher(\n String msg,\n java.util.function.Function<_SOURCE,_TARGET> converter,\n org.hamcrest.Matcher<? super _TARGET> matcher) {\n return new org.hamcrest.FeatureMatcher<_SOURCE,_TARGET>(matcher, msg, msg) {\n protected _TARGET featureValueOf(_SOURCE actual) {\n return converter.apply(actual);\n }};\n }\n\n";
protected final List<AbstractFieldDescription> fields;
private final String fieldsMatcher;
private static AbstractFieldDescription reduceByOrderingOnIgnoreFieldDescription(AbstractFieldDescription l,
AbstractFieldDescription r) {
return Optional.ofNullable(l).filter(c -> c instanceof IgnoreFieldDescription).orElse(r);
}
private List<AbstractFieldDescription> generateFields(TypeElement typeElement,
ProvidesMatchersSubElementVisitor providesMatchersSubElementVisitor) {
return typeElement.getEnclosedElements().stream().map(ie -> ie.accept(providesMatchersSubElementVisitor, this))
.filter(Optional::isPresent).map(Optional::get)
.collect(collectingAndThen(groupingBy(FieldDescriptionMetaData::getFieldName, reducing(
ProvidesMatchersAnnotatedElementMatcherMirror::reduceByOrderingOnIgnoreFieldDescription)),
Map::values))
.stream().filter(Optional::isPresent).map(Optional::get).sorted(COMPARING_FIELD_BY_NAME)
.collect(toList());
}
public ProvidesMatchersAnnotatedElementMatcherMirror(TypeElement typeElement, RoundMirror roundMirror) {
super(typeElement, roundMirror);
this.fields = unmodifiableList(generateFields(typeElement, new ProvidesMatchersSubElementVisitor(roundMirror)));
this.fieldsMatcher = JOIN_FIELD_MATCHER.asString(fields) + "\n";
}
public String generatePublicInterface() {
return addPrefix(" ",
format(INTERFACE_FORMAT, getFullyQualifiedNameOfClassAnnotated(), getSimpleNameOfClassAnnotated(),
getParamComment(), simpleNameOfGeneratedInterfaceMatcher, fullGeneric,
getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(), getFullGenericParent(),
generic, getGenericParent(), JOIN_FIELD_DSL_INTERFACE.asString(fields)));
}
protected String generatePrivateImplementation() {
return addPrefix(" ", format(hasSuperClass() ? IMPLEMENTATION_PARENT_FORMAT : IMPLEMENTATION_NO_PARENT_FORMAT,
getSimpleNameOfGeneratedImplementationMatcher(), getFullGenericParent(),
getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(),
getSimpleNameOfGeneratedInterfaceMatcherWithGenericParent(), getFullyQualifiedNameOfClassAnnotated(),
JOIN_FIELD_MATCHERFIELD.asString(fields), JOIN_FIELD_IMPL.asString(fields),
JOIN_FIELD_MATCHES_SAFELY.asString(fields), JOIN_FIELD_DESCRIBE_TO.asString(fields),
fullyQualifiedNameOfSuperClassOfClassAnnotated.orElse("")));
}
public String generateMatchers() {
return new StringBuilder(DEFAULT_FEATUREMATCHER_FORCONVERTER).append(fieldsMatcher)
.append(fullyQualifiedNameOfSuperClassOfClassAnnotated.map(this::generateParentMatcher).orElse(""))
.toString();
}
public String generateParentMatcher(String parent) {
return addPrefix(" ", new FeatureMatcher("SuperClass", fullGeneric, getFullyQualifiedNameOfClassAnnotated(),
"", parent, "parent", "actual").toString());
}
public List<AbstractFieldDescription> getFields() {
return fields;
}
public String generateMetadata() {
return format(METADATA_FORMAT, getAnnotationProcessorVersion(), getCompatibility(),
getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(),
getFullyQualifiedNameOfClassAnnotated(),
fullyQualifiedNameOfSuperClassOfClassAnnotated.map(CommonUtils::toJavaSyntax).orElse("null"),
JOIN_FIELD_METADATA.asString(fields));
}
}