org.nuiton.jaxx.compiler.finalizers.ValidatorFinalizer Maven / Gradle / Ivy
The newest version!
/*
* #%L
* JAXX :: Compiler
* %%
* Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jaxx.compiler.finalizers;
import com.google.auto.service.AutoService;
import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.plexus.component.annotations.Component;
import org.nuiton.jaxx.compiler.CompiledObject;
import org.nuiton.jaxx.compiler.CompiledObject.ChildRef;
import org.nuiton.jaxx.compiler.JAXXCompiler;
import org.nuiton.jaxx.compiler.java.JavaElementFactory;
import org.nuiton.jaxx.compiler.java.JavaField;
import org.nuiton.jaxx.compiler.java.JavaFile;
import org.nuiton.jaxx.compiler.reflect.ClassDescriptor;
import org.nuiton.jaxx.compiler.tags.swing.TabWithValidatorHandler;
import org.nuiton.jaxx.compiler.tags.validator.BeanValidatorHandler;
import org.nuiton.jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator;
import org.nuiton.jaxx.compiler.types.TypeManager;
import org.nuiton.jaxx.runtime.swing.SwingUtil;
import org.nuiton.jaxx.validator.JAXXValidator;
import org.nuiton.jaxx.validator.swing.ValidatorField;
import org.nuiton.jaxx.validator.swing.tab.TabInfoWithValidator;
import javax.swing.JComponent;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
/**
* To finalize validators fields.
*
* @author Tony Chemit - [email protected]
*/
@AutoService(JAXXCompilerFinalizer.class)
@Component(hint = "validators", role = JAXXCompilerFinalizer.class)
public class ValidatorFinalizer extends AbstractFinalizer {
protected static final JavaField VALIDATOR_IDS_FIELD =
JavaElementFactory.newField(
Modifier.PROTECTED,
List.class.getName() + "",
"validatorIds",
true
);
protected static final JavaField VALIDATOR_EDITORS_FIELD =
JavaElementFactory.newField(
Modifier.PROTECTED,
String.format("%s<%s, %s>", ArrayListMultimap.class.getName(), JComponent.class.getName(), ValidatorField.class.getName()),
"validatorEditors",
true
);
@Override
public boolean accept(JAXXCompiler compiler) {
//use this finalizer if compiler is validation aware
return BeanValidatorHandler.hasValidator(compiler);
}
@Override
public void finalizeCompiler(CompiledObject root,
JAXXCompiler compiler,
JavaFile javaFile,
String packageName,
String className) {
for (CompiledObject object : compiler.getObjects().values()) {
List children = object.getChilds();
if (children == null || children.isEmpty()) {
continue;
}
for (ChildRef child : children) {
// some validators are defined on this object
boolean found = BeanValidatorHandler.isComponentUsedByValidator(compiler, child.getChild().getId());
if (found) {
String type = compiler.getImportedType(SwingUtil.class);
String javaCode = child.getChildJavaCode();
// box the child component in a JxLayer
child.setChildJavaCode(type + ".boxComponentWithJxLayer(" + javaCode + ")");
}
}
}
String eol = JAXXCompiler.getLineSeparator();
// register validators
List validators = BeanValidatorHandler.getValidators(compiler);
StringBuilder createValidatorEditorsContent = new StringBuilder();
compiler.addImport(LinkedList.class);
createValidatorEditorsContent.append("ArrayListMultimap editors = ArrayListMultimap.create();").append(eol);
String fieldType = compiler.getImportedType(ValidatorField.class);
int fieldCount = 0;
List validatorIds = new LinkedList<>();
for (CompiledBeanValidator validator : validators) {
String validatorId = TypeManager.getJavaCode(validator.getId());
validatorIds.add(validatorId);
fieldCount += registerValidatorFields(validator, compiler, validatorId, fieldType, createValidatorEditorsContent, eol);
}
createValidatorEditorsContent.append("return editors;");
javaFile.addMethod(JavaElementFactory.newMethod(
Modifier.PUBLIC,
"ArrayListMultimap",
"createValidatorEditors",
createValidatorEditorsContent.toString(),
true)
);
StringBuilder builder = new StringBuilder();
builder.append(eol).append("// register ").append(validatorIds.size()).append(" validator(s)").append(eol);
builder.append("validatorIds = List.of(").append(Joiner.on(", ").join(validatorIds)).append(");").append(eol);
builder.append("// register ").append(fieldCount).append(" validator fields(s)").append(eol);
builder.append("validatorEditors = createValidatorEditors();").append(eol);
builder.append("installValidationUI();").append(eol);
List tabs = TabWithValidatorHandler.getTabs(compiler);
if (!tabs.isEmpty()) {
for (TabInfoWithValidator tab : tabs) {
builder.append("installTabUI(this, ").append(tab.getId()).append(");").append(eol);
}
}
compiler.appendLateInitializer(builder.toString());
}
@Override
public void prepareJavaFile(CompiledObject root,
JAXXCompiler compiler,
JavaFile javaFile,
String packageName,
String className) {
ClassDescriptor validatorClass = compiler.getEngine().getValidatorFactoryClass();
Class> validatorInterface = JAXXValidator.class;
boolean parentIsValidator = compiler.isSuperClassAware(validatorInterface);
if (!parentIsValidator) {
// add JAXXValidator interface
javaFile.addInterface(JAXXCompiler.getCanonicalName(validatorInterface));
}
// implements JAXXValidator
addField(javaFile, VALIDATOR_IDS_FIELD);
addField(javaFile, VALIDATOR_EDITORS_FIELD);
String type = compiler.getImportedType(validatorClass.getName());
String initializer = String.format("return (%s>) (validatorIds.contains(validatorId) ? getObjectById(validatorId) : null);", type);
javaFile.addMethod(JavaElementFactory.newMethod(
Modifier.PUBLIC,
type + ">",
"getValidator",
initializer,
true,
JavaElementFactory.newArgument(TYPE_STRING, "validatorId"))
);
}
public int registerValidatorFields(CompiledBeanValidator validator, JAXXCompiler compiler, String validatorId, String fieldType, StringBuilder createValidatorEditorsContent, String eol) {
int fieldCount = 0;
for (String component : validator.getFieldEditors()) {
Collection propertyNames = validator.getFieldPropertyNames(component);
List keyCodes = new ArrayList<>(propertyNames.size());
for (String propertyName : propertyNames) {
if (!validator.checkBeanProperty(compiler, propertyName)) {
// property not find on bean
continue;
}
String keyCode = TypeManager.getJavaCode(propertyName);
keyCodes.add(keyCode);
}
if (keyCodes.isEmpty()) {
// no property
continue;
}
String keyCode = Joiner.on(", ").join(keyCodes);
String editorCode = TypeManager.getJavaCode(component);
String editorGetter = "get" + StringUtils.capitalize(component);
String annotation = String.format("new %s( %s, %s, %s)", fieldType, validatorId, editorCode, keyCode);
createValidatorEditorsContent.append(String.format("editors.put(%s(), %s);", editorGetter, annotation)).append(eol);
fieldCount++;
}
return fieldCount;
}
}