| /* | |
| * Copyright 2010 Google Inc. | |
| * | |
| * 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 com.google.gwt.validation.rebind; | |
| 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 com.google.gwt.validation.client.GwtValidation; | |
| import com.google.gwt.validation.client.impl.AbstractGwtValidator; | |
| import com.google.gwt.validation.client.impl.GwtBeanDescriptor; | |
| import com.google.gwt.validation.client.impl.GwtSpecificValidator; | |
| import com.google.gwt.validation.client.impl.GwtValidationContext; | |
| import java.util.List; | |
| import java.util.Set; | |
| import javax.validation.ConstraintViolation; | |
| import javax.validation.metadata.BeanDescriptor; | |
| /** | |
| * <strong>EXPERIMENTAL</strong> and subject to change. Do not use this in | |
| * production code. | |
| * <p> | |
| * Class that creates the validator for the given input class. | |
| */ | |
| public class ValidatorCreator extends AbstractCreator { | |
| /** | |
| * The beans to validate in source declaration order. | |
| */ | |
| private final ImmutableList<BeanHelper> beansToValidate; | |
| private final GwtValidation gwtValidation; | |
| public ValidatorCreator(JClassType validatorType, // | |
| GwtValidation gwtValidation, // | |
| TreeLogger logger, // | |
| GeneratorContext context) throws UnableToCompleteException { | |
| super(context, logger, validatorType); | |
| this.gwtValidation = gwtValidation; | |
| List<BeanHelper> temp = Lists.newArrayList(); | |
| for (Class<?> clazz : gwtValidation.value()) { | |
| BeanHelper helper = createBeanHelper(clazz); | |
| temp.add(helper); | |
| } | |
| beansToValidate = Util.sortMostSpecificFirst(temp, BeanHelper.TO_CLAZZ); | |
| } | |
| @Override | |
| protected void compose(ClassSourceFileComposerFactory composerFactory) { | |
| addImports(composerFactory, | |
| GWT.class, | |
| GwtBeanDescriptor.class, | |
| GwtSpecificValidator.class, | |
| GwtValidationContext.class, | |
| Set.class, | |
| ConstraintViolation.class, | |
| BeanDescriptor.class); | |
| composerFactory.setSuperclass(AbstractGwtValidator.class.getCanonicalName()); | |
| composerFactory.addImplementedInterface(this.validatorType.getQualifiedSourceName()); | |
| } | |
| @Override | |
| protected void writeClassBody(SourceWriter sourceWriter) { | |
| writeConstructor(sourceWriter); | |
| sourceWriter.println(); | |
| writeValidate(sourceWriter); | |
| sourceWriter.println(); | |
| writeValidateProperty(sourceWriter); | |
| sourceWriter.println(); | |
| writeValidateValue(sourceWriter); | |
| sourceWriter.println(); | |
| writeGetConstraintsForClass(sourceWriter); | |
| sourceWriter.println(); | |
| writeGwtValidate(sourceWriter); | |
| } | |
| private String getSimpleName() { | |
| return validatorType.getSimpleSourceName() + "Impl"; | |
| } | |
| private void writeConstructor(SourceWriter sw) { | |
| // public MyValidator() { | |
| sw.println("public " + getSimpleName() + "() {"); | |
| sw.indent(); | |
| // super( <<groups>>); | |
| sw.print("super("); | |
| boolean first = true; | |
| for (Class<?> group : gwtValidation.groups()) { | |
| if (!first) { | |
| sw.print(", "); | |
| } else { | |
| first = false; | |
| } | |
| sw.print(group.getCanonicalName() + ".class"); | |
| } | |
| sw.println(");"); | |
| sw.outdent(); | |
| sw.println("}"); | |
| } | |
| private void writeContext(SourceWriter sw, BeanHelper bean, 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(), | |
| sw.print(bean.getFullyQualifiedValidatorName()); | |
| sw.println(".INSTANCE.getConstraints(), "); | |
| // getMessageInterpolator(), | |
| sw.println("getMessageInterpolator(), "); | |
| // this); | |
| sw.println("this);"); | |
| sw.outdent(); | |
| sw.outdent(); | |
| } | |
| private void writeGetConstraintsForClass(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 (BeanHelper bean : beansToValidate) { | |
| writeGetConstraintsForClass(sw, bean); | |
| } | |
| writeThrowIllegalArgumnet(sw, "clazz.getName()"); | |
| // } | |
| sw.outdent(); | |
| sw.println("}"); | |
| } | |
| private void writeGetConstraintsForClass(SourceWriter sw, | |
| BeanHelper bean) { | |
| // if (clazz.eqals(MyBean.class)) { | |
| sw.println("if (clazz.equals(" + bean.getTypeCanonicalName() + ".class)) {"); | |
| sw.indent(); | |
| // return MyBeanValidator.INSTANCE.getConstraints(); | |
| sw.print("return "); | |
| sw.print(bean.getFullyQualifiedValidatorName()); | |
| sw.println(".INSTANCE.getConstraints();"); | |
| // } | |
| sw.outdent(); | |
| sw.println("}"); | |
| } | |
| private void writeGwtValidate(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 (BeanHelper bean : Util.sortMostSpecificFirst( | |
| BeanHelper.getBeanHelpers().values(), BeanHelper.TO_CLAZZ)) { | |
| writeGwtValidate(sw, bean); | |
| } | |
| // TODO(nchalko) log warning instead. | |
| writeThrowIllegalArgumnet(sw, "object.getClass().getName()"); | |
| sw.outdent(); | |
| sw.println("}"); | |
| } | |
| private void writeGwtValidate(SourceWriter sw, BeanHelper bean) { | |
| 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(SourceWriter sourceWriter, BeanHelper bean) { | |
| // if (object instanceof MyBean) { | |
| sourceWriter.print("if (object instanceof "); | |
| sourceWriter.print(bean.getTypeCanonicalName()); | |
| sourceWriter.println(") {"); | |
| } | |
| private void writeThrowIllegalArgumnet(SourceWriter sourceWriter, | |
| 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(beansToValidate.toString()); | |
| sourceWriter.println("\");"); | |
| sourceWriter.outdent(); | |
| sourceWriter.outdent(); | |
| } | |
| private void writeValidate(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 (BeanHelper bean : beansToValidate) { | |
| writeValidate(sw, bean); | |
| } | |
| writeThrowIllegalArgumnet(sw, "object.getClass().getName()"); | |
| sw.outdent(); | |
| sw.println("}"); | |
| } | |
| private void writeValidate(SourceWriter sw, BeanHelper bean) { | |
| writeIfInstanceofBeanType(sw, bean); | |
| sw.indent(); | |
| 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(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 (BeanHelper bean : beansToValidate) { | |
| writeValidateProperty(sw, bean); | |
| } | |
| writeThrowIllegalArgumnet(sw, "object.getClass().getName()"); | |
| sw.outdent(); | |
| sw.println("}"); | |
| } | |
| private void writeValidateProperty(SourceWriter sw, BeanHelper bean) { | |
| writeIfInstanceofBeanType(sw, bean); | |
| sw.indent(); | |
| 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(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 (BeanHelper bean : beansToValidate) { | |
| writeValidateValue(sw, bean); | |
| } | |
| writeThrowIllegalArgumnet(sw, "beanType.getName()"); | |
| sw.outdent(); | |
| sw.println("}"); | |
| } | |
| private void writeValidateValue(SourceWriter sw, BeanHelper bean) { | |
| sw.println("if (beanType.equals(" + bean.getTypeCanonicalName() | |
| + ".class)) {"); | |
| sw.indent(); | |
| 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("}"); | |
| } | |
| } |