Skip to content

Commit f756ba4

Browse files
committed
Implement generateAspectImplementationStub Maven goal
1 parent 5417e82 commit f756ba4

22 files changed

+602
-107
lines changed

core/esmf-aspect-model-generator/src/main/java/org/eclipse/esmf/aspectmodel/generator/Generator.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.function.Function;
2020
import java.util.stream.Stream;
2121

22+
import org.eclipse.esmf.functions.ThrowingFunction;
2223
import org.eclipse.esmf.metamodel.ModelElement;
2324

2425
import lombok.Getter;
@@ -62,6 +63,16 @@ public void generate( final Function<I, OutputStream> nameMapper ) {
6263
generate().toList().forEach( generationResult -> write( generationResult, nameMapper ) );
6364
}
6465

66+
/**
67+
* Similar to {@link #generate(Function)}, except the name mapper function can also write an exception
68+
*
69+
* @param nameMapper the callback function that maps artifact identifiers to OutputStreams
70+
* @param <E> the type of exception that can be thrown by the name mapper
71+
*/
72+
public <E extends Throwable> void generateThrowing( final ThrowingFunction<I, OutputStream, E> nameMapper ) {
73+
generate().toList().forEach( generationResult -> writeThrowing( generationResult, nameMapper ) );
74+
}
75+
6576
/**
6677
* Generates artifacts for the given Aspect model
6778
*
@@ -103,4 +114,20 @@ protected void write( final Artifact<I, T> artifact, final Function<I, OutputStr
103114
LOG.error( "Failure during writing of generated artifact", exception );
104115
}
105116
}
117+
118+
/**
119+
* Writes an artifact to the corresponding output stream
120+
*
121+
* @param artifact the artifact
122+
* @param nameMapper the function that provides the output stream for the artifact
123+
*/
124+
protected <E extends Throwable> void writeThrowing( final Artifact<I, T> artifact,
125+
final ThrowingFunction<I, OutputStream, E> nameMapper ) {
126+
try ( final OutputStream output = nameMapper.apply( artifact.getId() ) ) {
127+
output.write( artifact.serialize() );
128+
output.flush();
129+
} catch ( final Throwable exception ) {
130+
LOG.error( "Failure during writing of generated artifact", exception );
131+
}
132+
}
106133
}

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
<!-- Dependency version overrides -->
8484
<log4j-version>2.22.1</log4j-version>
8585
<wagon-maven-plugin-version>1.0</wagon-maven-plugin-version>
86+
<mojo-executor-version>2.4.0</mojo-executor-version>
8687
</properties>
8788

8889
<dependencyManagement>
@@ -208,6 +209,11 @@
208209
<artifactId>log4j-core</artifactId>
209210
<version>${log4j-version}</version>
210211
</dependency>
212+
<dependency>
213+
<groupId>org.twdata.maven</groupId>
214+
<artifactId>mojo-executor</artifactId>
215+
<version>${mojo-executor-version}</version>
216+
</dependency>
211217
</dependencies>
212218
</dependencyManagement>
213219

tools/esmf-aspect-model-maven-plugin/pom.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@
5151
<version>${maven-plugin-dependencies-version}</version>
5252
<scope>provided</scope>
5353
</dependency>
54+
<dependency>
55+
<groupId>org.twdata.maven</groupId>
56+
<artifactId>mojo-executor</artifactId>
57+
</dependency>
58+
<dependency>
59+
<groupId>io.soabase.record-builder</groupId>
60+
<artifactId>record-builder-processor</artifactId>
61+
<scope>provided</scope>
62+
</dependency>
5463

5564
<dependency>
5665
<groupId>org.eclipse.esmf</groupId>
@@ -88,6 +97,20 @@
8897

8998
<build>
9099
<plugins>
100+
<plugin>
101+
<groupId>org.apache.maven.plugins</groupId>
102+
<artifactId>maven-compiler-plugin</artifactId>
103+
<configuration>
104+
<annotationProcessorPaths>
105+
<path>
106+
<groupId>io.soabase.record-builder</groupId>
107+
<artifactId>record-builder-processor</artifactId>
108+
<version>${record-builder-version}</version>
109+
</path>
110+
</annotationProcessorPaths>
111+
</configuration>
112+
</plugin>
113+
91114
<plugin>
92115
<groupId>org.apache.maven.plugins</groupId>
93116
<artifactId>maven-plugin-plugin</artifactId>

tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/AspectModelMojo.java

Lines changed: 85 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@
1313

1414
package org.eclipse.esmf.aspectmodel;
1515

16+
import static java.lang.String.format;
17+
18+
import java.io.File;
19+
import java.io.FileInputStream;
1620
import java.io.FileOutputStream;
1721
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.nio.charset.StandardCharsets;
1824
import java.nio.file.Files;
1925
import java.nio.file.Path;
2026
import java.util.ArrayList;
@@ -42,7 +48,15 @@
4248
import org.eclipse.esmf.metamodel.Aspect;
4349
import org.eclipse.esmf.metamodel.AspectModel;
4450

51+
import com.fasterxml.jackson.databind.ObjectMapper;
52+
import com.fasterxml.jackson.databind.node.ObjectNode;
53+
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
54+
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
4555
import io.vavr.control.Either;
56+
import io.vavr.control.Try;
57+
import org.apache.commons.io.FilenameUtils;
58+
import org.apache.commons.io.IOUtils;
59+
import org.apache.commons.lang3.StringUtils;
4660
import org.apache.maven.execution.MavenSession;
4761
import org.apache.maven.plugin.AbstractMojo;
4862
import org.apache.maven.plugin.MojoExecutionException;
@@ -53,29 +67,41 @@
5367
import org.codehaus.plexus.util.xml.Xpp3Dom;
5468

5569
public abstract class AspectModelMojo extends AbstractMojo {
56-
@Parameter( defaultValue = "${basedir}" )
57-
private String basedir;
70+
protected static final ObjectMapper YAML_MAPPER = new YAMLMapper().enable( YAMLGenerator.Feature.MINIMIZE_QUOTES );
71+
protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
5872

5973
@Parameter
60-
private String modelsRootDirectory;
74+
protected String modelsRootDirectory;
6175

6276
@Parameter( required = true, property = "include" )
6377
protected Set<String> includes;
6478

6579
@Parameter
6680
protected String outputDirectory = "";
6781

82+
@Parameter
83+
protected String generatedSourcesDirectory = "";
84+
6885
@Parameter( defaultValue = "false" )
6986
protected boolean detailedValidationMessages;
7087

7188
@Parameter
7289
protected String githubServerId;
7390

7491
@Parameter( defaultValue = "${session}", readonly = true )
75-
private MavenSession session;
92+
protected MavenSession mavenSession;
7693

7794
protected GithubModelSourceConfig gitHubConfig;
7895

96+
private Map<AspectModel, Aspect> aspects;
97+
98+
public AspectModelMojo() {
99+
}
100+
101+
protected AspectModelMojo( final Map<AspectModel, Aspect> aspects ) {
102+
this.aspects = aspects;
103+
}
104+
79105
/**
80106
* Skip the execution.
81107
*/
@@ -97,6 +123,9 @@ protected Set<AspectModel> loadModels() throws MojoExecutionException {
97123
}
98124

99125
private Map<AspectModel, Aspect> loadAspectModels() throws MojoExecutionException {
126+
if ( aspects != null ) {
127+
return aspects;
128+
}
100129
final List<ResolutionStrategy> strategies = new ArrayList<>();
101130
if ( modelsRootDirectory != null ) {
102131
final Path modelsRoot = Path.of( modelsRootDirectory );
@@ -110,7 +139,7 @@ private Map<AspectModel, Aspect> loadAspectModels() throws MojoExecutionExceptio
110139
"Neither modelsRootDirectory nor gitHubServerId were configured, don't know how to resolve Aspect Models" );
111140
}
112141

113-
final Map<AspectModel, Aspect> result = new HashMap<>();
142+
aspects = new HashMap<>();
114143

115144
final AspectModelLoader aspectModelLoader = new AspectModelLoader( strategies );
116145
for ( final String inputUrn : includes ) {
@@ -129,18 +158,27 @@ private Map<AspectModel, Aspect> loadAspectModels() throws MojoExecutionExceptio
129158
.filter( theAspect -> theAspect.urn().equals( urn ) )
130159
.findFirst()
131160
.orElseThrow( () -> new MojoExecutionException( "Loaded Aspect Model does not contain Aspect " + urn ) );
132-
result.put( aspectModel, aspect );
161+
aspects.put( aspectModel, aspect );
133162
}
134-
return result;
163+
return aspects;
135164
}
136165

137-
protected FileOutputStream getOutputStreamForFile( final String artifactName, final String outputDirectory ) {
166+
protected File getOutFile( final String artifactName, final String outputDirectory ) throws MojoExecutionException {
138167
try {
139168
final Path outputPath = Path.of( outputDirectory );
140169
Files.createDirectories( outputPath );
141-
return new FileOutputStream( outputPath.resolve( artifactName ).toFile() );
170+
return outputPath.resolve( artifactName ).toFile();
171+
} catch ( final IOException exception ) {
172+
throw new MojoExecutionException( "Could not create missing directories for path " + outputDirectory );
173+
}
174+
}
175+
176+
protected FileOutputStream getOutputStreamForFile( final String artifactName, final String outputDirectory )
177+
throws MojoExecutionException {
178+
try {
179+
return new FileOutputStream( getOutFile( artifactName, outputDirectory ) );
142180
} catch ( final IOException exception ) {
143-
throw new RuntimeException( "Could not write to output " + outputDirectory );
181+
throw new MojoExecutionException( "Could not write to output " + outputDirectory );
144182
}
145183
}
146184

@@ -152,10 +190,10 @@ public void execute() throws MojoExecutionException, MojoFailureException {
152190
}
153191

154192
if ( githubServerId != null ) {
155-
if ( session == null ) {
193+
if ( mavenSession == null ) {
156194
getLog().warn( "Could not read Maven session, ignoring GitHub server configuration." );
157195
} else {
158-
final Server server = session.getSettings().getServer( githubServerId );
196+
final Server server = mavenSession.getSettings().getServer( githubServerId );
159197
if ( server != null ) {
160198
final Xpp3Dom dom = (Xpp3Dom) server.getConfiguration();
161199
final String[] repositoryParts = Optional.ofNullable( dom.getChild( "repository" ) )
@@ -177,7 +215,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
177215
.map( GithubRepository.Tag::new ) )
178216
.orElse( new GithubRepository.Branch( "main" ) );
179217

180-
final List<Proxy> proxies = session.getSettings().getProxies();
218+
final List<Proxy> proxies = mavenSession.getSettings().getProxies();
181219
final ProxyConfig proxyConfig = Optional.ofNullable( proxies ).stream().flatMap( Collection::stream )
182220
.filter( proxy -> proxy.getProtocol().equals( "https" ) )
183221
.findFirst()
@@ -203,4 +241,38 @@ public void execute() throws MojoExecutionException, MojoFailureException {
203241
}
204242

205243
abstract void executeGeneration() throws MojoExecutionException, MojoFailureException;
244+
245+
protected ObjectNode readFile( final String file ) throws MojoExecutionException {
246+
if ( StringUtils.isBlank( file ) ) {
247+
return null;
248+
}
249+
final String extension = FilenameUtils.getExtension( file ).toUpperCase();
250+
final Try<String> fileData = Try.of( () -> getFileAsString( file ) ).mapTry( Optional::get );
251+
return switch ( extension ) {
252+
case "YAML", "YML" -> (ObjectNode) fileData
253+
.mapTry( data -> YAML_MAPPER.readValue( data, Object.class ) )
254+
.mapTry( OBJECT_MAPPER::writeValueAsString )
255+
.mapTry( OBJECT_MAPPER::readTree )
256+
.get();
257+
case "JSON" -> (ObjectNode) fileData
258+
.mapTry( OBJECT_MAPPER::readTree )
259+
.get();
260+
default -> throw new MojoExecutionException( format( "File extension [%s] not supported.", extension ) );
261+
};
262+
}
263+
264+
private static Optional<String> getFileAsString( final String filePath ) throws MojoExecutionException {
265+
if ( filePath == null || filePath.isEmpty() ) {
266+
return Optional.empty();
267+
}
268+
final File f = new File( filePath );
269+
if ( f.exists() && !f.isDirectory() ) {
270+
try ( final InputStream inputStream = new FileInputStream( filePath ) ) {
271+
return Optional.of( IOUtils.toString( inputStream, StandardCharsets.UTF_8 ) );
272+
} catch ( final IOException e ) {
273+
throw new MojoExecutionException( format( "Could not load file %s.", filePath ), e );
274+
}
275+
}
276+
throw new MojoExecutionException( format( "File does not exist %s.", filePath ) );
277+
}
206278
}

tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/CodeGenerationMojo.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,16 @@
1515

1616
import java.io.File;
1717
import java.io.OutputStream;
18-
import java.util.function.Function;
1918

2019
import org.eclipse.esmf.aspectmodel.java.QualifiedName;
2120
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
21+
import org.eclipse.esmf.functions.ThrowingFunction;
2222
import org.eclipse.esmf.metamodel.Aspect;
2323

2424
import org.apache.maven.plugin.MojoExecutionException;
2525
import org.apache.maven.plugins.annotations.Parameter;
2626

2727
public abstract class CodeGenerationMojo extends AspectModelMojo {
28-
2928
@Parameter
3029
protected String packageName = "";
3130

@@ -51,13 +50,15 @@ protected void validateParameters( final File templateLibFile ) throws MojoExecu
5150
super.validateParameters();
5251
}
5352

54-
protected final Function<QualifiedName, OutputStream> nameMapper = artifact -> {
55-
final String path = artifact.getPackageName();
56-
final String fileName = artifact.getClassName();
57-
final String outputDirectoryForArtifact = outputDirectory + File.separator + path.replace( '.', File.separatorChar );
58-
final String artifactName = fileName + ".java";
59-
return getOutputStreamForFile( artifactName, outputDirectoryForArtifact );
60-
};
53+
protected ThrowingFunction<QualifiedName, OutputStream, MojoExecutionException> javaFileNameMapper( final String outputPath ) {
54+
return artifact -> {
55+
final String path = artifact.getPackageName();
56+
final String fileName = artifact.getClassName();
57+
final String outputDirectoryForArtifact = outputPath + File.separator + path.replace( '.', File.separatorChar );
58+
final String artifactName = fileName + ".java";
59+
return getOutputStreamForFile( artifactName, outputDirectoryForArtifact );
60+
};
61+
}
6162

6263
protected String determinePackageName( final Aspect aspect ) {
6364
if ( packageName == null || packageName.isEmpty() ) {

tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateAspectFromAas.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
import org.apache.maven.plugins.annotations.LifecyclePhase;
3030
import org.apache.maven.plugins.annotations.Mojo;
3131

32-
@Mojo( name = "generateAspectFromAas", defaultPhase = LifecyclePhase.GENERATE_RESOURCES )
32+
@Mojo( name = GenerateAspectFromAas.MAVEN_GOAL, defaultPhase = LifecyclePhase.GENERATE_RESOURCES )
3333
public class GenerateAspectFromAas extends AspectModelMojo {
34+
public static final String MAVEN_GOAL = "generateAspectFromAas";
35+
3436
@Override
3537
public void executeGeneration() throws MojoExecutionException, MojoFailureException {
3638
validateParameters();

0 commit comments

Comments
 (0)