Commit a6a19292 authored by Phillip Webb's avatar Phillip Webb

Extract inner-classes from GroovyCompiler

Extract and refactor inner-classes from the GroovyCompiler to improve
code readability.
parent 8d186945
/*
* Copyright 2012-2013 the original author or authors.
*
* 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 org.springframework.boot.cli.compiler;
import groovy.lang.GroovyClassLoader;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.transform.ASTTransformation;
/**
* {@link ASTTransformation} to apply
* {@link CompilerAutoConfiguration#applyDependencies(DependencyCustomizer) dependency
* auto-configuration}.
*
* @author Phillip Webb
* @author Dave Syer
* @author Andy Wilkinson
*/
class DependencyAutoConfigurationTransformation implements ASTTransformation {
private final GroovyClassLoader loader;
private final ArtifactCoordinatesResolver coordinatesResolver;
private final Iterable<CompilerAutoConfiguration> compilerAutoConfigurations;
DependencyAutoConfigurationTransformation(GroovyClassLoader loader,
ArtifactCoordinatesResolver coordinatesResolver,
Iterable<CompilerAutoConfiguration> compilerAutoConfigurations) {
this.loader = loader;
this.coordinatesResolver = coordinatesResolver;
this.compilerAutoConfigurations = compilerAutoConfigurations;
}
@Override
public void visit(ASTNode[] nodes, SourceUnit source) {
for (ASTNode astNode : nodes) {
if (astNode instanceof ModuleNode) {
visitModule((ModuleNode) astNode);
}
}
}
private void visitModule(ModuleNode module) {
DependencyCustomizer dependencies = new DependencyCustomizer(this.loader, module,
this.coordinatesResolver);
for (ClassNode classNode : module.getClasses()) {
for (CompilerAutoConfiguration autoConfiguration : this.compilerAutoConfigurations) {
if (autoConfiguration.matches(classNode)) {
autoConfiguration.applyDependencies(dependencies);
}
}
}
}
}
...@@ -41,17 +41,17 @@ public class DependencyCustomizer { ...@@ -41,17 +41,17 @@ public class DependencyCustomizer {
private final ClassNode classNode; private final ClassNode classNode;
private final ArtifactCoordinatesResolver artifactCoordinatesResolver; private final ArtifactCoordinatesResolver coordinatesResolver;
/** /**
* Create a new {@link DependencyCustomizer} instance. * Create a new {@link DependencyCustomizer} instance.
* @param loader * @param loader
*/ */
public DependencyCustomizer(GroovyClassLoader loader, ModuleNode moduleNode, public DependencyCustomizer(GroovyClassLoader loader, ModuleNode moduleNode,
ArtifactCoordinatesResolver artifactCoordinatesResolver) { ArtifactCoordinatesResolver coordinatesResolver) {
this.loader = loader; this.loader = loader;
this.classNode = moduleNode.getClasses().get(0); this.classNode = moduleNode.getClasses().get(0);
this.artifactCoordinatesResolver = artifactCoordinatesResolver; this.coordinatesResolver = coordinatesResolver;
} }
/** /**
...@@ -61,7 +61,7 @@ public class DependencyCustomizer { ...@@ -61,7 +61,7 @@ public class DependencyCustomizer {
protected DependencyCustomizer(DependencyCustomizer parent) { protected DependencyCustomizer(DependencyCustomizer parent) {
this.loader = parent.loader; this.loader = parent.loader;
this.classNode = parent.classNode; this.classNode = parent.classNode;
this.artifactCoordinatesResolver = parent.artifactCoordinatesResolver; this.coordinatesResolver = parent.coordinatesResolver;
} }
public String getVersion(String artifactId) { public String getVersion(String artifactId) {
...@@ -70,7 +70,7 @@ public class DependencyCustomizer { ...@@ -70,7 +70,7 @@ public class DependencyCustomizer {
} }
public String getVersion(String artifactId, String defaultVersion) { public String getVersion(String artifactId, String defaultVersion) {
String version = this.artifactCoordinatesResolver.getVersion(artifactId); String version = this.coordinatesResolver.getVersion(artifactId);
if (version == null) { if (version == null) {
version = defaultVersion; version = defaultVersion;
} }
...@@ -184,8 +184,8 @@ public class DependencyCustomizer { ...@@ -184,8 +184,8 @@ public class DependencyCustomizer {
* @return this {@link DependencyCustomizer} for continued use * @return this {@link DependencyCustomizer} for continued use
*/ */
public DependencyCustomizer add(String module) { public DependencyCustomizer add(String module) {
return this.add(this.artifactCoordinatesResolver.getGroupId(module), module, return this.add(this.coordinatesResolver.getGroupId(module), module,
this.artifactCoordinatesResolver.getVersion(module), true); this.coordinatesResolver.getVersion(module), true);
} }
/** /**
...@@ -198,8 +198,8 @@ public class DependencyCustomizer { ...@@ -198,8 +198,8 @@ public class DependencyCustomizer {
* @return this {@link DependencyCustomizer} for continued use * @return this {@link DependencyCustomizer} for continued use
*/ */
public DependencyCustomizer add(String module, boolean transitive) { public DependencyCustomizer add(String module, boolean transitive) {
return this.add(this.artifactCoordinatesResolver.getGroupId(module), module, return this.add(this.coordinatesResolver.getGroupId(module), module,
this.artifactCoordinatesResolver.getVersion(module), transitive); this.coordinatesResolver.getVersion(module), transitive);
} }
private DependencyCustomizer add(String group, String module, String version, private DependencyCustomizer add(String group, String module, String version,
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
package org.springframework.boot.cli.compiler; package org.springframework.boot.cli.compiler;
import groovy.grape.GrapeEngine; import groovy.grape.GrapeEngine;
import groovy.lang.Grab;
import groovy.lang.GroovyClassLoader; import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyClassLoader.ClassCollector; import groovy.lang.GroovyClassLoader.ClassCollector;
...@@ -34,14 +33,7 @@ import java.util.List; ...@@ -34,14 +33,7 @@ import java.util.List;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ImportNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.classgen.GeneratorContext; import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.control.CompilationFailedException; import org.codehaus.groovy.control.CompilationFailedException;
import org.codehaus.groovy.control.CompilationUnit; import org.codehaus.groovy.control.CompilationUnit;
...@@ -66,6 +58,7 @@ import org.codehaus.groovy.transform.ASTTransformationVisitor; ...@@ -66,6 +58,7 @@ import org.codehaus.groovy.transform.ASTTransformationVisitor;
* *
* <li>Generated class files can also be loaded using * <li>Generated class files can also be loaded using
* {@link ClassLoader#getResource(String)}</li> * {@link ClassLoader#getResource(String)}</li>
*
* <ul> * <ul>
* *
* @author Phillip Webb * @author Phillip Webb
...@@ -77,32 +70,45 @@ public class GroovyCompiler { ...@@ -77,32 +70,45 @@ public class GroovyCompiler {
private static final ClassLoader AETHER_CLASS_LOADER = new URLClassLoader( private static final ClassLoader AETHER_CLASS_LOADER = new URLClassLoader(
new URL[] { GroovyCompiler.class.getResource("/internal/") }); new URL[] { GroovyCompiler.class.getResource("/internal/") });
private GroovyCompilerConfiguration configuration; private final GroovyCompilerConfiguration configuration;
private ExtendedGroovyClassLoader loader; private final ExtendedGroovyClassLoader loader;
private ArtifactCoordinatesResolver artifactCoordinatesResolver; private final ArtifactCoordinatesResolver coordinatesResolver;
private final ASTTransformation dependencyCustomizerTransformation = new DependencyCustomizerAstTransformation(); private final ServiceLoader<CompilerAutoConfiguration> compilerAutoConfigurations;
private final ASTTransformation dependencyCoordinatesTransformation = new DefaultDependencyCoordinatesAstTransformation(); private final List<ASTTransformation> transformations;
/** /**
* Create a new {@link GroovyCompiler} instance. * Create a new {@link GroovyCompiler} instance.
* @param configuration the compiler configuration * @param configuration the compiler configuration
*/ */
@SuppressWarnings("unchecked")
public GroovyCompiler(final GroovyCompilerConfiguration configuration) { public GroovyCompiler(final GroovyCompilerConfiguration configuration) {
this.configuration = configuration; this.configuration = configuration;
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
this.loader = new ExtendedGroovyClassLoader(getClass().getClassLoader(), this.loader = new ExtendedGroovyClassLoader(getClass().getClassLoader(),
compilerConfiguration); new CompilerConfiguration());
if (configuration.getClasspath().length() > 0) { if (configuration.getClasspath().length() > 0) {
this.loader.addClasspath(configuration.getClasspath()); this.loader.addClasspath(configuration.getClasspath());
} }
this.artifactCoordinatesResolver = new PropertiesArtifactCoordinatesResolver( this.coordinatesResolver = new PropertiesArtifactCoordinatesResolver(this.loader);
this.loader); installGrapeEngine();
this.loader.getConfiguration().addCompilationCustomizers(
new CompilerAutoConfigureCustomizer());
this.compilerAutoConfigurations = ServiceLoader.load(
CompilerAutoConfiguration.class, GroovyCompiler.class.getClassLoader());
this.transformations = new ArrayList<ASTTransformation>();
this.transformations.add(new DependencyAutoConfigurationTransformation(this.loader,
this.coordinatesResolver, this.compilerAutoConfigurations));
if (this.configuration.isGuessDependencies()) {
this.transformations.add(new ResolveDependencyCoordinatesTransformation(
this.coordinatesResolver));
}
}
@SuppressWarnings("unchecked")
private void installGrapeEngine() {
try { try {
Class<GrapeEngine> grapeEngineClass = (Class<GrapeEngine>) AETHER_CLASS_LOADER Class<GrapeEngine> grapeEngineClass = (Class<GrapeEngine>) AETHER_CLASS_LOADER
.loadClass("org.springframework.boot.cli.compiler.AetherGrapeEngine"); .loadClass("org.springframework.boot.cli.compiler.AetherGrapeEngine");
...@@ -110,16 +116,13 @@ public class GroovyCompiler { ...@@ -110,16 +116,13 @@ public class GroovyCompiler {
GroovyClassLoader.class, String.class, String.class, String.class); GroovyClassLoader.class, String.class, String.class, String.class);
GrapeEngine grapeEngine = constructor.newInstance(this.loader, GrapeEngine grapeEngine = constructor.newInstance(this.loader,
"org.springframework.boot", "spring-boot-starter-parent", "org.springframework.boot", "spring-boot-starter-parent",
this.artifactCoordinatesResolver.getVersion("spring-boot")); this.coordinatesResolver.getVersion("spring-boot"));
new GrapeEngineInstaller(grapeEngine).install(); new GrapeEngineInstaller(grapeEngine).install();
} }
catch (Exception ex) { catch (Exception ex) {
throw new IllegalStateException("Failed to install custom GrapeEngine", ex); throw new IllegalStateException("Failed to install custom GrapeEngine", ex);
} }
compilerConfiguration
.addCompilationCustomizers(new CompilerAutoConfigureCustomizer());
} }
public void addCompilationCustomizers(CompilationCustomizer... customizers) { public void addCompilationCustomizers(CompilationCustomizer... customizers) {
...@@ -157,12 +160,12 @@ public class GroovyCompiler { ...@@ -157,12 +160,12 @@ public class GroovyCompiler {
this.loader.clearCache(); this.loader.clearCache();
List<Class<?>> classes = new ArrayList<Class<?>>(); List<Class<?>> classes = new ArrayList<Class<?>>();
CompilerConfiguration compilerConfiguration = this.loader.getConfiguration(); CompilerConfiguration configuration = this.loader.getConfiguration();
final CompilationUnit compilationUnit = new CompilationUnit( CompilationUnit compilationUnit = new CompilationUnit(configuration, null,
compilerConfiguration, null, this.loader); this.loader);
SourceUnit sourceUnit = new SourceUnit(file[0], compilerConfiguration, SourceUnit sourceUnit = new SourceUnit(file[0], configuration, this.loader,
this.loader, compilationUnit.getErrorCollector()); compilationUnit.getErrorCollector());
ClassCollector collector = this.loader.createCollector(compilationUnit, ClassCollector collector = this.loader.createCollector(compilationUnit,
sourceUnit); sourceUnit);
compilationUnit.setClassgenCallback(collector); compilationUnit.setClassgenCallback(collector);
...@@ -189,18 +192,23 @@ public class GroovyCompiler { ...@@ -189,18 +192,23 @@ public class GroovyCompiler {
} }
return classes.toArray(new Class<?>[classes.size()]); return classes.toArray(new Class<?>[classes.size()]);
}
@SuppressWarnings("rawtypes")
private void addAstTransformations(CompilationUnit compilationUnit) {
LinkedList[] phaseOperations = getPhaseOperations(compilationUnit);
processConversionOperations(phaseOperations[Phases.CONVERSION]);
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private void addAstTransformations(final CompilationUnit compilationUnit) { private LinkedList[] getPhaseOperations(final CompilationUnit compilationUnit) {
try { try {
Field field = CompilationUnit.class.getDeclaredField("phaseOperations"); Field field = CompilationUnit.class.getDeclaredField("phaseOperations");
field.setAccessible(true); field.setAccessible(true);
LinkedList[] phaseOperations = (LinkedList[]) field.get(compilationUnit); LinkedList[] phaseOperations = (LinkedList[]) field.get(compilationUnit);
processConversionOperations(phaseOperations[Phases.CONVERSION]); return phaseOperations;
} }
catch (Exception npe) { catch (Exception ex) {
throw new IllegalStateException( throw new IllegalStateException(
"Phase operations not available from compilation unit"); "Phase operations not available from compilation unit");
} }
...@@ -208,24 +216,26 @@ public class GroovyCompiler { ...@@ -208,24 +216,26 @@ public class GroovyCompiler {
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
private void processConversionOperations(LinkedList conversionOperations) { private void processConversionOperations(LinkedList conversionOperations) {
for (int i = 0; i < conversionOperations.size(); i++) { int index = getIndexOfASTTransformationVisitor(conversionOperations);
Object operation = conversionOperations.get(i); conversionOperations.add(index, new CompilationUnit.SourceUnitOperation() {
@Override
public void call(SourceUnit source) throws CompilationFailedException {
ASTNode[] nodes = new ASTNode[] { source.getAST() };
for (ASTTransformation transformation : GroovyCompiler.this.transformations) {
transformation.visit(nodes, source);
}
}
});
}
if (operation.getClass().getName() private int getIndexOfASTTransformationVisitor(LinkedList<?> conversionOperations) {
for (int index = 0; index < conversionOperations.size(); index++) {
if (conversionOperations.get(index).getClass().getName()
.startsWith(ASTTransformationVisitor.class.getName())) { .startsWith(ASTTransformationVisitor.class.getName())) {
conversionOperations.add(i, new CompilationUnit.SourceUnitOperation() { return index;
@Override
public void call(SourceUnit source) throws CompilationFailedException {
ASTNode[] astNodes = new ASTNode[] { source.getAST() };
GroovyCompiler.this.dependencyCustomizerTransformation.visit(
astNodes, source);
GroovyCompiler.this.dependencyCoordinatesTransformation.visit(
astNodes, source);
}
});
break;
} }
} }
return conversionOperations.size();
} }
/** /**
...@@ -243,12 +253,8 @@ public class GroovyCompiler { ...@@ -243,12 +253,8 @@ public class GroovyCompiler {
ImportCustomizer importCustomizer = new ImportCustomizer(); ImportCustomizer importCustomizer = new ImportCustomizer();
ServiceLoader<CompilerAutoConfiguration> customizers = ServiceLoader.load(
CompilerAutoConfiguration.class,
GroovyCompiler.class.getClassLoader());
// Additional auto configuration // Additional auto configuration
for (CompilerAutoConfiguration autoConfiguration : customizers) { for (CompilerAutoConfiguration autoConfiguration : GroovyCompiler.this.compilerAutoConfigurations) {
if (autoConfiguration.matches(classNode)) { if (autoConfiguration.matches(classNode)) {
if (GroovyCompiler.this.configuration.isGuessImports()) { if (GroovyCompiler.this.configuration.isGuessImports()) {
autoConfiguration.applyImports(importCustomizer); autoConfiguration.applyImports(importCustomizer);
...@@ -270,134 +276,4 @@ public class GroovyCompiler { ...@@ -270,134 +276,4 @@ public class GroovyCompiler {
} }
} }
private class DependencyCustomizerAstTransformation implements ASTTransformation {
@Override
public void visit(ASTNode[] nodes, SourceUnit source) {
ServiceLoader<CompilerAutoConfiguration> customizers = ServiceLoader.load(
CompilerAutoConfiguration.class,
GroovyCompiler.class.getClassLoader());
for (ASTNode astNode : nodes) {
if (astNode instanceof ModuleNode) {
ModuleNode module = (ModuleNode) astNode;
DependencyCustomizer dependencyCustomizer = new DependencyCustomizer(
GroovyCompiler.this.loader, module,
GroovyCompiler.this.artifactCoordinatesResolver);
ClassNode firstClass = null;
for (ClassNode classNode : module.getClasses()) {
if (firstClass == null) {
firstClass = classNode;
}
for (CompilerAutoConfiguration autoConfiguration : customizers) {
if (autoConfiguration.matches(classNode)) {
if (GroovyCompiler.this.configuration
.isGuessDependencies()) {
autoConfiguration
.applyDependencies(dependencyCustomizer);
}
}
}
}
}
}
}
}
private class DefaultDependencyCoordinatesAstTransformation implements
ASTTransformation {
@Override
public void visit(ASTNode[] nodes, final SourceUnit source) {
for (ASTNode node : nodes) {
if (node instanceof ModuleNode) {
ModuleNode module = (ModuleNode) node;
for (ImportNode importNode : module.getImports()) {
visitAnnotatedNode(importNode);
}
for (ClassNode classNode : module.getClasses()) {
visitAnnotatedNode(classNode);
classNode.visitContents(new ClassCodeVisitorSupport() {
@Override
protected SourceUnit getSourceUnit() {
return source;
}
@Override
public void visitAnnotations(AnnotatedNode node) {
visitAnnotatedNode(node);
}
});
}
}
}
}
private void visitAnnotatedNode(AnnotatedNode annotatedNode) {
for (AnnotationNode annotationNode : annotatedNode.getAnnotations()) {
if (isGrabAnnotation(annotationNode)) {
transformGrabAnnotation(annotationNode);
}
}
}
private boolean isGrabAnnotation(AnnotationNode annotationNode) {
String annotationClassName = annotationNode.getClassNode().getName();
return annotationClassName.equals(Grab.class.getName())
|| annotationClassName.equals(Grab.class.getSimpleName());
}
private void transformGrabAnnotation(AnnotationNode grabAnnotation) {
grabAnnotation.setMember("initClass", new ConstantExpression(false));
Expression valueExpression = grabAnnotation.getMember("value");
String value = null;
if (valueExpression instanceof ConstantExpression) {
ConstantExpression constantExpression = (ConstantExpression) valueExpression;
Object valueObject = constantExpression.getValue();
if (valueObject instanceof String) {
value = (String) valueObject;
if (isConvenienceForm(value)) {
return;
}
}
}
applyGroupAndVersion(grabAnnotation, value);
}
private boolean isConvenienceForm(String value) {
return value.contains(":") || value.contains("#");
}
private void applyGroupAndVersion(AnnotationNode grabAnnotation, String module) {
if (module != null) {
grabAnnotation.setMember("module", new ConstantExpression(module));
}
else {
module = (String) ((ConstantExpression) grabAnnotation.getMembers().get(
"module")).getValue();
}
if (grabAnnotation.getMember("group") == null) {
ConstantExpression groupIdExpression = new ConstantExpression(
GroovyCompiler.this.artifactCoordinatesResolver
.getGroupId(module));
grabAnnotation.setMember("group", groupIdExpression);
}
if (grabAnnotation.getMember("version") == null) {
ConstantExpression versionExpression = new ConstantExpression(
GroovyCompiler.this.artifactCoordinatesResolver
.getVersion(module));
grabAnnotation.setMember("version", versionExpression);
}
}
}
} }
/*
* Copyright 2012-2013 the original author or authors.
*
* 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 org.springframework.boot.cli.compiler;
import groovy.lang.Grab;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ImportNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.transform.ASTTransformation;
/**
* {@link ASTTransformation} to resolve {@link Grab} artifact coordinates.
* @author Andy Wilkinson
* @author Phillip Webb
*/
class ResolveDependencyCoordinatesTransformation implements ASTTransformation {
private static final Set<String> GRAB_ANNOTATION_NAMES = Collections
.unmodifiableSet(new HashSet<String>(Arrays.asList(Grab.class.getName(),
Grab.class.getSimpleName())));
private final ArtifactCoordinatesResolver coordinatesResolver;
ResolveDependencyCoordinatesTransformation(
ArtifactCoordinatesResolver coordinatesResolver) {
this.coordinatesResolver = coordinatesResolver;
}
@Override
public void visit(ASTNode[] nodes, SourceUnit source) {
ClassVisitor classVisitor = new ClassVisitor(source);
for (ASTNode node : nodes) {
if (node instanceof ModuleNode) {
ModuleNode module = (ModuleNode) node;
for (ImportNode importNode : module.getImports()) {
visitAnnotatedNode(importNode);
}
for (ClassNode classNode : module.getClasses()) {
visitAnnotatedNode(classNode);
classNode.visitContents(classVisitor);
}
}
}
}
private void visitAnnotatedNode(AnnotatedNode annotatedNode) {
for (AnnotationNode annotationNode : annotatedNode.getAnnotations()) {
if (GRAB_ANNOTATION_NAMES.contains(annotationNode.getClassNode().getName())) {
transformGrabAnnotation(annotationNode);
}
}
}
private void transformGrabAnnotation(AnnotationNode grabAnnotation) {
grabAnnotation.setMember("initClass", new ConstantExpression(false));
String value = getValue(grabAnnotation);
if (value != null && !isConvenienceForm(value)) {
applyGroupAndVersion(grabAnnotation, value);
}
}
private String getValue(AnnotationNode annotation) {
Expression expression = annotation.getMember("value");
if (expression instanceof ConstantExpression) {
Object value = ((ConstantExpression) expression).getValue();
return (value instanceof String ? (String) value : null);
}
return null;
}
private boolean isConvenienceForm(String value) {
return value.contains(":") || value.contains("#");
}
private void applyGroupAndVersion(AnnotationNode annotation, String module) {
if (module != null) {
setMember(annotation, "module", module);
}
else {
Expression expression = annotation.getMembers().get("module");
module = (String) ((ConstantExpression) expression).getValue();
}
if (annotation.getMember("group") == null) {
setMember(annotation, "group", this.coordinatesResolver.getGroupId(module));
}
if (annotation.getMember("version") == null) {
setMember(annotation, "version", this.coordinatesResolver.getVersion(module));
}
}
private void setMember(AnnotationNode annotation, String name, String value) {
ConstantExpression expression = new ConstantExpression(value);
annotation.setMember(name, expression);
}
private class ClassVisitor extends ClassCodeVisitorSupport {
private final SourceUnit source;
public ClassVisitor(SourceUnit source) {
this.source = source;
}
@Override
protected SourceUnit getSourceUnit() {
return this.source;
}
@Override
public void visitAnnotations(AnnotatedNode node) {
visitAnnotatedNode(node);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment