Skip to content

Commit

Permalink
Confirm email validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
wellingtoncosta committed Feb 8, 2018
1 parent fbea5e6 commit 622c3b6
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package convalida.annotations;

import android.support.annotation.StringRes;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.CLASS;

/**
* @author Wellington Costa on 07/02/18.
*/
@Target(FIELD)
@Retention(CLASS)
public @interface ConfirmEmailValidation {

@StringRes int value();

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ class Constants {
static final ClassName VIEW = ClassName.get("android.view", "View");
static final ClassName VIEW_ONCLICK_LISTENER = ClassName.get("android.view", "View.OnClickListener");

static final ClassName VALIDATOR = ClassName.get("convalida.validators", "ConvalidaValidator");
static final ClassName VALIDATOR_SET = ClassName.get("convalida.validators", "ValidatorSet");

static final String NOT_EMPTY_ANNOTATION = "convalida.annotations.NotEmptyValidation";
static final String EMAIL_ANNOTATION = "convalida.annotations.EmailValidation";
static final String CONFIRM_EMAIL_VALIDATION = "convalida.annotations.ConfirmEmailValidation";
static final String PATTERN_ANNOTATION = "convalida.annotations.PatternValidation";
static final String LENGTH_ANNOTATION = "convalida.annotations.LengthValidation";
static final String ONLY_NUMBER_ANNOTATION = "convalida.annotations.OnlyNumberValidation";
Expand All @@ -29,6 +29,7 @@ class Constants {

static final ClassName NOT_EMPTY_VALIDATOR = ClassName.get(VALIDATORS_PACKAGE, "NotEmptyValidator");
static final ClassName EMAIL_VALIDATOR = ClassName.get(VALIDATORS_PACKAGE, "EmailValidator");
static final ClassName CONFIRM_EMAIL_VALIDATOR = ClassName.get(VALIDATORS_PACKAGE, "ConfirmEmailValidator");
static final ClassName PATTERN_VALIDATOR = ClassName.get(VALIDATORS_PACKAGE, "PatternValidator");
static final ClassName LENGTH_VALIDATOR = ClassName.get(VALIDATORS_PACKAGE, "LengthValidator");
static final ClassName ONLY_NUMBER_VALIDATOR = ClassName.get(VALIDATORS_PACKAGE, "OnlyNumberValidator");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import javax.tools.Diagnostic.Kind;

import convalida.annotations.ClearValidationsOnClick;
import convalida.annotations.ConfirmEmailValidation;
import convalida.annotations.ConfirmPasswordValidation;
import convalida.annotations.EmailValidation;
import convalida.annotations.LengthValidation;
Expand All @@ -58,6 +59,14 @@
import convalida.compiler.internal.scanners.IdScanner;
import convalida.compiler.internal.scanners.RClassScanner;

import static convalida.compiler.Constants.CONFIRM_EMAIL_VALIDATION;
import static convalida.compiler.Constants.CONFIRM_PASSWORD_ANNOTATION;
import static convalida.compiler.Constants.EMAIL_ANNOTATION;
import static convalida.compiler.Constants.LENGTH_ANNOTATION;
import static convalida.compiler.Constants.NOT_EMPTY_ANNOTATION;
import static convalida.compiler.Constants.ONLY_NUMBER_ANNOTATION;
import static convalida.compiler.Constants.PASSWORD_ANNOTATION;
import static convalida.compiler.Constants.PATTERN_ANNOTATION;
import static javax.lang.model.element.ElementKind.CLASS;
import static javax.lang.model.element.ElementKind.FIELD;
import static javax.lang.model.element.Modifier.PRIVATE;
Expand All @@ -69,13 +78,14 @@
@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({
"convalida.annotations.NotEmptyValidation",
"convalida.annotations.EmailValidation",
"convalida.annotations.PatternValidation",
"convalida.annotations.LengthValidation",
"convalida.annotations.OnlyNumberValidation",
"convalida.annotations.PasswordValidation",
"convalida.annotations.ConfirmPasswordValidation"
NOT_EMPTY_ANNOTATION,
EMAIL_ANNOTATION,
CONFIRM_EMAIL_VALIDATION,
PATTERN_ANNOTATION,
LENGTH_ANNOTATION,
ONLY_NUMBER_ANNOTATION,
PASSWORD_ANNOTATION,
CONFIRM_PASSWORD_ANNOTATION
})
public class ConvalidaProcessor extends AbstractProcessor {

Expand Down Expand Up @@ -109,6 +119,7 @@ private Set<Class<? extends Annotation>> getSupportedAnnotations() {

annotations.add(NotEmptyValidation.class);
annotations.add(EmailValidation.class);
annotations.add(ConfirmEmailValidation.class);
annotations.add(PatternValidation.class);
annotations.add(LengthValidation.class);
annotations.add(OnlyNumberValidation.class);
Expand Down Expand Up @@ -162,6 +173,16 @@ private List<ValidationClass> findAndParseValidations(RoundEnvironment env) {
}
}

// Process each @ConfirmEmailValidation element
for (Element element : env.getElementsAnnotatedWith(ConfirmEmailValidation.class)) {
if (!SuperficialValidation.validateElement(element)) continue;
try {
parseConfirmEmailValidation(element, parents, validationFields);
} catch (Exception e) {
logParsingError(element, ConfirmEmailValidation.class, e);
}
}

// Process each @PatternValidation element.
for (Element element : env.getElementsAnnotatedWith(PatternValidation.class)) {
if (!SuperficialValidation.validateElement(element)) continue;
Expand Down Expand Up @@ -374,6 +395,20 @@ private void parseEmailValidation(Element element, Set<Element> parents, List<Va
validationFields.add(new ValidationField(element, EmailValidation.class.getCanonicalName(), getId(qualifiedId)));
}

private void parseConfirmEmailValidation(Element element, Set<Element> parents, List<ValidationField> validationFields) {
boolean hasError = isInvalid(ConfirmEmailValidation.class, element) ||
isInaccessible(ConfirmEmailValidation.class, element) ||
!validateConfirmValidationElements(EmailValidation.class, ConfirmEmailValidation.class, element);

if (hasError) return;

int errorMessageResourceId = element.getAnnotation(ConfirmEmailValidation.class).value();
QualifiedId qualifiedId = elementToQualifiedId(element, errorMessageResourceId);

parents.add(element.getEnclosingElement());
validationFields.add(new ValidationField(element, ConfirmEmailValidation.class.getCanonicalName(), getId(qualifiedId)));
}

private void parsePatternValidation(Element element, Set<Element> parents, List<ValidationField> validationFields) {
boolean hasError = isInvalid(PatternValidation.class, element) || isInaccessible(PatternValidation.class, element);

Expand Down Expand Up @@ -464,50 +499,65 @@ private void parsePasswordValidation(Element element, Set<Element> parents, List
}

private void parseConfirmPasswordValidation(Element element, Set<Element> parents, List<ValidationField> validationFields) {
boolean hasError = isInvalid(ConfirmPasswordValidation.class, element) || isInaccessible(ConfirmPasswordValidation.class, element);
boolean hasError = isInvalid(ConfirmPasswordValidation.class, element) ||
isInaccessible(ConfirmPasswordValidation.class, element) ||
!validateConfirmValidationElements(PasswordValidation.class, ConfirmPasswordValidation.class, element);

if (hasError) {
return;
}
if (hasError) return;

int elementsAnnotatedWithPasswordValidation = 0;
int elementsAnnotatedWithConfirmPasswordValidation = 0;
int errorMessageResourceId = element.getAnnotation(ConfirmPasswordValidation.class).value();
QualifiedId qualifiedId = elementToQualifiedId(element, errorMessageResourceId);

parents.add(element.getEnclosingElement());
validationFields.add(new ValidationField(element, ConfirmPasswordValidation.class.getCanonicalName(), getId(qualifiedId)));
}

private boolean validateConfirmValidationElements(
Class<? extends Annotation> primaryAnnotation,
Class<? extends Annotation> confirmAnnotation,
Element element
) {
boolean isValid = true;

String primaryAnnotationClassName = primaryAnnotation.getSimpleName();
String confirmAnnotationClassName = confirmAnnotation.getSimpleName();

int elementsAnnotatedWithPrimaryValidation;
int elementsAnnotatedWithConfirmValidation;

List<? extends Element> elementsOfParent = element.getEnclosingElement().getEnclosedElements();

for (Element elementOfParent : elementsOfParent) {
if (elementOfParent.getAnnotation(PasswordValidation.class) != null) {
elementsAnnotatedWithPasswordValidation++;
}
elementsAnnotatedWithPrimaryValidation = (int) elementsOfParent.stream()
.filter(elementOfParent -> elementOfParent.getAnnotation(primaryAnnotation) != null)
.count();

if (elementOfParent.getAnnotation(ConfirmPasswordValidation.class) != null) {
elementsAnnotatedWithConfirmPasswordValidation++;
}
}
elementsAnnotatedWithConfirmValidation = (int) elementsOfParent.stream()
.filter(elementOfParent -> elementOfParent.getAnnotation(confirmAnnotation) != null)
.count();

if (elementsAnnotatedWithPasswordValidation == 0 && elementsAnnotatedWithConfirmPasswordValidation > 0) {
if (elementsAnnotatedWithPrimaryValidation == 0 && elementsAnnotatedWithConfirmValidation > 0) {
isValid = false;
TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
error(
element.getEnclosingElement(),
"%s must have at least one element annotated with @PasswordValidation.",
enclosingElement.getSimpleName()
"%s must have at least one element annotated with @%s.",
enclosingElement.getSimpleName(),
primaryAnnotationClassName
);
}

if (elementsAnnotatedWithConfirmPasswordValidation > 1) {
if (elementsAnnotatedWithConfirmValidation > 1) {
isValid = false;
TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
error(
element.getEnclosingElement(),
"%s must have only one element annotated with @ConfirmPasswordValidation.",
enclosingElement.getSimpleName()
"%s must have only one element annotated with @%s.",
enclosingElement.getSimpleName(),
confirmAnnotationClassName
);
}

int errorMessageResourceId = element.getAnnotation(ConfirmPasswordValidation.class).value();
QualifiedId qualifiedId = elementToQualifiedId(element, errorMessageResourceId);

parents.add(element.getEnclosingElement());
validationFields.add(new ValidationField(element, ConfirmPasswordValidation.class.getCanonicalName(), getId(qualifiedId)));
return isValid;
}

private boolean isInvalid(Class<? extends Annotation> annotationClass, Element element) {
Expand Down
23 changes: 23 additions & 0 deletions convalida-compiler/src/main/java/convalida/compiler/JavaFiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import convalida.compiler.internal.ValidationClass;
import convalida.compiler.internal.ValidationField;

import static convalida.compiler.Constants.CONFIRM_EMAIL_VALIDATION;
import static convalida.compiler.Constants.CONFIRM_EMAIL_VALIDATOR;
import static convalida.compiler.Constants.CONFIRM_PASSWORD_ANNOTATION;
import static convalida.compiler.Constants.CONFIRM_PASSWORD_VALIDATOR;
import static convalida.compiler.Constants.EMAIL_ANNOTATION;
Expand Down Expand Up @@ -87,6 +89,13 @@ private static CodeBlock createValidationsCodeBlock(ValidationClass validationCl
case EMAIL_ANNOTATION:
builder.add(createEmailValidationCodeBlock(field));
break;
case CONFIRM_EMAIL_VALIDATION:
ValidationField emailField = validationClass.fields.stream()
.filter(streamField -> streamField.annotationClass.equals(EMAIL_ANNOTATION))
.collect(Collectors.toList()).get(0);

builder.add(createConfirmEmailValidationCodeBlock(emailField, field));
break;
case PATTERN_ANNOTATION:
builder.add(createPatternValidationCodeBlock(field));
break;
Expand Down Expand Up @@ -136,6 +145,20 @@ private static CodeBlock createEmailValidationCodeBlock(ValidationField field) {
.build();
}

private static CodeBlock createConfirmEmailValidationCodeBlock(
ValidationField emailField,
ValidationField confirmEmailField) {
return CodeBlock.builder()
.addStatement(
"validatorSet.addValidator(new $T(target.$N, target.$N, target.getString($L)))",
CONFIRM_EMAIL_VALIDATOR,
emailField.name,
confirmEmailField.name,
confirmEmailField.id.code
)
.build();
}

private static CodeBlock createPatternValidationCodeBlock(ValidationField field) {
return CodeBlock.builder()
.addStatement(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package convalida.validators;

import android.support.design.widget.TextInputLayout;
import android.widget.EditText;

/**
* @author Wellington Costa on 07/02/18.
*/
public class ConfirmEmailValidator extends AbstractValidator {

private EditText emailField;
private String email;

ConfirmEmailValidator(String email) {
this.email = email;
}

public ConfirmEmailValidator(TextInputLayout emailLayout, TextInputLayout confirmEmailLayout, String errorMessage) {
super(confirmEmailLayout, errorMessage);
this.emailField = emailLayout.getEditText();
}

public ConfirmEmailValidator(EditText emailField, EditText confirmEmailField, String errorMessage) {
super(confirmEmailField, errorMessage);
this.emailField = emailField;
}

@Override
boolean isNotValid(String value) {
if (emailField != null) {
email = emailField.getText().toString();
}

return !email.equals(value);
}

}

This file was deleted.

Loading

0 comments on commit 622c3b6

Please sign in to comment.