Skip to content

Commit

Permalink
Issue #331 - Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
boretti committed May 31, 2020
1 parent e9fae03 commit 147a4c8
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 99 deletions.
Expand Up @@ -85,21 +85,21 @@ public List<FieldDSLMethod> getDslForIterableWithGeneric() {
}

@Override
protected String getFieldCopy(String lhs, String rhs, String paramForHasSameValue) {
public String getFieldCopy(String lhs, String rhs, String ignore) {
if (!"".equals(generic)) {
return getFieldCopyForList(lhs, rhs);
}
return super.getFieldCopy(lhs, rhs, paramForHasSameValue);
return super.getFieldCopy(lhs, rhs, ignore);
}

protected String getFieldCopyForList(String lhs, String rhs) {
String fieldAccessor = getFieldAccessor();
String fieldName = getFieldName();
return "if(" + rhs + "." + fieldAccessor + "==null) {" + lhs + "." + fieldName + "(" + MATCHERS
+ ".nullValue()); } else if (" + rhs + "." + fieldAccessor + ".isEmpty()) {" + lhs + "." + fieldName
+ "IsEmptyIterable(); } else {" + lhs + "." + fieldName + "Contains(" + rhs + "." + fieldAccessor
+ ".stream().map(" + generateMatcherBuilderReferenceFor(generic)
+ ").collect(java.util.stream.Collectors.toList())); }";
return "if(" + rhs + "." + fieldAccessor + "==null) {\n " + lhs + "." + fieldName + "(" + MATCHERS
+ ".nullValue());\n} else if (" + rhs + "." + fieldAccessor + ".isEmpty()) {\n " + lhs + "."
+ fieldName + "IsEmptyIterable();\n} else {\n " + lhs + "." + fieldName + "Contains(" + rhs + "."
+ fieldAccessor + ".stream().map(" + generateMatcherBuilderReferenceFor(generic)
+ ").collect(java.util.stream.Collectors.toList()));\n}";
}

protected String generateMatcherBuilderReferenceFor(String generic) {
Expand Down
Expand Up @@ -22,8 +22,6 @@
import static ch.powerunit.extensions.matchers.common.CommonUtils.toJavaSyntax;
import static java.util.stream.Collectors.joining;

import java.util.Optional;

import javax.lang.model.element.Element;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
Expand All @@ -37,8 +35,6 @@ public abstract class FieldDescriptionMetaData extends AbstractFieldDescriptionC
public static final String SEE_TEXT_FOR_IS_MATCHER = "org.hamcrest.Matchers#is(java.lang.Object)";
public static final String SEE_TEXT_FOR_HAMCREST_MATCHER = "org.hamcrest.Matchers The main class from hamcrest that provides default matchers.";
public static final String MATCHERS = "org.hamcrest.Matchers";
public static final String MAIN_FIELD_COPY = "%1$s.%2$s(%3$s)";
public static final String IS_MATCHER = "(org.hamcrest.Matcher)" + MATCHERS + ".is((java.lang.Object)%1$s.%2$s)";

protected final String generic;
protected final String defaultReturnMethod;
Expand Down Expand Up @@ -67,37 +63,17 @@ public String getMatcherForField() {
getFieldName(), "actual." + getFieldAccessor()).toString();
}

public String generateBaseFieldCopy(String lhs, String innerMatcher) {
return String.format(MAIN_FIELD_COPY, lhs, getFieldName(), innerMatcher);
}

public String getFieldCopyDefault(String lhs, String rhs) {
return generateBaseFieldCopy(lhs, String.format(IS_MATCHER, rhs, getFieldAccessor()));
}

public String getFieldCopySameRound(String lhs, String rhs, Matchable target, String paramForHasSameValue) {
String fieldAccessor = getFieldAccessor();
return generateBaseFieldCopy(lhs,
rhs + "." + fieldAccessor + "==null?" + MATCHERS + ".nullValue():" + target.getWithSameValue(false)
+ "(" + rhs + "." + fieldAccessor + (target.supportIgnore() ? paramForHasSameValue : "") + ")");
}

public String getFieldCopy(String lhs, String rhs, Optional<String> ignored) {
return ignored
.map(i -> "if (!java.util.Arrays.asList(" + i + ").contains(\"" + getFieldName() + "\")) {"
+ getFieldCopy(lhs, rhs,
",java.util.Arrays.stream(" + i + ").filter(s->s.startsWith(\"" + getFieldName()
+ ".\")).map(s->s.replaceFirst(\"" + getFieldName()
+ "\\\\.\",\"\")).toArray(String[]::new)")
+ ";}")
.orElseGet(() -> getFieldCopy(lhs, rhs, ""));
}

protected String getFieldCopy(String lhs, String rhs, String paramForHasSameValue) {
public String getFieldCopy(String lhs, String rhs, String ignore) {
return mirror.getMatchable(containingElementMirror.getRoundMirror())
.filter(a -> mirror.getFieldTypeAsTypeElement().getTypeParameters().isEmpty())
.filter(Matchable::hasWithSameValue).map(p -> getFieldCopySameRound(lhs, rhs, p, paramForHasSameValue))
.orElse(getFieldCopyDefault(lhs, rhs));
.filter(Matchable::hasWithSameValue)
.map(p -> String.format(
"%1$s.%6$s(%2$s.%3$s == null ? org.hamcrest.Matchers.nullValue() : %4$s(%2$s.%3$s%5$s));", lhs,
rhs, getFieldAccessor(), p.getWithSameValue(false), p.supportIgnore() ? ignore : "",
getFieldName()))
.orElseGet(() -> String.format(
"%1$s.%4$s((org.hamcrest.Matcher)org.hamcrest.Matchers.is((java.lang.Object)%2$s.%3$s));", lhs,
rhs, getFieldAccessor(), getFieldName()));
}

public String asMatchesSafely() {
Expand Down
Expand Up @@ -57,7 +57,7 @@ public String asMatcherField() {
}

@Override
protected String getFieldCopy(String lhs, String rhs,String paramForHasSameValue) {
public String getFieldCopy(String lhs, String rhs, String ignore) {
return "/* ignored - " + getFieldName() + " */";
}

Expand Down
Expand Up @@ -73,15 +73,15 @@ private FieldDSLMethod generateHasSameValue(String fieldType, String keyMatcher,
}

@Override
protected String getFieldCopy(String lhs, String rhs, String paramForHasSameValue) {
public String getFieldCopy(String lhs, String rhs, String ignore) {
if (!"".equals(generic)) {
String fieldAccessor = getFieldAccessor();
String fieldName = getFieldName();
return "if(" + rhs + "." + fieldAccessor + "==null) {" + lhs + "." + fieldName + "(" + MATCHERS
+ ".nullValue()); } else {" + lhs + "." + fieldName + "HasSameValues(" + rhs + "." + fieldAccessor
+ ");}";
return "if(" + rhs + "." + fieldAccessor + "==null) {\n " + lhs + "." + fieldName + "(" + MATCHERS
+ ".nullValue());\n} else {\n " + lhs + "." + fieldName + "HasSameValues(" + rhs + "."
+ fieldAccessor + ");\n}";
}
return super.getFieldCopy(lhs, rhs, paramForHasSameValue);
return super.getFieldCopy(lhs, rhs, ignore);

}

Expand Down
Expand Up @@ -79,22 +79,22 @@ private Collection<FieldDSLMethod> getAbsentDSL() {
}

@Override
protected String getFieldCopy(String lhs, String rhs, String paramForHasSameValue) {
public String getFieldCopy(String lhs, String rhs, String ignore) {
if (!"".equals(generic)) {
return getFieldCopyForOptional(lhs, rhs, paramForHasSameValue);
return getFieldCopyForOptional(lhs, rhs, ignore);
}
return super.getFieldCopy(lhs, rhs, paramForHasSameValue);
return super.getFieldCopy(lhs, rhs, ignore);
}

public String getFieldCopyForOptional(String lhs, String rhs, String paramForHasSameValue) {
String fieldAccessor = getFieldAccessor();
String fieldName = getFieldName();
return "if(" + rhs + "." + fieldAccessor + "==null) {" + lhs + "." + fieldName + "(" + MATCHERS
+ ".nullValue()); } else if (!" + rhs + "." + fieldAccessor + ".isPresent()) {" + lhs + "." + fieldName
+ "IsAbsent(); } else {" + lhs + "." + fieldName + "IsPresentAndIs("
return "if(" + rhs + "." + fieldAccessor + "==null) {\n " + lhs + "." + fieldName + "(" + MATCHERS
+ ".nullValue());\n} else if (!" + rhs + "." + fieldAccessor + ".isPresent()) {\n " + lhs + "."
+ fieldName + "IsAbsent();\n} else {\n " + lhs + "." + fieldName + "IsPresentAndIs("
+ generateMatcherBuilderReferenceFor(generic, rhs + "." + fieldAccessor + ".get()",
paramForHasSameValue)
+ "); }";
+ ");\n}";
}

public String generateMatcherBuilderReferenceFor(String generic, String accessor, String paramForHasSameValue) {
Expand Down
@@ -1,58 +1,85 @@
package ch.powerunit.extensions.matchers.provideprocessor.helper;

import static ch.powerunit.extensions.matchers.common.CommonUtils.addPrefix;
import static ch.powerunit.extensions.matchers.provideprocessor.dsl.DSLMethod.of;
import static java.util.Arrays.asList;
import static java.util.Optional.empty;
import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.tools.Diagnostic.Kind;

import ch.powerunit.extensions.matchers.provideprocessor.ProvidesMatchersAnnotatedElementMirror;
import ch.powerunit.extensions.matchers.provideprocessor.dsl.DSLMethod;
import ch.powerunit.extensions.matchers.provideprocessor.fields.AbstractFieldDescription;

public final class ProvidesMatchersWithSameValueHelper {

private ProvidesMatchersWithSameValueHelper() {
}

private static DSLMethod generateWithSameValueWithParentMatcherAndMayIgnore(
ProvidesMatchersAnnotatedElementMirror target, boolean hasSuper, boolean ignore) {
private static DSLMethod generateWithSameValueWithParentMatcherIgnore(ProvidesMatchersAnnotatedElementMirror target,
boolean hasSuper) {
String genericNoParent = target.getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent();
String simpleNameGenericNoParent = target.getSimpleNameOfGeneratedImplementationMatcherWithGenericNoParent();
String simpleNameGenericWithParent = target
.getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric();
String fullyQualified = target.getFullyQualifiedNameOfGeneratedClass();
String withSameValueMethodName = target.getMethodNameDSLWithSameValue();
String fullGeneric = target.getFullGeneric();
String argumentForParentBuilder = hasSuper ? (target.getParentMirror().map(
p -> p.getWithSameValue(false) + "(other" + (p.supportIgnore() && ignore ? ",ignoredFields" : "") + ")")
.orElse("org.hamcrest.Matchers.anything()")) : "";
String javadoc = target.generateDefaultJavaDocWithoutDSLStarter(
Optional.of("other the other object to be used as a reference."
+ (ignore ? "\n ignoredFields fields name that must be ignored." : "")),
String argumentForParentBuilder = hasSuper
? (target.getParentMirror()
.map(p -> p.getWithSameValue(false) + "(other" + (p.supportIgnore() ? ",ignoredFields" : "")
+ ")")
.orElse("org.hamcrest.Matchers.anything()"))
: "";
String javadoc = target.generateDefaultJavaDocWithoutDSLStarter(Optional.of(
"other the other object to be used as a reference.\n ignoredFields fields name that must be ignored."),
"the DSL matcher", false);
List<String> lines = new ArrayList<>();
lines.add("java.util.Set<String> ignored = new java.util.HashSet<>(java.util.Arrays.asList(ignoredFields));");
lines.add(genericNoParent + " m=new " + simpleNameGenericNoParent + "(" + argumentForParentBuilder + ");");
lines.addAll(target.getFields().stream()
.map(f -> f.getFieldCopy("m", "other", ignore ? Optional.of("ignoredFields") : empty()) + ";")
.collect(toList()));

lines.addAll(
target.getFields().stream().flatMap(ProvidesMatchersWithSameValueHelper::copyField).collect(toList()));
lines.add("return m;");
return of(fullGeneric + " " + fullyQualified + "." + genericNoParent + " " + withSameValueMethodName)
.withArguments(ignore
? new String[][] { { simpleNameGenericWithParent, "other" }, { "String...", "ignoredFields" } }
: new String[][] { { simpleNameGenericWithParent, "other" } })
.withArguments(
new String[][] { { simpleNameGenericWithParent, "other" }, { "String...", "ignoredFields" } })
.withImplementation(lines).withJavadoc(javadoc);
}

private static Stream<String> copyField(AbstractFieldDescription f) {
return Arrays.stream(String.format(
"if(!ignored.contains(\"%1$s\")) {\n String localIgnored[] = ignored.stream().filter(s->s.startsWith(\"%1$s.\")).map(s->s.replaceFirst(\"%1$s\\\\.\",\"\")).toArray(String[]::new);\n%2$s\n}",
f.getFieldName(), addPrefix(" ", f.getFieldCopy("m", "other", ",localIgnored"))).split("\n"));
}

private static DSLMethod generateWithSameValueWithParentMatcherAndNoIgnore(
ProvidesMatchersAnnotatedElementMirror target, boolean hasSuper) {
String genericNoParent = target.getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent();
String simpleNameGenericWithParent = target
.getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric();
String fullyQualified = target.getFullyQualifiedNameOfGeneratedClass();
String withSameValueMethodName = target.getMethodNameDSLWithSameValue();
String fullGeneric = target.getFullGeneric();
String javadoc = target.generateDefaultJavaDocWithoutDSLStarter(
Optional.of("other the other object to be used as a reference."), "the DSL matcher", false);
return of(fullGeneric + " " + fullyQualified + "." + genericNoParent + " " + withSameValueMethodName)
.withOneArgument(simpleNameGenericWithParent, "other")
.withImplementation("return " + withSameValueMethodName + "(other,new String[]{});")
.withJavadoc(javadoc);
}

public static boolean isWeakAllowed(ProvidesMatchersAnnotatedElementMirror target) {
if (target.getRealAnnotation().allowWeakWithSameValue()) {
Optional<AnnotationMirror> am = target.getAnnotationMirror();
Expand All @@ -71,26 +98,25 @@ public static Collection<Supplier<DSLMethod>> generateParentValueDSLStarter(
ProvidesMatchersAnnotatedElementMirror target, boolean hasSuper) {
if (hasSuper) {
return asList(() -> target.getParentMirror()
.map(parentMirror -> generateWithSameValueWithParentMatcherAndMayIgnore(target, true, true))
.orElseGet(() -> {
.map(parentMirror -> generateWithSameValueWithParentMatcherIgnore(target, true)).orElseGet(() -> {
if (isWeakAllowed(target)) {
return generateWithSameValueWithParentMatcherAndMayIgnore(target, true, true);
return generateWithSameValueWithParentMatcherIgnore(target, true);
} else {
return null;
}
}),
() -> target.getParentMirror().map(
parentMirror -> generateWithSameValueWithParentMatcherAndMayIgnore(target, true, false))
() -> target.getParentMirror()
.map(parentMirror -> generateWithSameValueWithParentMatcherAndNoIgnore(target, true))
.orElseGet(() -> {
if (isWeakAllowed(target)) {
return generateWithSameValueWithParentMatcherAndMayIgnore(target, true, false);
return generateWithSameValueWithParentMatcherAndNoIgnore(target, true);
} else {
return null;
}
}));
}
return asList(() -> generateWithSameValueWithParentMatcherAndMayIgnore(target, false, false),
() -> generateWithSameValueWithParentMatcherAndMayIgnore(target, false, true));
return asList(() -> generateWithSameValueWithParentMatcherIgnore(target, false),
() -> generateWithSameValueWithParentMatcherAndNoIgnore(target, false));
}

}
Expand Up @@ -107,7 +107,7 @@ public void testGenerateDSLStarter() {
Collection<DSLMethod> results = underTest.generateDSLStarter();
assertThat(results).is(iterableWithSize(4));
assertThat(results.stream().map(x -> x.asStaticImplementation()).collect(Collectors.joining("\n"))).is(
"/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * <p>\n * The returned builder (which is also a Matcher), at this point accepts any object that is a {@link fqn.Sn Sn}.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher <Void> snWith() {\n return new SnMatcherImpl<Void>();\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * <p>\n * The returned builder (which is also a Matcher), at this point accepts any object that is a {@link fqn.Sn Sn}.\n * @param parentBuilder the parentBuilder.\n * \n * \n * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used an indicate no parent builder.\n * @return the DSL matcher\n */\npublic static <_PARENT> fqn.SnMatchers.SnMatcher <_PARENT> snWithParent(_PARENT parentBuilder) {\n return new SnMatcherImpl<_PARENT>(parentBuilder);\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * @param other the other object to be used as a reference.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher <Void> snWithSameValue(fqn.Sn other) {\n SnMatcher <Void> m=new SnMatcherImpl<Void>();\n return m;\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * @param other the other object to be used as a reference.\n * @param ignoredFields fields name that must be ignored.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher <Void> snWithSameValue(fqn.Sn other,String... ignoredFields) {\n SnMatcher <Void> m=new SnMatcherImpl<Void>();\n return m;\n}\n");
"/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * <p>\n * The returned builder (which is also a Matcher), at this point accepts any object that is a {@link fqn.Sn Sn}.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher <Void> snWith() {\n return new SnMatcherImpl<Void>();\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * <p>\n * The returned builder (which is also a Matcher), at this point accepts any object that is a {@link fqn.Sn Sn}.\n * @param parentBuilder the parentBuilder.\n * \n * \n * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used an indicate no parent builder.\n * @return the DSL matcher\n */\npublic static <_PARENT> fqn.SnMatchers.SnMatcher <_PARENT> snWithParent(_PARENT parentBuilder) {\n return new SnMatcherImpl<_PARENT>(parentBuilder);\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * @param other the other object to be used as a reference.\n * @param ignoredFields fields name that must be ignored.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher <Void> snWithSameValue(fqn.Sn other,String... ignoredFields) {\n java.util.Set<String> ignored = new java.util.HashSet<>(java.util.Arrays.asList(ignoredFields));\n SnMatcher <Void> m=new SnMatcherImpl<Void>();\n return m;\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * @param other the other object to be used as a reference.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher <Void> snWithSameValue(fqn.Sn other) {\n return snWithSameValue(other,new String[]{});\n}\n");
}

}
Expand Up @@ -4,7 +4,6 @@

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
Expand Down Expand Up @@ -139,30 +138,12 @@ public void testAsMatchesSafely() {
}

@Test
public void testGetFieldCopy() {
public void testGetFieldCopyIgnore() {
DefaultFieldDescription undertest = new DefaultFieldDescription(() -> provideMatchersAnnotatedElementMirror,
new FieldDescriptionMirror(() -> provideMatchersAnnotatedElementMirror, "field", "boolean",
executableElement));
assertThat(undertest.getFieldCopy("a", "b",""))
.is("a.field((org.hamcrest.Matcher)org.hamcrest.Matchers.is((java.lang.Object)b.field()))");
}

@Test
public void testGetFieldCopyIgnoreAbsent() {
DefaultFieldDescription undertest = new DefaultFieldDescription(() -> provideMatchersAnnotatedElementMirror,
new FieldDescriptionMirror(() -> provideMatchersAnnotatedElementMirror, "field", "boolean",
executableElement));
assertThat(undertest.getFieldCopy("a", "b", Optional.empty()))
.is("a.field((org.hamcrest.Matcher)org.hamcrest.Matchers.is((java.lang.Object)b.field()))");
}

@Test
public void testGetFieldCopyIgnorePresent() {
DefaultFieldDescription undertest = new DefaultFieldDescription(() -> provideMatchersAnnotatedElementMirror,
new FieldDescriptionMirror(() -> provideMatchersAnnotatedElementMirror, "field", "boolean",
executableElement));
assertThat(undertest.getFieldCopy("a", "b", Optional.of("x"))).is(
"if (!java.util.Arrays.asList(x).contains(\"field\")) {a.field((org.hamcrest.Matcher)org.hamcrest.Matchers.is((java.lang.Object)b.field()));}");
assertThat(undertest.getFieldCopy("a", "b", ",x"))
.is("a.field((org.hamcrest.Matcher)org.hamcrest.Matchers.is((java.lang.Object)b.field()));");
}

@Test
Expand Down

0 comments on commit 147a4c8

Please sign in to comment.