de.knightsoftnet.validators.rebind.ValidatorCreator.java Source code

Java tutorial

Introduction

Here is the source code for de.knightsoftnet.validators.rebind.ValidatorCreator.java

Source

/*
 * Copyright 2010 Google Inc. Copyright 2016 Manfred Tremmel
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package de.knightsoftnet.validators.rebind;

import de.knightsoftnet.validators.client.GwtValidation;
import de.knightsoftnet.validators.client.impl.AbstractGwtValidator;
import de.knightsoftnet.validators.client.impl.GwtBeanDescriptor;
import de.knightsoftnet.validators.client.impl.GwtSpecificValidator;
import de.knightsoftnet.validators.client.impl.GwtValidationContext;
import de.knightsoftnet.validators.client.impl.metadata.ValidationGroupsMetadata;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.GroupSequence;
import javax.validation.groups.Default;
import javax.validation.metadata.BeanDescriptor;

/**
 * Creates the validator for the given input class.
 */
public final class ValidatorCreator extends AbstractCreator {

    /**
     * The beans to validate in source declaration order.
     */
    private final ImmutableList<BeanHelper> beansToValidate;
    private final GwtValidation gwtValidation;

    /**
     * constructor.
     */
    public ValidatorCreator(final JClassType validatorType, //
            final GwtValidation gwtValidation, //
            final TreeLogger logger, //
            final GeneratorContext context, final BeanHelperCache cache) throws UnableToCompleteException {
        super(context, logger, validatorType, cache);
        this.gwtValidation = gwtValidation;

        final List<BeanHelper> temp = Lists.newArrayList();
        for (final Class<?> clazz : gwtValidation.value()) {
            final BeanHelper helper = this.createBeanHelper(clazz);
            temp.add(helper);
        }
        this.beansToValidate = Util.sortMostSpecificFirst(temp, BeanHelper.TO_CLAZZ);
    }

    @Override
    protected void compose(final ClassSourceFileComposerFactory composerFactory) {
        this.addImports(composerFactory, GWT.class, GwtBeanDescriptor.class, GwtSpecificValidator.class,
                GwtValidationContext.class, ValidationGroupsMetadata.class, Set.class, HashSet.class, Map.class,
                HashMap.class, Default.class, ConstraintViolation.class, BeanDescriptor.class);
        composerFactory.setSuperclass(AbstractGwtValidator.class.getCanonicalName());
        composerFactory.addImplementedInterface(this.validatorType.getQualifiedSourceName());
    }

    @Override
    protected void writeClassBody(final SourceWriter sourceWriter) {
        this.writeConstructor(sourceWriter);
        sourceWriter.println();
        this.writeCreateValidationGroupsMetadata(sourceWriter);
        sourceWriter.println();
        this.writeValidate(sourceWriter);
        sourceWriter.println();
        this.writeValidateProperty(sourceWriter);
        sourceWriter.println();
        this.writeValidateValue(sourceWriter);
        sourceWriter.println();
        this.writeGetConstraintsForClass(sourceWriter);
        sourceWriter.println();
        this.writeGwtValidate(sourceWriter);
    }

    private void writeConstructor(final SourceWriter sw) {
        // public MyValidator() {
        sw.println("public " + this.getSimpleName() + "() {");
        sw.indent();

        // super(createValidationGroupsMetadata());
        sw.println("super(createValidationGroupsMetadata());");

        sw.outdent();
        sw.println("}");
    }

    private void writeContext(final SourceWriter sw, final BeanHelper bean, final String objectName) {
        // GwtValidationContext<MyBean> context = new GwtValidationContext<MyBean>(
        sw.print(GwtValidationContext.class.getSimpleName());
        sw.print("<T> context = new ");
        sw.print(GwtValidationContext.class.getSimpleName());
        sw.println("<T>(");
        sw.indent();
        sw.indent();

        // (Class<T>) MyBean.class,
        sw.print("(Class<T>) ");
        sw.println(bean.getTypeCanonicalName() + ".class, ");

        // object,
        sw.println(objectName + ", ");

        // MyBeanValidator.INSTANCE.getConstraints(getValidationGroupsMetadata()),
        sw.print(bean.getFullyQualifiedValidatorName());
        sw.println(".INSTANCE.getConstraints(getValidationGroupsMetadata()), ");

        // getMessageInterpolator(),
        sw.println("getMessageInterpolator(), ");

        // getTraversableResolver(),
        sw.println("getTraversableResolver(), ");

        // this);
        sw.println("this);");
        sw.outdent();
        sw.outdent();
    }

    private void writeCreateValidationGroupsMetadata(final SourceWriter sw) {
        // private static ValidationGroupsMetadata createValidationGroupsMetadata() {
        sw.println("private static ValidationGroupsMetadata createValidationGroupsMetadata() {");
        sw.indent();

        // return ValidationGroupsMetadata.builder()
        sw.println("return ValidationGroupsMetadata.builder()");
        sw.indent();
        sw.indent();
        for (final Class<?> group : this.gwtValidation.groups()) {
            final GroupSequence sequenceAnnotation = group.getAnnotation(GroupSequence.class);
            Class<?>[] groups;
            if (sequenceAnnotation == null) {
                // .addGroup(<<group>>
                sw.print(".addGroup(");
                sw.print(group.getCanonicalName() + ".class");
                groups = group.getInterfaces();
            } else {
                // .addSequence(<<sequence>>
                sw.print(".addSequence(");
                sw.print(group.getCanonicalName() + ".class");
                groups = sequenceAnnotation.value();
            }
            for (final Class<?> clazz : groups) {
                // , <<group class>>
                sw.print(", ");
                sw.print(clazz.getCanonicalName() + ".class");
            }
            // )
            sw.println(")");
        }

        // .build();
        sw.println(".build();");
        sw.outdent();
        sw.outdent();

        // }
        sw.outdent();
        sw.println("}");
    }

    private void writeGetConstraintsForClass(final SourceWriter sw) {
        // public BeanDescriptor getConstraintsForClass(Class<?> clazz {
        sw.println("public BeanDescriptor getConstraintsForClass(Class<?> clazz) {");
        sw.indent();

        // checkNotNull(clazz, "clazz");
        sw.println("checkNotNull(clazz, \"clazz\");");

        for (final BeanHelper bean : this.beansToValidate) {
            this.writeGetConstraintsForClass(sw, bean);
        }

        this.writeThrowIllegalArgumnet(sw, "clazz.getName()");

        // }
        sw.outdent();
        sw.println("}");
    }

    private void writeGetConstraintsForClass(final SourceWriter sw, final BeanHelper bean) {
        // if (clazz.eqals(MyBean.class)) {
        sw.println("if (clazz.equals(" + bean.getTypeCanonicalName() + ".class)) {");
        sw.indent();

        // return MyBeanValidator.INSTANCE.getConstraints(getValidationGroupsMetadata());
        sw.print("return ");
        sw.print(bean.getFullyQualifiedValidatorName());
        sw.println(".INSTANCE.getConstraints(getValidationGroupsMetadata());");

        // }
        sw.outdent();
        sw.println("}");
    }

    private void writeGwtValidate(final SourceWriter sw) {
        // public <T> Set<ConstraintViolation<T>> validate(GwtValidationContext<T>
        // context,
        sw.print("public <T> Set<ConstraintViolation<T>> ");
        sw.println("validate(GwtValidationContext<T> context,");
        sw.indent();
        sw.indent();

        // Object object, Class<?>... groups) {
        sw.println("Object object, Class<?>... groups) {");
        sw.outdent();

        sw.println("checkNotNull(context, \"context\");");
        sw.println("checkNotNull(object, \"object\");");
        sw.println("checkNotNull(groups, \"groups\");");
        sw.println("checkGroups(groups);");

        for (final BeanHelper bean : this.cache.getAllBeans()) {
            this.writeGwtValidate(sw, bean);
        }

        // TODO(nchalko) log warning instead.
        this.writeThrowIllegalArgumnet(sw, "object.getClass().getName()");

        sw.outdent();
        sw.println("}");
    }

    private void writeGwtValidate(final SourceWriter sw, final BeanHelper bean) {
        this.writeIfInstanceofBeanType(sw, bean);
        sw.indent();

        // return PersonValidator.INSTANCE

        sw.print("return ");
        sw.println(bean.getFullyQualifiedValidatorName() + ".INSTANCE");
        sw.indent();
        sw.indent();
        // .validate(context, (<<MyBean>>) object, groups);
        sw.print(".validate(context, ");
        sw.print("(" + bean.getTypeCanonicalName() + ") object, ");
        sw.println("groups);");
        sw.outdent();
        sw.outdent();

        // }
        sw.outdent();
        sw.println("}");
    }

    private void writeIfInstanceofBeanType(final SourceWriter sourceWriter, final BeanHelper bean) {
        // if (object instanceof MyBean) {
        sourceWriter.print("if (object instanceof ");
        sourceWriter.print(bean.getTypeCanonicalName());
        sourceWriter.println(") {");
    }

    private void writeThrowIllegalArgumnet(final SourceWriter sourceWriter, final String getClassName) {
        // throw new IllegalArgumentException("MyValidator can not validate ",
        sourceWriter.print("throw new IllegalArgumentException(\"");
        sourceWriter.print(this.validatorType.getName() + " can not  validate \"");
        sourceWriter.indent();
        sourceWriter.indent();

        // + object.getClass().getName() +". "
        sourceWriter.print("+ ");
        sourceWriter.print(getClassName);
        sourceWriter.println("+ \". \"");

        // + "Valid values are {Foo.clas, Bar.class}
        sourceWriter.print("+ \"Valid types are ");
        sourceWriter.print(this.beansToValidate.toString());
        sourceWriter.println("\");");
        sourceWriter.outdent();
        sourceWriter.outdent();
    }

    private void writeValidate(final SourceWriter sw) {
        // public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>...
        // groups) {
        sw.println("public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {");
        sw.indent();

        sw.println("checkNotNull(object, \"object\");");
        sw.println("checkNotNull(groups, \"groups\");");
        sw.println("checkGroups(groups);");

        for (final BeanHelper bean : this.beansToValidate) {
            this.writeValidate(sw, bean);
        }

        this.writeThrowIllegalArgumnet(sw, "object.getClass().getName()");

        sw.outdent();
        sw.println("}");
    }

    private void writeValidate(final SourceWriter sw, final BeanHelper bean) {
        this.writeIfInstanceofBeanType(sw, bean);
        sw.indent();

        this.writeContext(sw, bean, "object");

        // return PersonValidator.INSTANCE
        sw.print("return ");
        sw.println(bean.getFullyQualifiedValidatorName() + ".INSTANCE");
        sw.indent();
        sw.indent();

        // .validate(context, (<<MyBean>>) object, groups);
        sw.print(".validate(context, ");
        sw.print("(" + bean.getTypeCanonicalName() + ") object, ");
        sw.println("groups);");
        sw.outdent();
        sw.outdent();

        // }
        sw.outdent();
        sw.println("}");
    }

    private void writeValidateProperty(final SourceWriter sw) {
        sw.println("public <T> Set<ConstraintViolation<T>> validateProperty("
                + "T object,String propertyName, Class<?>... groups) {");
        sw.indent();

        sw.println("checkNotNull(object, \"object\");");
        sw.println("checkNotNull(propertyName, \"propertyName\");");
        sw.println("checkNotNull(groups, \"groups\");");
        sw.println("checkGroups(groups);");

        for (final BeanHelper bean : this.beansToValidate) {
            this.writeValidateProperty(sw, bean);
        }

        this.writeThrowIllegalArgumnet(sw, "object.getClass().getName()");

        sw.outdent();
        sw.println("}");
    }

    private void writeValidateProperty(final SourceWriter sw, final BeanHelper bean) {
        this.writeIfInstanceofBeanType(sw, bean);
        sw.indent();
        this.writeContext(sw, bean, "object");

        // return PersonValidator.INSTANCE
        sw.print("return ");
        sw.println(bean.getFullyQualifiedValidatorName() + ".INSTANCE");
        sw.indent();
        sw.indent();

        // .validateProperty(context, (MyBean) object, propertyName, groups);
        sw.print(".validateProperty(context, (");
        sw.print(bean.getTypeCanonicalName());
        sw.print(") object, propertyName, ");
        sw.println("groups);");
        sw.outdent();
        sw.outdent();

        // }
        sw.outdent();
        sw.println("}");
    }

    private void writeValidateValue(final SourceWriter sw) {
        sw.println("public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, "
                + "String propertyName, Object value, Class<?>... groups) {");
        sw.indent();

        sw.println("checkNotNull(beanType, \"beanType\");");
        sw.println("checkNotNull(propertyName, \"propertyName\");");
        sw.println("checkNotNull(groups, \"groups\");");
        sw.println("checkGroups(groups);");

        for (final BeanHelper bean : this.beansToValidate) {
            this.writeValidateValue(sw, bean);
        }

        this.writeThrowIllegalArgumnet(sw, "beanType.getName()");

        sw.outdent();
        sw.println("}");
    }

    private void writeValidateValue(final SourceWriter sw, final BeanHelper bean) {
        sw.println("if (beanType.equals(" + bean.getTypeCanonicalName() + ".class)) {");
        sw.indent();
        this.writeContext(sw, bean, "null");

        // return PersonValidator.INSTANCE
        sw.print("return ");
        sw.println(bean.getFullyQualifiedValidatorName() + ".INSTANCE");
        sw.indent();
        sw.indent();

        // .validateValue(context, (Class<MyBean> beanType, propertyName, value,
        // groups);
        sw.print(".validateValue(context, (Class<");
        sw.print(bean.getTypeCanonicalName());
        sw.println(">)beanType, propertyName, value, groups);");
        sw.outdent();
        sw.outdent();

        // }
        sw.outdent();
        sw.println("}");
    }
}