
fr.ird.observe.maven.plugins.toolbox.ValidatorsCache Maven / Gradle / Ivy
package fr.ird.observe.maven.plugins.toolbox;
/*-
* #%L
* ObServe Toolkit :: Maven plugin
* %%
* Copyright (C) 2017 - 2018 IRD, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* .
* #L%
*/
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
import org.apache.maven.plugin.logging.Log;
import org.nuiton.validator.NuitonValidatorScope;
import org.nuiton.validator.bean.simple.SimpleBeanValidator;
/**
* Created on 31/08/16.
*
* @author Tony Chemit - [email protected]
*/
public class ValidatorsCache {
public static class ValidatorInfo {
private final Class> type;
private final String context;
private final NuitonValidatorScope scope;
private final Set fields;
ValidatorInfo(Class> type, String context, NuitonValidatorScope scope, Set fields) {
this.type = type;
this.context = context;
this.scope = scope;
this.fields = fields;
}
public Class> getType() {
return type;
}
public String getContext() {
return context;
}
public NuitonValidatorScope getScope() {
return scope;
}
public Set getFields() {
return fields;
}
}
private final static ValidatorsCache instance = new ValidatorsCache();
public static ValidatorsCache get() {
return instance;
}
private final Multimap validators = ArrayListMultimap.create();
public Collection getValidators(ValidatorCacheRequest request) throws IOException {
Log log = request.getLog();
boolean verbose = request.isVerbose();
Path sourceRootPath = request.getSourceRootPath();
String key = sourceRootPath.toFile().getAbsolutePath();
if (!validators.containsKey(key)) {
log.info("Loading validators from " + sourceRootPath);
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(request.getUrlClassLoader());
PathSimpleFileVisitorResult result = new PathSimpleFileVisitor(log, sourceRootPath, verbose).walk();
NuitonValidatorScope[] scopes = result.getEffectiveScopes();
for (ValidatorDescriptor descritptor : result.descritptors) {
String typeName = descritptor.getTypeName();
String context = descritptor.getContext();
Class> type = Class.forName(typeName);
SimpleBeanValidator> validator = SimpleBeanValidator.newValidator(type, context, scopes);
for (NuitonValidatorScope scope : validator.getEffectiveScopes()) {
Set effectiveFields = validator.getEffectiveFields(scope);
ValidatorInfo validatorInfo = new ValidatorInfo(type, context, scope, effectiveFields);
validators.put(key, validatorInfo);
}
}
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
} finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
return validators.get(key);
}
private static class PathSimpleFileVisitorResult {
private final Set descritptors;
private PathSimpleFileVisitorResult(Set descritptors) {
this.descritptors = descritptors;
}
public NuitonValidatorScope[] getEffectiveScopes() {
EnumSet result = EnumSet.noneOf(NuitonValidatorScope.class);
result.addAll(descritptors.stream().map(ValidatorDescriptor::getScope).collect(Collectors.toList()));
return result.toArray(new NuitonValidatorScope[0]);
}
}
private static class ValidatorDescriptor {
private final String typeName;
private final String context;
private final NuitonValidatorScope scope;
private ValidatorDescriptor(String typeName, String context, NuitonValidatorScope scope) {
this.typeName = typeName;
this.context = context;
this.scope = scope;
}
public String getTypeName() {
return typeName;
}
public String getContext() {
return context;
}
public NuitonValidatorScope getScope() {
return scope;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ValidatorDescriptor that = (ValidatorDescriptor) o;
return Objects.equals(getTypeName(), that.getTypeName()) &&
Objects.equals(getContext(), that.getContext()) &&
getScope() == that.getScope();
}
@Override
public int hashCode() {
return Objects.hash(getTypeName(), getContext(), getScope());
}
}
private static class PathSimpleFileVisitor extends SimpleFileVisitor {
private final Set descritptors = new LinkedHashSet<>();
private final Set scopes = new LinkedHashSet<>();
private final Log log;
private final Path sourceRootPath;
private final boolean verbose;
private String packageName = "";
PathSimpleFileVisitor(Log log, Path sourceRootPath, boolean verbose) {
this.log = log;
this.sourceRootPath = sourceRootPath;
this.verbose = verbose;
for (NuitonValidatorScope scope : NuitonValidatorScope.values()) {
scopes.add(scope.name().toLowerCase());
}
}
public PathSimpleFileVisitorResult walk() throws IOException {
Files.walkFileTree(sourceRootPath, this);
log.info(descritptors.size() + " type(s) detected.");
return new PathSimpleFileVisitorResult(descritptors);
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if (!dir.equals(sourceRootPath)) {
if (!packageName.isEmpty()) {
packageName += ".";
}
packageName += dir.toFile().getName();
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
if (!dir.equals(sourceRootPath)) {
String name = dir.toFile().getName();
packageName = packageName.substring(0, packageName.length() - name.length());
if (packageName.endsWith(".")) {
packageName = packageName.substring(0, packageName.length() - 1);
}
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
String name = file.toFile().getName();
if (name.endsWith("-validation.xml")) {
int i = name.indexOf('-');
String typeName = packageName + "." + name.substring(0, i);
String rest = name.substring(i);
LinkedHashSet contexts = new LinkedHashSet<>();
StringTokenizer tok = new StringTokenizer(rest, "-");
NuitonValidatorScope scope = null;
while (tok.hasMoreTokens()) {
String token = tok.nextToken();
if (scopes.contains(token)) {
scope = NuitonValidatorScope.valueOf(token.toUpperCase());
break;
}
contexts.add(token);
}
String context = String.join("-", contexts);
ValidatorDescriptor descritptor = new ValidatorDescriptor(typeName, context, scope);
boolean add = descritptors.add(descritptor);
if (add) {
if (verbose) {
log.info("Register " + typeName);
}
}
}
return FileVisitResult.CONTINUE;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy